2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef sktext_gpu_TextBlob_DEFINED
9 #define sktext_gpu_TextBlob_DEFINED
14 #include "include/core/SkPoint3.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/private/chromium/Slug.h"
17 #include "src/core/SkDevice.h"
18 #include "src/core/SkGlyphRunPainter.h"
19 #include "src/core/SkIPoint16.h"
20 #include "src/core/SkMaskFilterBase.h"
21 #include "src/core/SkOpts.h"
22 #include "src/core/SkRectPriv.h"
23 #include "src/core/SkStrikeSpec.h"
24 #include "src/core/SkTInternalLList.h"
25 #include "src/core/SkTLazy.h"
27 #include "src/gpu/ganesh/GrColor.h"
28 #include "src/gpu/ganesh/ops/GrOp.h"
30 #include "src/text/gpu/SubRunAllocator.h"
34 class GrDeferredUploadTarget;
35 class GrMeshDrawTarget;
38 class SkMatrixProvider;
42 class SkTextBlobRunIterator;
44 namespace sktext::gpu {
49 namespace skgpu::v1 { class SurfaceDrawContext; }
51 namespace sktext::gpu {
53 // -- AtlasSubRun --------------------------------------------------------------------------------
54 // AtlasSubRun is the API that AtlasTextOp uses to generate vertex data for drawing.
55 // There are three different ways AtlasSubRun is specialized.
56 // * DirectMaskSubRun* - this is by far the most common type of SubRun. The mask pixels are
57 // in 1:1 correspondence with the pixels on the device. The destination rectangles in this
58 // SubRun are in device space. This SubRun handles color glyphs.
59 // * TransformedMaskSubRun* - handles glyph where the image in the atlas needs to be
60 // transformed to the screen. It is usually used for large color glyph which can't be
61 // drawn with paths or scaled distance fields, but will be used to draw bitmap glyphs to
62 // the screen, if the matrix does not map 1:1 to the screen. The destination rectangles
63 // are in source space.
64 // * SDFTSubRun* - scaled distance field text handles largish single color glyphs that still
65 // can fit in the atlas; the sizes between direct SubRun, and path SubRun. The destination
66 // rectangles are in source space.
69 virtual ~AtlasSubRun() = default;
71 virtual int glyphCount() const = 0;
74 virtual size_t vertexStride(const SkMatrix& drawMatrix) const = 0;
76 virtual std::tuple<const GrClip*, GrOp::Owner>
79 const SkMatrixProvider& viewMatrix,
82 sk_sp<SkRefCnt>&& subRunStorage,
83 skgpu::v1::SurfaceDrawContext*) const = 0;
85 virtual void fillVertexData(
86 void* vertexDst, int offset, int count,
88 const SkMatrix& drawMatrix,
90 SkIRect clip) const = 0;
92 // This call is not thread safe. It should only be called from GrDrawOp::onPrepare which
93 // is single threaded.
94 virtual std::tuple<bool, int> regenerateAtlas(
95 int begin, int end, GrMeshDrawTarget* target) const = 0;
98 virtual void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache) const = 0;
101 // -- SubRun -------------------------------------------------------------------------------------
102 // SubRun defines the most basic functionality of a SubRun; the ability to draw, and the
103 // ability to be in a list.
105 using SubRunOwner = std::unique_ptr<SubRun, SubRunAllocator::Destroyer>;
111 // Produce GPU ops for this subRun or just draw them.
112 virtual void draw(SkCanvas*,
114 const SkMatrixProvider& viewMatrix,
117 sk_sp<SkRefCnt> subRunStorage,
118 skgpu::v1::SurfaceDrawContext*) const = 0;
121 virtual const BlobSubRun* blobCast() const;
122 void flatten(SkWriteBuffer& buffer) const;
123 static SubRunOwner MakeFromBuffer(const SkMatrix& initialPositionMatrix,
124 SkReadBuffer& buffer,
125 sktext::gpu::SubRunAllocator* alloc,
126 const SkStrikeClient* client);
128 // Size hint for unflattening this run. If this is accurate, it will help with the allocation
129 // of the slug. If it's off then there may be more allocations needed to unflatten.
130 virtual int unflattenSize() const = 0;
132 // Given an already cached subRun, can this subRun handle this combination paint, matrix, and
134 virtual bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const = 0;
136 // Return the underlying atlas SubRun if it exists. Otherwise, return nullptr.
137 // * Don't use this API. It is only to support testing.
138 virtual const AtlasSubRun* testingOnly_atlasSubRun() const = 0;
141 enum SubRunType : int;
142 virtual SubRunType subRunType() const = 0;
143 virtual void doFlatten(SkWriteBuffer& buffer) const = 0;
146 friend class SubRunList;
150 // -- SubRunList ---------------------------------------------------------------------------------
155 using value_type = SubRun;
156 using difference_type = ptrdiff_t;
157 using pointer = value_type*;
158 using reference = value_type&;
159 using iterator_category = std::input_iterator_tag;
160 Iterator(SubRun* subRun) : fPtr{subRun} { }
161 Iterator& operator++() { fPtr = fPtr->fNext.get(); return *this; }
162 Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; }
163 bool operator==(const Iterator& rhs) const { return fPtr == rhs.fPtr; }
164 bool operator!=(const Iterator& rhs) const { return fPtr != rhs.fPtr; }
165 reference operator*() { return *fPtr; }
171 void append(SubRunOwner subRun) {
172 SubRunOwner* newTail = &subRun->fNext;
173 *fTail = std::move(subRun);
176 bool isEmpty() const { return fHead == nullptr; }
177 Iterator begin() { return Iterator{ fHead.get()}; }
178 Iterator end() { return Iterator{nullptr}; }
179 Iterator begin() const { return Iterator{ fHead.get()}; }
180 Iterator end() const { return Iterator{nullptr}; }
181 SubRun& front() const {return *fHead; }
184 SubRunOwner fHead{nullptr};
185 SubRunOwner* fTail{&fHead};
188 // -- TextBlob -----------------------------------------------------------------------------------
189 // A TextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
190 // on the GPU. These are initially created with valid positions and colors, but with invalid
191 // texture coordinates.
193 // A TextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun
194 // tracks its own glyph and position data.
196 // In these classes, I'm trying to follow the convention about matrices and origins.
197 // * drawMatrix and drawOrigin - describes transformations for the current draw command.
198 // * positionMatrix - is equal to drawMatrix * [drawOrigin-as-translation-matrix]
199 // * initial Matrix - describes the combined initial matrix and origin the TextBlob was created
203 class TextBlob final : public SkRefCnt {
205 // Key is not used as part of a hash map, so the hash is never taken. It's only used in a
206 // list search using operator =().
208 static std::tuple<bool, Key> Make(const SkGlyphRunList& glyphRunList,
209 const SkPaint& paint,
210 const SkMatrix& drawMatrix,
211 const SkStrikeDeviceInfo& strikeDevice);
213 // Color may affect the gamma of the mask we generate, but in a fairly limited way.
214 // Each color is assigned to on of a fixed number of buckets based on its
215 // luminance. For each luminance bucket there is a "canonical color" that
216 // represents the bucket. This functionality is currently only supported for A8
217 SkColor fCanonicalColor;
218 SkScalar fFrameWidth;
219 SkScalar fMiterLimit;
220 SkPixelGeometry fPixelGeometry;
221 SkMaskFilterBase::BlurRec fBlurRec;
222 uint32_t fScalerContextFlags;
223 SkMatrix fPositionMatrix;
224 // Below here fields are of size 1 byte.
225 bool fHasSomeDirectSubRuns;
227 SkPaint::Style fStyle;
230 bool operator==(const Key& other) const;
233 SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
235 // Make a TextBlob and its sub runs.
236 static sk_sp<TextBlob> Make(const SkGlyphRunList& glyphRunList,
237 const SkPaint& paint,
238 const SkMatrix& positionMatrix,
239 SkStrikeDeviceInfo strikeDeviceInfo,
240 SkStrikeForGPUCacheInterface* strikeCache);
242 TextBlob(SubRunAllocator&& alloc,
244 const SkMatrix& positionMatrix,
245 SkColor initialLuminance);
247 ~TextBlob() override;
249 // Change memory management to handle the data after TextBlob, but in the same allocation
250 // of memory. Only allow placement new.
251 void operator delete(void* p);
252 void* operator new(size_t);
253 void* operator new(size_t, void* p);
255 const Key& key() { return fKey; }
257 void addKey(const Key& key);
258 bool hasPerspective() const;
260 bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const;
262 const Key& key() const;
263 size_t size() const { return SkTo<size_t>(fSize); }
268 const SkMatrixProvider& viewMatrix,
270 const SkPaint& paint,
271 skgpu::v1::SurfaceDrawContext* sdc);
273 const AtlasSubRun* testingOnlyFirstSubRun() const;
276 // The allocator must come first because it needs to be destroyed last. Other fields of this
277 // structure may have pointers into it.
278 SubRunAllocator fAlloc;
280 // Owner and list of the SubRun.
281 SubRunList fSubRunList;
283 // Overall size of this struct plus vertices and glyphs at the end.
286 // The initial view matrix combined with the initial origin. Used to determine if a cached
287 // subRun can be used in this draw situation.
288 const SkMatrix fInitialPositionMatrix;
290 const SkColor fInitialLuminance;
294 bool fSomeGlyphsExcluded{false};
297 } // namespace sktext::gpu
299 namespace skgpu::v1 {
300 sk_sp<sktext::gpu::Slug> MakeSlug(const SkMatrixProvider& drawMatrix,
301 const SkGlyphRunList& glyphRunList,
302 const SkPaint& initialPaint,
303 const SkPaint& drawingPaint,
304 SkStrikeDeviceInfo strikeDeviceInfo,
305 SkStrikeForGPUCacheInterface* strikeCache);
306 } // namespace skgpu::v1
308 #endif // sktext_gpu_TextBlob_DEFINED