kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef GrStencilAndCoverTextContext_DEFINED |
| 9 | #define GrStencilAndCoverTextContext_DEFINED |
| 10 | |
| 11 | #include "GrTextContext.h" |
cdalton | b2808cd | 2014-07-25 14:13:57 -0700 | [diff] [blame] | 12 | #include "GrDrawTarget.h" |
kkinnunen | 50b58e6 | 2015-05-18 23:02:07 -0700 | [diff] [blame] | 13 | #include "GrStrokeInfo.h" |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 14 | #include "SkTHash.h" |
| 15 | #include "SkTInternalLList.h" |
| 16 | #include "SkTLList.h" |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 17 | |
| 18 | class GrTextStrike; |
| 19 | class GrPath; |
robertphillips | fcf7829 | 2015-06-19 11:49:52 -0700 | [diff] [blame] | 20 | class SkSurfaceProps; |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 21 | |
| 22 | /* |
| 23 | * This class implements text rendering using stencil and cover path rendering |
| 24 | * (by the means of GrDrawTarget::drawPath). |
| 25 | * This class exposes the functionality through GrTextContext interface. |
| 26 | */ |
| 27 | class GrStencilAndCoverTextContext : public GrTextContext { |
| 28 | public: |
robertphillips | f6703fa | 2015-09-01 05:36:47 -0700 | [diff] [blame] | 29 | static GrStencilAndCoverTextContext* Create(GrContext*, const SkSurfaceProps&); |
jvanverth | 8c27a18 | 2014-10-14 08:45:50 -0700 | [diff] [blame] | 30 | |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 31 | virtual ~GrStencilAndCoverTextContext(); |
| 32 | |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 33 | private: |
robertphillips | f6703fa | 2015-09-01 05:36:47 -0700 | [diff] [blame] | 34 | GrStencilAndCoverTextContext(GrContext*, const SkSurfaceProps&); |
jvanverth | 8c27a18 | 2014-10-14 08:45:50 -0700 | [diff] [blame] | 35 | |
robertphillips | 6ee690e | 2015-12-02 08:57:50 -0800 | [diff] [blame] | 36 | bool canDraw(const SkPaint& skPaint, const SkMatrix&) override { |
| 37 | return this->internalCanDraw(skPaint); |
| 38 | } |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 39 | |
| 40 | bool internalCanDraw(const SkPaint&); |
jvanverth | 8c27a18 | 2014-10-14 08:45:50 -0700 | [diff] [blame] | 41 | |
robertphillips | 433625e | 2015-12-04 06:58:16 -0800 | [diff] [blame^] | 42 | void onDrawText(GrDrawContext*, const GrClip&, const GrPaint&, const SkPaint&, |
cdalton | e68f736 | 2015-03-25 14:02:37 -0700 | [diff] [blame] | 43 | const SkMatrix& viewMatrix, |
| 44 | const char text[], size_t byteLength, |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 45 | SkScalar x, SkScalar y, const SkIRect& clipBounds) override; |
robertphillips | 433625e | 2015-12-04 06:58:16 -0800 | [diff] [blame^] | 46 | void onDrawPosText(GrDrawContext*, |
robertphillips | f6703fa | 2015-09-01 05:36:47 -0700 | [diff] [blame] | 47 | const GrClip&, const GrPaint&, const SkPaint&, |
cdalton | e68f736 | 2015-03-25 14:02:37 -0700 | [diff] [blame] | 48 | const SkMatrix& viewMatrix, |
| 49 | const char text[], size_t byteLength, |
| 50 | const SkScalar pos[], int scalarsPerPosition, |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 51 | const SkPoint& offset, const SkIRect& clipBounds) override; |
robertphillips | 433625e | 2015-12-04 06:58:16 -0800 | [diff] [blame^] | 52 | void drawTextBlob(GrDrawContext*, const GrClip&, const SkPaint&, |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 53 | const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y, |
| 54 | SkDrawFilter*, const SkIRect& clipBounds) override; |
jvanverth | 8c27a18 | 2014-10-14 08:45:50 -0700 | [diff] [blame] | 55 | |
cdalton | 02015e5 | 2015-10-05 15:28:20 -0700 | [diff] [blame] | 56 | class FallbackBlobBuilder; |
| 57 | |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 58 | class TextRun { |
| 59 | public: |
| 60 | TextRun(const SkPaint& fontAndStroke); |
| 61 | ~TextRun(); |
| 62 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 63 | void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y); |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 64 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 65 | void setPosText(const char text[], size_t byteLength, const SkScalar pos[], |
| 66 | int scalarsPerPosition, const SkPoint& offset); |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 67 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 68 | void draw(GrContext*, GrDrawContext*, GrPipelineBuilder*, GrColor, const SkMatrix&, |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 69 | SkScalar x, SkScalar y, const SkIRect& clipBounds, |
| 70 | GrTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const; |
| 71 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 72 | void releaseGlyphCache() const; |
| 73 | |
| 74 | size_t computeSizeInCache() const; |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 75 | |
| 76 | private: |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 77 | SkGlyphCache* getGlyphCache() const; |
| 78 | GrPathRange* createGlyphs(GrContext*) const; |
cdalton | 02015e5 | 2015-10-05 15:28:20 -0700 | [diff] [blame] | 79 | void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*); |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 80 | |
| 81 | GrStrokeInfo fStroke; |
| 82 | SkPaint fFont; |
| 83 | SkScalar fTextRatio; |
| 84 | float fTextInverseRatio; |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 85 | bool fUsingRawGlyphPaths; |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 86 | GrUniqueKey fGlyphPathsKey; |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 87 | int fTotalGlyphCount; |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 88 | SkAutoTUnref<GrPathRangeDraw> fDraw; |
cdalton | 02015e5 | 2015-10-05 15:28:20 -0700 | [diff] [blame] | 89 | SkAutoTUnref<const SkTextBlob> fFallbackTextBlob; |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 90 | mutable SkGlyphCache* fDetachedGlyphCache; |
| 91 | mutable uint32_t fLastDrawnGlyphsID; |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 92 | mutable SkMatrix fLocalMatrixTemplate; |
cdalton | 3bd909a | 2015-10-05 14:57:20 -0700 | [diff] [blame] | 93 | }; |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 94 | |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 95 | // Text blobs/caches. |
| 96 | |
bsalomon | f045d60 | 2015-11-18 19:01:12 -0800 | [diff] [blame] | 97 | class TextBlob : public SkTLList<TextRun, 1> { |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 98 | public: |
| 99 | typedef SkTArray<uint32_t, true> Key; |
| 100 | |
| 101 | static const Key& GetKey(const TextBlob* blob) { return blob->key(); } |
| 102 | |
| 103 | static uint32_t Hash(const Key& key) { |
| 104 | SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map. |
| 105 | return SkChecksum::Murmur3(key.begin(), sizeof(uint32_t) * key.count()); |
| 106 | } |
| 107 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 108 | TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint) |
| 109 | : fKey(&blobId, 1) { this->init(skBlob, skPaint); } |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 110 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 111 | TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint) |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 112 | : fKey(key) { |
| 113 | // 1-length keys are unterstood to be the blob id and must use the other constructor. |
| 114 | SkASSERT(fKey.count() > 1); |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 115 | this->init(skBlob, skPaint); |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | const Key& key() const { return fKey; } |
| 119 | |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 120 | size_t cpuMemorySize() const { return fCpuMemorySize; } |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 121 | |
| 122 | private: |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 123 | void init(const SkTextBlob*, const SkPaint&); |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 124 | |
| 125 | const SkSTArray<1, uint32_t, true> fKey; |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 126 | size_t fCpuMemorySize; |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 127 | |
| 128 | SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob); |
| 129 | }; |
| 130 | |
| 131 | const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&); |
| 132 | void purgeToFit(const TextBlob&); |
| 133 | |
| 134 | SkTHashMap<uint32_t, TextBlob*> fBlobIdCache; |
| 135 | SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob> fBlobKeyCache; |
| 136 | SkTInternalLList<TextBlob> fLRUList; |
cdalton | 8585dd2 | 2015-10-08 08:04:09 -0700 | [diff] [blame] | 137 | size_t fCacheSize; |
cdalton | cdd7907 | 2015-10-05 15:37:35 -0700 | [diff] [blame] | 138 | |
bsalomon | 1fcc01c | 2015-09-09 09:48:06 -0700 | [diff] [blame] | 139 | typedef GrTextContext INHERITED; |
kkinnunen | c6cb56f | 2014-06-24 00:12:27 -0700 | [diff] [blame] | 140 | }; |
| 141 | |
| 142 | #endif |