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 <limits>
12
13#include "include/core/SkPoint3.h"
14#include "include/core/SkRefCnt.h"
15#include "src/core/SkGlyphRunPainter.h"
16#include "src/core/SkIPoint16.h"
17#include "src/core/SkMaskFilterBase.h"
18#include "src/core/SkOpts.h"
19#include "src/core/SkRectPriv.h"
20#include "src/core/SkStrikeSpec.h"
21#include "src/core/SkTLazy.h"
22#include "src/gpu/GrColor.h"
23#include "src/gpu/GrDrawOpAtlas.h"
24
25class GrAtlasManager;
26class GrAtlasTextOp;
27class GrDeferredUploadTarget;
28class GrGlyph;
29class GrStrikeCache;
30class GrTextContext;
31
32class SkSurfaceProps;
33class SkTextBlob;
34class SkTextBlobRunIterator;
35
36
37// A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
38// on the GPU. These are initially created with valid positions and colors, but invalid
39// texture coordinates.
40//
41// A GrTextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun
42// tracks its own GrGlyph* and vertex data. The memory is organized in the arena in the following
43// way so that the pointers for the GrGlyph* and vertex data are known before creating the SubRun.
44//
45// GrGlyph*... | vertexData... | SubRun | GrGlyph*... | vertexData... | SubRun etc.
46//
47// In these classes, I'm trying to follow the convention about matrices and origins.
48// * draw Matrix|Origin - describes the current draw command.
49// * initial Matrix|Origin - describes the matrix and origin the GrTextBlob was created with.
50// * current Matrix|Origin - describes the matrix and origin that are currently in the SubRun's
51// vertex data.
52//
53// When handling repeated drawing using the same GrTextBlob initial data are compared to drawing
54// data to see if this blob can service this drawing. If it can, but small changes are needed to
55// the vertex data, the current data of the SubRuns is adjusted to conform to the drawing data
56// from the op using the VertexRegenerator.
57//
58class GrTextBlob final : public SkNVRefCnt<GrTextBlob>, public SkGlyphRunPainterInterface {
59public:
60 class SubRun;
61 class VertexRegenerator;
62
63 enum SubRunType {
64 kDirectMask,
65 kTransformedMask,
66 kTransformedPath,
67 kTransformedSDFT
68 };
69
70 struct Key {
71 Key();
72 uint32_t fUniqueID;
73 // Color may affect the gamma of the mask we generate, but in a fairly limited way.
74 // Each color is assigned to on of a fixed number of buckets based on its
75 // luminance. For each luminance bucket there is a "canonical color" that
76 // represents the bucket. This functionality is currently only supported for A8
77 SkColor fCanonicalColor;
78 SkPaint::Style fStyle;
79 SkPixelGeometry fPixelGeometry;
80 bool fHasBlur;
81 uint32_t fScalerContextFlags;
82
83 bool operator==(const Key& other) const;
84 };
85
86 // Any glyphs that can't be rendered with the base or override descriptor
87 // are rendered as paths
88 struct PathGlyph {
89 PathGlyph(const SkPath& path, SkPoint origin);
90 SkPath fPath;
91 SkPoint fOrigin;
92 };
93
94 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob);
95
96 // Change memory management to handle the data after GrTextBlob, but in the same allocation
97 // of memory. Only allow placement new.
98 void operator delete(void* p);
99 void* operator new(size_t);
100 void* operator new(size_t, void* p);
101
102 ~GrTextBlob() override;
103
104 // Make an empty GrTextBlob, with all the invariants set to make the right decisions when
105 // adding SubRuns.
106 static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
107 const SkMatrix& drawMatrix,
108 GrColor color,
109 bool forceWForDistanceFields);
110
111 // Key manipulation functions
112 void setupKey(const GrTextBlob::Key& key,
113 const SkMaskFilterBase::BlurRec& blurRec,
114 const SkPaint& paint);
115 static const Key& GetKey(const GrTextBlob& blob);
116 static uint32_t Hash(const Key& key);
117
118 bool hasDistanceField() const;
119 bool hasBitmap() const;
120 bool hasPerspective() const;
121
122 void setHasDistanceField();
123 void setHasBitmap();
124 void setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax);
125
126 static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord);
127
128 bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec,
129 const SkMatrix& drawMatrix, SkPoint drawOrigin);
130
131 void flush(GrTextTarget*, const SkSurfaceProps& props,
132 const SkPaint& paint, const SkPMColor4f& filteredColor, const GrClip& clip,
133 const SkMatrix& drawMatrix, SkPoint drawOrigin);
134
135 void computeSubRunBounds(SkRect* outBounds, const SubRun& subRun,
136 const SkMatrix& drawMatrix, SkPoint drawOrigin,
137 bool needsGlyphTransform);
138
139 // Normal text mask, SDFT, or color.
140 struct Mask2DVertex {
141 SkPoint devicePos;
142 GrColor color;
143 SkIPoint16 atlasPos;
144 };
145 struct ARGB2DVertex {
146 SkPoint devicePos;
147 SkIPoint16 atlasPos;
148 };
149
150 // Perspective SDFT or SDFT forced to 3D or perspective color.
151 struct SDFT3DVertex {
152 SkPoint3 devicePos;
153 GrColor color;
154 SkIPoint16 atlasPos;
155 };
156 struct ARGB3DVertex {
157 SkPoint3 devicePos;
158 SkIPoint16 atlasPos;
159 };
160
161 static const int kVerticesPerGlyph = 4;
162
163 const Key& key() const;
164 size_t size() const;
165
166 // Internal test methods
167 std::unique_ptr<GrDrawOp> test_makeOp(int glyphCount, const SkMatrix& drawMatrix,
168 SkPoint drawOrigin, const SkPaint& paint,
169 const SkPMColor4f& filteredColor, const SkSurfaceProps&,
170 GrTextTarget*);
171
172 bool hasW(SubRunType type) const;
173
174 SubRun* makeSubRun(SubRunType type,
175 const SkZip<SkGlyphVariant, SkPoint>& drawables,
176 const SkStrikeSpec& strikeSpec,
177 GrMaskFormat format);
178
179 void addSingleMaskFormat(
180 SubRunType type,
181 const SkZip<SkGlyphVariant, SkPoint>& drawables,
182 const SkStrikeSpec& strikeSpec,
183 GrMaskFormat format);
184
185 void addMultiMaskFormat(
186 SubRunType type,
187 const SkZip<SkGlyphVariant, SkPoint>& drawables,
188 const SkStrikeSpec& strikeSpec);
189
190 void addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
191 const SkStrikeSpec& strikeSpec,
192 const SkFont& runFont,
193 SkScalar minScale,
194 SkScalar maxScale);
195
196private:
197 enum TextType {
198 kHasDistanceField_TextType = 0x1,
199 kHasBitmap_TextType = 0x2,
200 };
201
202 struct StrokeInfo {
203 SkScalar fFrameWidth;
204 SkScalar fMiterLimit;
205 SkPaint::Join fJoin;
206 };
207
208 GrTextBlob(size_t allocSize,
209 const SkMatrix& drawMatrix,
210 SkPoint origin,
211 GrColor color,
212 SkColor initialLuminance,
213 bool forceWForDistanceFields);
214
215 void insertSubRun(SubRun* subRun);
216
217 std::unique_ptr<GrAtlasTextOp> makeOp(SubRun& info, int glyphCount, const SkMatrix& drawMatrix,
218 SkPoint drawOrigin, const SkIRect& clipRect,
219 const SkPaint& paint, const SkPMColor4f& filteredColor,
220 const SkSurfaceProps&, GrTextTarget*);
221
222 // Methods to satisfy SkGlyphRunPainterInterface
223 void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
224 const SkStrikeSpec& strikeSpec) override;
225 void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
226 const SkFont& runFont,
227 const SkStrikeSpec& strikeSpec) override;
228 void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
229 const SkStrikeSpec& strikeSpec,
230 const SkFont& runFont,
231 SkScalar minScale,
232 SkScalar maxScale) override;
233 void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
234 const SkStrikeSpec& strikeSpec) override;
235
236 // Overall size of this struct plus vertices and glyphs at the end.
237 const size_t fSize;
238
239 // The initial view matrix and its inverse. This is used for moving additional draws of this
240 // same text blob. We record the initial view matrix and initial offsets(x,y), because we
241 // record vertex bounds relative to these numbers. When blobs are reused with new matrices,
242 // we need to return to source space so we can update the vertex bounds appropriately.
243 const SkMatrix fInitialMatrix;
244 const SkMatrix fInitialMatrixInverse;
245
246 // Initial position of this blob. Used for calculating position differences when reusing this
247 // blob.
248 const SkPoint fInitialOrigin;
249
250 // From the distance field options to force distance fields to have a W coordinate.
251 const bool fForceWForDistanceFields;
252
253 // The color of the text to draw for solid colors.
254 const GrColor fColor;
255 const SkColor fInitialLuminance;
256
257 SkMaskFilterBase::BlurRec fBlurRec;
258 StrokeInfo fStrokeInfo;
259 Key fKey;
260
261 // We can reuse distance field text, but only if the new view matrix would not result in
262 // a mip change. Because there can be multiple runs in a blob, we track the overall
263 // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
264 SkScalar fMaxMinScale{-SK_ScalarMax};
265 SkScalar fMinMaxScale{SK_ScalarMax};
266
267 uint8_t fTextType{0};
268
269 SubRun* fFirstSubRun{nullptr};
270 SubRun* fLastSubRun{nullptr};
271 SkArenaAlloc fAlloc;
272};
273
274/**
275 * Used to produce vertices for a subrun of a blob. The vertices are cached in the blob itself.
276 * This is invoked each time a sub run is drawn. It regenerates the vertex data as required either
277 * because of changes to the atlas or because of different draw parameters (e.g. color change). In
278 * rare cases the draw may have to interrupted and flushed in the middle of the sub run in order to
279 * free up atlas space. Thus, this generator is stateful and should be invoked in a loop until the
280 * entire sub run has been completed.
281 */
282class GrTextBlob::VertexRegenerator {
283public:
284 /**
285 * Consecutive VertexRegenerators often use the same SkGlyphCache. If the same instance of
286 * SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
287 * SkGlyphCache.
288 */
289 VertexRegenerator(GrResourceProvider*, GrTextBlob::SubRun* subRun,
290 GrDeferredUploadTarget*, GrAtlasManager*);
291
292 // Return {success, number of glyphs regenerated}
293 std::tuple<bool, int> regenerate(int begin, int end);
294
295private:
296 // Return {success, number of glyphs regenerated}
297 std::tuple<bool, int> updateTextureCoordinates(int begin, int end);
298
299 GrResourceProvider* fResourceProvider;
300 GrDeferredUploadTarget* fUploadTarget;
301 GrAtlasManager* fFullAtlasManager;
302 SkTLazy<SkBulkGlyphMetricsAndImages> fMetricsAndImages;
303 SubRun* fSubRun;
304};
305
306// -- GrTextBlob::SubRun ---------------------------------------------------------------------------
307// Hold data to draw the different types of sub run. SubRuns are produced knowing all the
308// glyphs that are included in them.
309class GrTextBlob::SubRun {
310public:
311 // Within a glyph-based subRun, the glyphs are initially recorded as SkPackedGlyphs. At
312 // flush time they are then converted to GrGlyph's (via the GrTextStrike). Once converted
313 // they are never converted back.
314 union PackedGlyphIDorGrGlyph {
315 PackedGlyphIDorGrGlyph() {}
316
317 SkPackedGlyphID fPackedGlyphID;
318 GrGlyph* fGrGlyph;
319 };
320
321 // SubRun for masks
322 SubRun(SubRunType type,
323 GrTextBlob* textBlob,
324 const SkStrikeSpec& strikeSpec,
325 GrMaskFormat format,
326 const SkSpan<PackedGlyphIDorGrGlyph>& glyphs,
327 const SkSpan<char>& vertexData);
328
329 // SubRun for paths
330 SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec);
331
332 void appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables);
333
334 // TODO when this object is more internal, drop the privacy
335 void resetBulkUseToken();
336 GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken();
337 GrTextStrike* strike() const;
338
339 GrMaskFormat maskFormat() const;
340
341 size_t vertexStride() const;
342 size_t colorOffset() const;
343 size_t texCoordOffset() const;
344 char* quadStart(size_t index) const;
345 size_t quadOffset(size_t index) const;
346
347 const SkRect& vertexBounds() const;
348 void joinGlyphBounds(const SkRect& glyphBounds);
349
350 bool drawAsDistanceFields() const;
351 bool drawAsPaths() const;
352 bool needsTransform() const;
353 bool needsPadding() const;
354
355 // Acquire a GrTextStrike and convert the SkPackedGlyphIDs to GrGlyphs for this run
356 void prepareGrGlyphs(GrStrikeCache*);
357 // has 'prepareGrGlyphs' been called (i.e., can the GrGlyphs be accessed) ?
358 SkDEBUGCODE(bool isPrepared() const { return SkToBool(fStrike); })
359
360 void translateVerticesIfNeeded(const SkMatrix& drawMatrix, SkPoint drawOrigin);
361 void updateVerticesColorIfNeeded(GrColor newColor);
362 void updateTexCoords(int begin, int end);
363
364 // df properties
365 void setUseLCDText(bool useLCDText);
366 bool hasUseLCDText() const;
367 void setAntiAliased(bool antiAliased);
368 bool isAntiAliased() const;
369
370 const SkStrikeSpec& strikeSpec() const;
371
372 SubRun* fNextSubRun{nullptr};
373 const SubRunType fType;
374 GrTextBlob* const fBlob;
375 const GrMaskFormat fMaskFormat;
376 const SkSpan<PackedGlyphIDorGrGlyph> fGlyphs;
377 const SkSpan<char> fVertexData;
378 const SkStrikeSpec fStrikeSpec;
379 sk_sp<GrTextStrike> fStrike;
380 struct {
381 bool useLCDText:1;
382 bool antiAliased:1;
383 } fFlags{false, false};
384 GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
385 SkRect fVertexBounds = SkRectPriv::MakeLargestInverted();
386 uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
387 GrColor fCurrentColor;
388 SkPoint fCurrentOrigin;
389 SkMatrix fCurrentMatrix;
390 std::vector<PathGlyph> fPaths;
391
392private:
393 bool hasW() const;
394
395}; // SubRun
396
397#endif // GrTextBlob_DEFINED
398