/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrStencilAndCoverTextContext_DEFINED
#define GrStencilAndCoverTextContext_DEFINED
#include "GrDrawTarget.h"
#include "GrStrokeInfo.h"
#include "SkDrawFilter.h"
#include "SkTextBlob.h"
#include "SkTHash.h"
#include "SkTInternalLList.h"
#include "SkTLList.h"
#include "batches/GrDrawPathBatch.h"
class GrAtlasTextContext;
class GrTextStrike;
class GrPath;
class SkSurfaceProps;
/*
* This class implements text rendering using stencil and cover path rendering
* (by the means of GrDrawTarget::drawPath).
*/
class GrStencilAndCoverTextContext {
public:
static GrStencilAndCoverTextContext* Create();
void drawText(GrContext*, GrDrawContext* dc,
const GrClip&, const GrPaint&, const SkPaint&,
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
size_t byteLength, SkScalar x,
SkScalar y, const SkIRect& clipBounds);
void drawPosText(GrContext*, GrDrawContext*,
const GrClip&, const GrPaint&, const SkPaint&,
const SkMatrix& viewMatrix, const SkSurfaceProps&,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& clipBounds);
void drawTextBlob(GrContext*, GrDrawContext*, const GrClip&, const SkPaint&,
const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
SkScalar x, SkScalar y,
SkDrawFilter*, const SkIRect& clipBounds);
virtual ~GrStencilAndCoverTextContext();
private:
GrStencilAndCoverTextContext();
bool canDraw(const SkPaint& skPaint, const SkMatrix&) {
return this->internalCanDraw(skPaint);
}
bool internalCanDraw(const SkPaint&);
void uncachedDrawTextBlob(GrContext*, GrDrawContext* dc,
const GrClip& clip, const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const SkTextBlob* blob,
SkScalar x, SkScalar y,
SkDrawFilter* drawFilter,
const SkIRect& clipBounds);
class FallbackBlobBuilder;
class TextRun {
public:
TextRun(const SkPaint& fontAndStroke);
~TextRun();
void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y);
void setPosText(const char text[], size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset);
void draw(GrContext*, GrDrawContext*, GrPipelineBuilder*, GrColor, const SkMatrix&,
const SkSurfaceProps&,
SkScalar x, SkScalar y, const SkIRect& clipBounds,
GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const;
void releaseGlyphCache() const;
size_t computeSizeInCache() const;
private:
typedef GrDrawPathRangeBatch::InstanceData InstanceData;
SkGlyphCache* getGlyphCache() const;
GrPathRange* createGlyphs(GrContext*) const;
void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*);
GrStrokeInfo fStroke;
SkPaint fFont;
SkScalar fTextRatio;
float fTextInverseRatio;
bool fUsingRawGlyphPaths;
GrUniqueKey fGlyphPathsKey;
int fTotalGlyphCount;
SkAutoTUnref<InstanceData> fInstanceData;
int fFallbackGlyphCount;
SkAutoTUnref<const SkTextBlob> fFallbackTextBlob;
mutable SkGlyphCache* fDetachedGlyphCache;
mutable uint32_t fLastDrawnGlyphsID;
};
// Text blobs/caches.
class TextBlob : public SkTLList<TextRun, 1> {
public:
typedef SkTArray<uint32_t, true> Key;
static const Key& GetKey(const TextBlob* blob) { return blob->key(); }
static uint32_t Hash(const Key& key) {
SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map.
return SkChecksum::Murmur3(key.begin(), sizeof(uint32_t) * key.count());
}
TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint)
: fKey(&blobId, 1) { this->init(skBlob, skPaint); }
TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint)
: fKey(key) {
// 1-length keys are unterstood to be the blob id and must use the other constructor.
SkASSERT(fKey.count() > 1);
this->init(skBlob, skPaint);
}
const Key& key() const { return fKey; }
size_t cpuMemorySize() const { return fCpuMemorySize; }
private:
void init(const SkTextBlob*, const SkPaint&);
const SkSTArray<1, uint32_t, true> fKey;
size_t fCpuMemorySize;
SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
};
const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&);
void purgeToFit(const TextBlob&);
GrAtlasTextContext* fFallbackTextContext;
SkTHashMap<uint32_t, TextBlob*> fBlobIdCache;
SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob> fBlobKeyCache;
SkTInternalLList<TextBlob> fLRUList;
size_t fCacheSize;
};
#endif