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