• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 GrTextBlob_DEFINED
9 #define GrTextBlob_DEFINED
10 
11 #include <algorithm>
12 #include <limits>
13 
14 #include "include/core/SkPoint3.h"
15 #include "include/core/SkRefCnt.h"
16 #include "src/core/SkGlyphRunPainter.h"
17 #include "src/core/SkIPoint16.h"
18 #include "src/core/SkMaskFilterBase.h"
19 #include "src/core/SkOpts.h"
20 #include "src/core/SkRectPriv.h"
21 #include "src/core/SkStrikeSpec.h"
22 #include "src/core/SkTLazy.h"
23 #include "src/gpu/GrColor.h"
24 #include "src/gpu/GrSubRunAllocator.h"
25 #include "src/gpu/ops/GrMeshDrawOp.h"
26 #include "src/gpu/ops/GrOp.h"
27 
28 class GrAtlasManager;
29 class GrAtlasTextOp;
30 class GrDeferredUploadTarget;
31 class GrGlyph;
32 class GrStrikeCache;
33 class GrSubRun;
34 
35 class SkMatrixProvider;
36 class SkSurfaceProps;
37 class SkTextBlob;
38 class SkTextBlobRunIterator;
39 
40 
41 // -- GrAtlasSubRun --------------------------------------------------------------------------------
42 // GrAtlasSubRun is the API that GrAtlasTextOp uses to generate vertex data for drawing.
43 //     There are three different ways GrAtlasSubRun is specialized.
44 //      * DirectMaskSubRun - this is by far the most common type of SubRun. The mask pixels are
45 //        in 1:1 correspondence with the pixels on the device. The destination rectangles in this
46 //        SubRun are in device space. This SubRun handles color glyphs.
47 //      * TransformedMaskSubRun - handles glyph where the image in the atlas needs to be
48 //        transformed to the screen. It is usually used for large color glyph which can't be
49 //        drawn with paths or scaled distance fields. The destination rectangles are in source
50 //        space.
51 //      * SDFTSubRun - scaled distance field text handles largish single color glyphs that still
52 //        can fit in the atlas; the sizes between direct SubRun, and path SubRun. The destination
53 
54 class GrAtlasSubRun;
55 using GrAtlasSubRunOwner = std::unique_ptr<GrAtlasSubRun, GrSubRunAllocator::Destroyer>;
56 class GrAtlasSubRun  {
57 public:
58     static constexpr int kVerticesPerGlyph = 4;
59 
60     virtual ~GrAtlasSubRun() = default;
61 
62     virtual size_t vertexStride(const SkMatrix& drawMatrix) const = 0;
63     virtual int glyphCount() const = 0;
64 
65     virtual std::tuple<const GrClip*, GrOp::Owner>
66     makeAtlasTextOp(
67             const GrClip* clip,
68             const SkMatrixProvider& viewMatrix,
69             const SkGlyphRunList& glyphRunList,
70             const SkPaint& paint,
71             GrSurfaceDrawContext* rtc,
72             GrAtlasSubRunOwner subRun) const = 0;
73     virtual void fillVertexData(
74             void* vertexDst, int offset, int count,
75             GrColor color, const SkMatrix& positionMatrix,
76             SkIRect clip) const = 0;
77 
78     virtual void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache* cache) = 0;
79 
80     // This call is not thread safe. It should only be called from GrDrawOp::onPrepare which
81     // is single threaded.
82     virtual std::tuple<bool, int> regenerateAtlas(
83             int begin, int end, GrMeshDrawOp::Target* target) const = 0;
84 };
85 
86 // -- GrSubRun -------------------------------------------------------------------------------------
87 // GrSubRun is the API the GrTextBlob uses for the SubRun.
88 // There are several types of SubRun, which can be broken into five classes:
89 //   * PathSubRun - handle very large single color glyphs using paths to render the glyph.
90 //   * DirectMaskSubRun - handle the majority of the glyphs where the cache entry's pixels are in
91 //     1:1 correspondence to the device pixels.
92 //   * TransformedMaskSubRun - handle large bitmap/argb glyphs that need to be scaled to the screen.
93 //   * SDFTSubRun - use signed distance fields to draw largish glyphs to the screen.
94 //   * GrAtlasSubRun - this is an abstract class used for atlas drawing.
95 class GrSubRun;
96 using GrSubRunOwner = std::unique_ptr<GrSubRun, GrSubRunAllocator::Destroyer>;
97 class GrSubRun {
98 public:
99     virtual ~GrSubRun() = default;
100 
101     // Produce GPU ops for this subRun.
102     virtual void draw(const GrClip* clip,
103                       const SkMatrixProvider& viewMatrix,
104                       const SkGlyphRunList& glyphRunList,
105                       const SkPaint& paint,
106                       GrSurfaceDrawContext* rtc) const = 0;
107 
108     // Given an already cached subRun, can this subRun handle this combination paint, matrix, and
109     // position.
110     virtual bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) const = 0;
111 
112     // Return the underlying atlas SubRun if it exists. Otherwise, return nullptr.
113     // * Don't use this API. It is only to support testing.
114     virtual GrAtlasSubRun* testingOnly_atlasSubRun() = 0;
115 
116     GrSubRunOwner fNext;
117 };
118 
119 struct GrSubRunList {
120     class Iterator {
121     public:
122         using value_type = GrSubRun;
123         using difference_type = ptrdiff_t;
124         using pointer = value_type*;
125         using reference = value_type&;
126         using iterator_category = std::input_iterator_tag;
IteratorGrSubRunList127         Iterator(GrSubRun* subRun) : fPtr{subRun} { }
128         Iterator& operator++() { fPtr = fPtr->fNext.get(); return *this; }
129         Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; }
130         bool operator==(const Iterator& rhs) const { return fPtr == rhs.fPtr; }
131         bool operator!=(const Iterator& rhs) const { return fPtr != rhs.fPtr; }
132         reference operator*() { return *fPtr; }
133 
134     private:
135         GrSubRun* fPtr;
136     };
137 
appendGrSubRunList138     void append(GrSubRunOwner subRun) {
139         GrSubRunOwner* newTail = &subRun->fNext;
140         *fTail = std::move(subRun);
141         fTail = newTail;
142     }
isEmptyGrSubRunList143     bool isEmpty() const { return fHead == nullptr; }
beginGrSubRunList144     Iterator begin() { return Iterator{ fHead.get()}; }
endGrSubRunList145     Iterator end() { return Iterator{nullptr}; }
beginGrSubRunList146     Iterator begin() const { return Iterator{ fHead.get()}; }
endGrSubRunList147     Iterator end() const { return Iterator{nullptr}; }
frontGrSubRunList148     GrSubRun& front() const {return *fHead; }
149 
150     GrSubRunOwner fHead{nullptr};
151     GrSubRunOwner* fTail{&fHead};
152 };
153 
154 // A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
155 // on the GPU.  These are initially created with valid positions and colors, but invalid
156 // texture coordinates.
157 //
158 // A GrTextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun
159 // tracks its own GrGlyph* and vertex data. The memory is organized in the arena in the following
160 // way so that the pointers for the GrGlyph* and vertex data are known before creating the SubRun.
161 //
162 //  GrGlyph*... | vertexData... | SubRun | GrGlyph*... | vertexData... | SubRun  etc.
163 //
164 // In these classes, I'm trying to follow the convention about matrices and origins.
165 // * draw Matrix|Origin    - describes the current draw command.
166 // * initial Matrix - describes the combined initial matrix and origin the GrTextBlob was created
167 //   with.
168 //
169 //
170 class GrTextBlob final : public SkNVRefCnt<GrTextBlob>, public SkGlyphRunPainterInterface {
171 public:
172 
173     // Key is not used as part of a hash map, so the hash is never taken. It's only used in a
174     // list search using operator =().
175     struct Key {
176         static std::tuple<bool, Key> Make(const SkGlyphRunList& glyphRunList,
177                                           const SkPaint& paint,
178                                           const SkSurfaceProps& surfaceProps,
179                                           const GrColorInfo& colorInfo,
180                                           const SkMatrix& drawMatrix,
181                                           const GrSDFTControl& control);
182         uint32_t fUniqueID;
183         // Color may affect the gamma of the mask we generate, but in a fairly limited way.
184         // Each color is assigned to on of a fixed number of buckets based on its
185         // luminance. For each luminance bucket there is a "canonical color" that
186         // represents the bucket.  This functionality is currently only supported for A8
187         SkColor fCanonicalColor;
188         SkScalar fFrameWidth;
189         SkScalar fMiterLimit;
190         SkPixelGeometry fPixelGeometry;
191         SkMaskFilterBase::BlurRec fBlurRec;
192         uint32_t fScalerContextFlags;
193         SkMatrix fDrawMatrix;
194         // Below here fields are of size 1 byte.
195         uint8_t fSetOfDrawingTypes;
196         bool fHasBlur;
197         SkPaint::Style fStyle;
198         SkPaint::Join fJoin;
199 
200         bool operator==(const Key& other) const;
201     };
202 
203     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob);
204 
205     // Make a GrTextBlob and its sub runs.
206     static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
207                                   const SkPaint& paint,
208                                   const SkMatrix& drawMatrix,
209                                   const GrSDFTControl& control,
210                                   SkGlyphRunListPainter* painter);
211 
212     ~GrTextBlob() override;
213 
214     // Change memory management to handle the data after GrTextBlob, but in the same allocation
215     // of memory. Only allow placement new.
216     void operator delete(void* p);
217     void* operator new(size_t);
218     void* operator new(size_t, void* p);
219 
key()220     const Key& key() { return fKey; }
221 
222     void addKey(const Key& key);
223     bool hasPerspective() const;
initialMatrix()224     const SkMatrix& initialMatrix() const { return fInitialMatrix; }
225 
scaleBounds()226     std::tuple<SkScalar, SkScalar> scaleBounds() const {
227         return {fMaxMinScale, fMinMaxScale};
228     }
229 
230     bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) const;
231 
232     const Key& key() const;
233     size_t size() const;
234 
subRunList()235     const GrSubRunList& subRunList() const {
236         return fSubRunList;
237     }
238 
239 private:
240     GrTextBlob(int allocSize, const SkMatrix& drawMatrix, SkColor initialLuminance);
241 
242     template<typename AddSingleMaskFormat>
243     void addMultiMaskFormat(
244             AddSingleMaskFormat addSingle,
245             const SkZip<SkGlyphVariant, SkPoint>& drawables,
246             const SkStrikeSpec& strikeSpec);
247 
248     // Methods to satisfy SkGlyphRunPainterInterface
249     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
250                             const SkStrikeSpec& strikeSpec) override;
251     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
252                             const SkFont& runFont,
253                             const SkStrikeSpec& strikeSpec) override;
254     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
255                            const SkStrikeSpec& strikeSpec,
256                            const SkFont& runFont,
257                            SkScalar minScale,
258                            SkScalar maxScale) override;
259     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
260                             const SkStrikeSpec& strikeSpec) override;
261 
262     // The allocator must come first because it needs to be destroyed last. Other fields of this
263     // structure may have pointers into it.
264     GrSubRunAllocator fAlloc;
265 
266     // Owner and list of the SubRun.
267     GrSubRunList fSubRunList;
268 
269     // Overall size of this struct plus vertices and glyphs at the end.
270     const int fSize;
271 
272     // The initial view matrix combined with the initial origin. Used to determine if a cached
273     // subRun can be used in this draw situation.
274     const SkMatrix fInitialMatrix;
275 
276     const SkColor fInitialLuminance;
277 
278     Key fKey;
279 
280     // We can reuse distance field text, but only if the new view matrix would not result in
281     // a mip change.  Because there can be multiple runs in a blob, we track the overall
282     // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
283     SkScalar fMaxMinScale{-SK_ScalarMax};
284     SkScalar fMinMaxScale{SK_ScalarMax};
285 
286     bool fSomeGlyphsExcluded{false};
287 };
288 
289 class GrSubRunNoCachePainter : public SkGlyphRunPainterInterface {
290 public:
291     GrSubRunNoCachePainter(GrSurfaceDrawContext* sdc,
292                            GrSubRunAllocator* alloc,
293                            const GrClip* clip,
294                            const SkMatrixProvider& viewMatrix,
295                            const SkGlyphRunList& glyphRunList,
296                            const SkPaint& paint);
297     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
298                             const SkStrikeSpec& strikeSpec) override;
299     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
300                             const SkStrikeSpec& strikeSpec) override;
301     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
302                             const SkFont& runFont, const SkStrikeSpec& strikeSpec) override;
303     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
304                            const SkStrikeSpec& strikeSpec, const SkFont& runFont,
305                            SkScalar minScale, SkScalar maxScale) override;
306 private:
307     // Draw passes ownership of the sub run to the op.
308     void draw(GrAtlasSubRunOwner subRun);
309 
310     GrSurfaceDrawContext* const fSDC;
311     GrSubRunAllocator* const fAlloc;
312     const GrClip* const fClip;
313     const SkMatrixProvider& fViewMatrix;
314     const SkGlyphRunList& fGlyphRunList;
315     const SkPaint& fPaint;
316 };
317 
318 #endif  // GrTextBlob_DEFINED
319