• 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 "include/private/chromium/GrSlug.h"
17 #include "src/core/SkGlyphRunPainter.h"
18 #include "src/core/SkIPoint16.h"
19 #include "src/core/SkMaskFilterBase.h"
20 #include "src/core/SkOpts.h"
21 #include "src/core/SkRectPriv.h"
22 #include "src/core/SkStrikeSpec.h"
23 #include "src/core/SkTInternalLList.h"
24 #include "src/core/SkTLazy.h"
25 #include "src/gpu/GrColor.h"
26 #include "src/gpu/GrSubRunAllocator.h"
27 #include "src/gpu/ops/GrOp.h"
28 
29 class GrAtlasManager;
30 class GrDeferredUploadTarget;
31 class GrGlyph;
32 class GrMeshDrawTarget;
33 class GrStrikeCache;
34 class GrSubRun;
35 
36 class SkMatrixProvider;
37 class SkStrikeClient;
38 class SkSurfaceProps;
39 class SkTextBlob;
40 class SkTextBlobRunIterator;
41 
42 namespace skgpu::v1 { class SurfaceDrawContext; }
43 
44 // -- GrAtlasSubRun --------------------------------------------------------------------------------
45 // GrAtlasSubRun is the API that AtlasTextOp uses to generate vertex data for drawing.
46 //     There are three different ways GrAtlasSubRun is specialized.
47 //      * DirectMaskSubRun* - this is by far the most common type of SubRun. The mask pixels are
48 //        in 1:1 correspondence with the pixels on the device. The destination rectangles in this
49 //        SubRun are in device space. This SubRun handles color glyphs.
50 //      * TransformedMaskSubRun* - handles glyph where the image in the atlas needs to be
51 //        transformed to the screen. It is usually used for large color glyph which can't be
52 //        drawn with paths or scaled distance fields, but will be used to draw bitmap glyphs to
53 //        the screen, if the matrix does not map 1:1 to the screen. The destination rectangles
54 //        are in source space.
55 //      * SDFTSubRun* - scaled distance field text handles largish single color glyphs that still
56 //        can fit in the atlas; the sizes between direct SubRun, and path SubRun. The destination
57 //        rectangles are in source space.
58 class GrAtlasSubRun;
59 using GrAtlasSubRunOwner = std::unique_ptr<GrAtlasSubRun, GrSubRunAllocator::Destroyer>;
60 class GrAtlasSubRun  {
61 public:
62     virtual ~GrAtlasSubRun() = default;
63 
64     virtual size_t vertexStride(const SkMatrix& drawMatrix) const = 0;
65     virtual int glyphCount() const = 0;
66 
67     virtual std::tuple<const GrClip*, GrOp::Owner>
68     makeAtlasTextOp(
69             const GrClip*,
70             const SkMatrixProvider& viewMatrix,
71             SkPoint drawOrigin,
72             const SkPaint&,
73             skgpu::v1::SurfaceDrawContext*,
74             GrAtlasSubRunOwner subRun) const = 0;
75 
76     virtual void fillVertexData(
77             void* vertexDst, int offset, int count,
78             GrColor color,
79             const SkMatrix& drawMatrix,
80             SkPoint drawOrigin,
81             SkIRect clip) const = 0;
82 
83     virtual void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache* cache) const = 0;
84 
85     // This call is not thread safe. It should only be called from GrDrawOp::onPrepare which
86     // is single threaded.
87     virtual std::tuple<bool, int> regenerateAtlas(
88             int begin, int end, GrMeshDrawTarget* target) const = 0;
89 };
90 
91 // -- GrSubRun -------------------------------------------------------------------------------------
92 // GrSubRun defines the most basic functionality of a SubRun; the ability to draw, and the
93 // ability to be in a list.
94 class GrSubRun;
95 using GrSubRunOwner = std::unique_ptr<GrSubRun, GrSubRunAllocator::Destroyer>;
96 class GrBlobSubRun;
97 class GrSubRun {
98 public:
99     virtual ~GrSubRun();
100     // Produce GPU ops for this subRun or just draw them.
101     virtual void draw(SkCanvas*,
102                       const GrClip*,
103                       const SkMatrixProvider& viewMatrix,
104                       SkPoint drawOrigin,
105                       const SkPaint&,
106                       skgpu::v1::SurfaceDrawContext*) const = 0;
107 
108     virtual const GrBlobSubRun* blobCast() const;
109     void flatten(SkWriteBuffer& buffer) const;
110     static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
111                                         SkReadBuffer& buffer,
112                                         GrSubRunAllocator* alloc,
113                                         const SkStrikeClient* client);
114 
115     // Size hint for unflattening this run. If this is accurate, it will help with the allocation
116     // of the slug. If it's off then there may be more allocations needed to unflatten.
117     virtual int unflattenSize() const = 0;
118 
119 protected:
120     enum SubRunType : int;
121     virtual SubRunType subRunType() const = 0;
122     virtual void doFlatten(SkWriteBuffer& buffer) const = 0;
123 
124 private:
125     friend class GrSubRunList;
126     GrSubRunOwner fNext;
127 };
128 
129 // -- GrSubRunList ---------------------------------------------------------------------------------
130 class GrSubRunList {
131 public:
132     class Iterator {
133     public:
134         using value_type = GrSubRun;
135         using difference_type = ptrdiff_t;
136         using pointer = value_type*;
137         using reference = value_type&;
138         using iterator_category = std::input_iterator_tag;
Iterator(GrSubRun * subRun)139         Iterator(GrSubRun* subRun) : fPtr{subRun} { }
140         Iterator& operator++() { fPtr = fPtr->fNext.get(); return *this; }
141         Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; }
142         bool operator==(const Iterator& rhs) const { return fPtr == rhs.fPtr; }
143         bool operator!=(const Iterator& rhs) const { return fPtr != rhs.fPtr; }
144         reference operator*() { return *fPtr; }
145 
146     private:
147         GrSubRun* fPtr;
148     };
149 
append(GrSubRunOwner subRun)150     void append(GrSubRunOwner subRun) {
151         GrSubRunOwner* newTail = &subRun->fNext;
152         *fTail = std::move(subRun);
153         fTail = newTail;
154     }
isEmpty()155     bool isEmpty() const { return fHead == nullptr; }
begin()156     Iterator begin() { return Iterator{ fHead.get()}; }
end()157     Iterator end() { return Iterator{nullptr}; }
begin()158     Iterator begin() const { return Iterator{ fHead.get()}; }
end()159     Iterator end() const { return Iterator{nullptr}; }
front()160     GrSubRun& front() const {return *fHead; }
161 
162 private:
163     GrSubRunOwner fHead{nullptr};
164     GrSubRunOwner* fTail{&fHead};
165 };
166 
167 // -- GrTextBlob -----------------------------------------------------------------------------------
168 // A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
169 // on the GPU.  These are initially created with valid positions and colors, but with invalid
170 // texture coordinates.
171 //
172 // A GrTextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun
173 // tracks its own GrGlyph* and vertex data. The memory is organized in the arena in the following
174 // way so that the pointers for the GrGlyph* and vertex data are known before creating the SubRun.
175 //
176 //  GrGlyph*... | vertexData... | SubRun | GrGlyph*... | vertexData... | SubRun  etc.
177 //
178 // In these classes, I'm trying to follow the convention about matrices and origins.
179 // * drawMatrix and drawOrigin    - describes transformations for the current draw command.
180 // * initial Matrix - describes the combined initial matrix and origin the GrTextBlob was created
181 //                    with.
182 //
183 //
184 class GrTextBlob final : public GrTextReferenceFrame, public SkGlyphRunPainterInterface {
185 public:
186     // Key is not used as part of a hash map, so the hash is never taken. It's only used in a
187     // list search using operator =().
188     struct Key {
189         static std::tuple<bool, Key> Make(const SkGlyphRunList& glyphRunList,
190                                           const SkPaint& paint,
191                                           const SkSurfaceProps& surfaceProps,
192                                           const GrColorInfo& colorInfo,
193                                           const SkMatrix& drawMatrix,
194                                           const GrSDFTControl& control);
195         uint32_t fUniqueID;
196         // Color may affect the gamma of the mask we generate, but in a fairly limited way.
197         // Each color is assigned to on of a fixed number of buckets based on its
198         // luminance. For each luminance bucket there is a "canonical color" that
199         // represents the bucket.  This functionality is currently only supported for A8
200         SkColor fCanonicalColor;
201         SkScalar fFrameWidth;
202         SkScalar fMiterLimit;
203         SkPixelGeometry fPixelGeometry;
204         SkMaskFilterBase::BlurRec fBlurRec;
205         uint32_t fScalerContextFlags;
206         SkMatrix fPositionMatrix;
207         // Below here fields are of size 1 byte.
208         bool fHasSomeDirectSubRuns;
209         bool fHasBlur;
210         SkPaint::Style fStyle;
211         SkPaint::Join fJoin;
212 
213         bool operator==(const Key& other) const;
214     };
215 
216     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob);
217 
218     // Make a GrTextBlob and its sub runs.
219     static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
220                                   const SkPaint& paint,
221                                   const SkMatrix& positionMatrix,
222                                   bool supportBilerpAtlas,
223                                   const GrSDFTControl& control,
224                                   SkGlyphRunListPainter* painter);
225 
226     ~GrTextBlob() override;
227 
228     // Change memory management to handle the data after GrTextBlob, but in the same allocation
229     // of memory. Only allow placement new.
230     void operator delete(void* p);
231     void* operator new(size_t);
232     void* operator new(size_t, void* p);
233 
key()234     const Key& key() { return fKey; }
235 
236     void addKey(const Key& key);
237     bool hasPerspective() const;
initialPositionMatrix()238     const SkMatrix& initialPositionMatrix() const override { return fInitialPositionMatrix; }
supportBilerpAtlas()239     bool supportBilerpAtlas() const { return fSupportBilerpAtlas; }
240 
241     bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const;
242 
243     const Key& key() const;
244     size_t size() const;
245 
246     void draw(SkCanvas*,
247               const GrClip* clip,
248               const SkMatrixProvider& viewMatrix,
249               SkPoint drawOrigin,
250               const SkPaint& paint,
251               skgpu::v1::SurfaceDrawContext* sdc);
252     const GrAtlasSubRun* testingOnlyFirstSubRun() const;
253 
254 private:
255     GrTextBlob(int allocSize,
256                bool supportBilerpAtlas,
257                const SkMatrix& positionMatrix,
258                SkColor initialLuminance);
259 
260     // Methods to satisfy SkGlyphRunPainterInterface
261     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& accepted,
262                             sk_sp<SkStrike>&& strike) override;
263     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& accepted,
264                             const SkFont& runFont,
265                             SkScalar strikeToSourceScale) override;
266     void processSourceDrawables(const SkZip<SkGlyphVariant, SkPoint>& accepted,
267                                 const SkFont& runFont,
268                                 SkScalar strikeToSourceScale) override;
269     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& accepted,
270                            sk_sp<SkStrike>&& strike,
271                            SkScalar strikeToSourceScale,
272                            const SkFont& runFont,
273                            const GrSDFTMatrixRange& matrixRange) override;
274     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& accepted,
275                             sk_sp<SkStrike>&& strike,
276                             SkScalar strikeToSourceScale) override;
277 
278     // The allocator must come first because it needs to be destroyed last. Other fields of this
279     // structure may have pointers into it.
280     GrSubRunAllocator fAlloc;
281 
282     // Owner and list of the SubRun.
283     GrSubRunList fSubRunList;
284 
285     // Overall size of this struct plus vertices and glyphs at the end.
286     const int fSize;
287 
288     // Support using bilerp for directly mapped sub runs.
289     const bool fSupportBilerpAtlas;
290 
291     // The initial view matrix combined with the initial origin. Used to determine if a cached
292     // subRun can be used in this draw situation.
293     const SkMatrix fInitialPositionMatrix;
294 
295     const SkColor fInitialLuminance;
296 
297     Key fKey;
298 
299     bool fSomeGlyphsExcluded{false};
300 };
301 
302 class GrSubRunNoCachePainter : public SkGlyphRunPainterInterface {
303 public:
304     GrSubRunNoCachePainter(SkCanvas*,
305                            skgpu::v1::SurfaceDrawContext*,
306                            GrSubRunAllocator*,
307                            const GrClip*,
308                            const SkMatrixProvider& viewMatrix,
309                            const SkGlyphRunList&,
310                            const SkPaint&);
311     void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& accepted,
312                             sk_sp<SkStrike>&& strike) override;
313     void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& accepted,
314                             sk_sp<SkStrike>&& strike,
315                             SkScalar strikeToSourceScale) override;
316     void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& accepted,
317                             const SkFont& runFont,
318                             SkScalar strikeToSourceScale) override;
319     void processSourceDrawables(const SkZip<SkGlyphVariant, SkPoint>& accepted,
320                                 const SkFont& runFont,
321                                 SkScalar strikeToSourceScale) override;
322     void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& accepted,
323                            sk_sp<SkStrike>&& strike,
324                            SkScalar strikeToSourceScale,
325                            const SkFont& runFont,
326                            const GrSDFTMatrixRange& matrixRange) override;
327 
328 private:
329 
330     // Draw passes ownership of the sub run to the op.
331     void draw(GrAtlasSubRunOwner subRun);
332 
333     SkCanvas* fCanvas;
334     skgpu::v1::SurfaceDrawContext* const fSDC;
335     GrSubRunAllocator* const fAlloc;
336     const GrClip* const fClip;
337     const SkMatrixProvider& fViewMatrix;
338     const SkGlyphRunList& fGlyphRunList;
339     const SkPaint& fPaint;
340 };
341 
342 namespace skgpu::v1 {
343 sk_sp<GrSlug> MakeSlug(const SkMatrixProvider& drawMatrix,
344                        const SkGlyphRunList& glyphRunList,
345                        const SkPaint& paint,
346                        const GrSDFTControl& control,
347                        SkGlyphRunListPainter* painter);
348 }  // namespace skgpu::v1
349 #endif  // GrTextBlob_DEFINED
350