| /* |
| * 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 "GrRenderTargetContext.h" |
| #include "GrStyle.h" |
| #include "SkDrawFilter.h" |
| #include "SkOpts.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 GrOpList::drawPath). |
| */ |
| class GrStencilAndCoverTextContext { |
| public: |
| static GrStencilAndCoverTextContext* Create(GrAtlasTextContext* fallbackTextContext); |
| |
| void drawText(GrContext*, GrRenderTargetContext* rtc, |
| 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*, GrRenderTargetContext*, |
| 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*, GrRenderTargetContext*, const GrClip&, const SkPaint&, |
| const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*, |
| SkScalar x, SkScalar y, |
| SkDrawFilter*, const SkIRect& clipBounds); |
| |
| virtual ~GrStencilAndCoverTextContext(); |
| |
| private: |
| GrStencilAndCoverTextContext(GrAtlasTextContext* fallbackTextContext); |
| |
| bool canDraw(const SkPaint& skPaint, const SkMatrix&) { |
| return this->internalCanDraw(skPaint); |
| } |
| |
| bool internalCanDraw(const SkPaint&); |
| |
| void uncachedDrawTextBlob(GrContext*, GrRenderTargetContext* rtc, |
| 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*, GrRenderTargetContext*, const GrPaint&, const GrClip&, |
| const SkMatrix&, const SkSurfaceProps&, |
| SkScalar x, SkScalar y, const SkIRect& clipBounds, |
| GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const; |
| |
| void releaseGlyphCache() const; |
| |
| size_t computeSizeInCache() const; |
| |
| GrAA isAntiAlias() const { return fFont.isAntiAlias() ? GrAA::kYes : GrAA::kNo; } |
| |
| private: |
| typedef GrDrawPathRangeBatch::InstanceData InstanceData; |
| |
| SkGlyphCache* getGlyphCache() const; |
| GrPathRange* createGlyphs(GrContext*) const; |
| void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*); |
| |
| GrStyle fStyle; |
| SkPaint fFont; |
| SkScalar fTextRatio; |
| float fTextInverseRatio; |
| bool fUsingRawGlyphPaths; |
| GrUniqueKey fGlyphPathsKey; |
| int fTotalGlyphCount; |
| sk_sp<InstanceData> fInstanceData; |
| int fFallbackGlyphCount; |
| sk_sp<SkTextBlob> fFallbackTextBlob; |
| mutable SkGlyphCache* fDetachedGlyphCache; |
| mutable GrGpuResource::UniqueID 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 SkOpts::hash(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 |