1 /* 2 * Copyright 2019 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 SkGlyphBuffer_DEFINED 9 #define SkGlyphBuffer_DEFINED 10 11 #include "src/core/SkGlyph.h" 12 #include "src/core/SkZip.h" 13 14 class SkStrikeForGPU; 15 struct SkGlyphPositionRoundingSpec; 16 17 // A memory format that allows an SkPackedGlyphID, SkGlyph*, and SkPath* to occupy the same 18 // memory. This allows SkPackedGlyphIDs as input, and SkGlyph*/SkPath* as output using the same 19 // memory. 20 class SkGlyphVariant { 21 public: SkGlyphVariant()22 SkGlyphVariant() : fV{nullptr} { } 23 SkGlyphVariant& operator= (SkPackedGlyphID packedID) { 24 fV.packedID = packedID; 25 SkDEBUGCODE(fTag = kPackedID); 26 return *this; 27 } 28 SkGlyphVariant& operator= (SkGlyph* glyph) { 29 fV.glyph = glyph; 30 SkDEBUGCODE(fTag = kGlyph); 31 return *this; 32 33 } 34 SkGlyphVariant& operator= (const SkPath* path) { 35 fV.path = path; 36 SkDEBUGCODE(fTag = kPath); 37 return *this; 38 } 39 glyph()40 SkGlyph* glyph() const { 41 SkASSERT(fTag == kGlyph); 42 return fV.glyph; 43 } path()44 const SkPath* path() const { 45 SkASSERT(fTag == kPath); 46 return fV.path; 47 } packedID()48 SkPackedGlyphID packedID() const { 49 SkASSERT(fTag == kPackedID); 50 return fV.packedID; 51 } 52 SkPackedGlyphID()53 operator SkPackedGlyphID() const { return this->packedID(); } 54 operator SkGlyph*() const { return this->glyph(); } 55 operator const SkPath*() const { return this->path(); } 56 57 private: 58 union { 59 SkGlyph* glyph; 60 const SkPath* path; 61 SkPackedGlyphID packedID; 62 } fV; 63 64 #ifdef SK_DEBUG 65 enum { 66 kEmpty, 67 kPackedID, 68 kGlyph, 69 kPath 70 } fTag{kEmpty}; 71 #endif 72 }; 73 74 // A buffer for converting SkPackedGlyph to SkGlyph* or SkPath*. Initially the buffer contains 75 // SkPackedGlyphIDs, but those are used to lookup SkGlyph*/SkPath* which are then copied over the 76 // SkPackedGlyphIDs. 77 class SkDrawableGlyphBuffer { 78 public: 79 void ensureSize(size_t size); 80 81 // Load the buffer with SkPackedGlyphIDs and positions in source space. 82 void startSource(const SkZip<const SkGlyphID, const SkPoint>& source, SkPoint origin); 83 84 // Load the buffer with SkPackedGlyphIDs and positions using the device transform. 85 void startDevice( 86 const SkZip<const SkGlyphID, const SkPoint>& source, 87 SkPoint origin, const SkMatrix& viewMatrix, 88 const SkGlyphPositionRoundingSpec& roundingSpec); 89 90 // The input of SkPackedGlyphIDs input()91 SkZip<SkGlyphVariant, SkPoint> input() { 92 SkASSERT(fPhase == kInput); 93 SkDEBUGCODE(fPhase = kProcess); 94 return SkZip<SkGlyphVariant, SkPoint>{fInputSize, fMultiBuffer, fPositions}; 95 } 96 97 // Store the glyph in the next drawable slot, using the position information located at index 98 // from. push_back(SkGlyph * glyph,size_t from)99 void push_back(SkGlyph* glyph, size_t from) { 100 SkASSERT(fPhase == kProcess); 101 SkASSERT(fDrawableSize <= from); 102 fPositions[fDrawableSize] = fPositions[from]; 103 fMultiBuffer[fDrawableSize] = glyph; 104 fDrawableSize++; 105 } 106 107 // Store the path in the next drawable slot, using the position information located at index 108 // from. push_back(const SkPath * path,size_t from)109 void push_back(const SkPath* path, size_t from) { 110 SkASSERT(fPhase == kProcess); 111 SkASSERT(fDrawableSize <= from); 112 fPositions[fDrawableSize] = fPositions[from]; 113 fMultiBuffer[fDrawableSize] = path; 114 fDrawableSize++; 115 } 116 117 // The result after a series of push_backs of drawable SkGlyph* or SkPath*. drawable()118 SkZip<SkGlyphVariant, SkPoint> drawable() { 119 SkASSERT(fPhase == kProcess); 120 SkDEBUGCODE(fPhase = kDraw); 121 return SkZip<SkGlyphVariant, SkPoint>{fDrawableSize, fMultiBuffer, fPositions}; 122 } 123 124 void reset(); 125 126 private: 127 size_t fMaxSize{0}; 128 size_t fInputSize{0}; 129 size_t fDrawableSize{0}; 130 SkAutoTMalloc<SkGlyphVariant> fMultiBuffer; 131 SkAutoTMalloc<SkPoint> fPositions; 132 133 #ifdef SK_DEBUG 134 enum { 135 kReset, 136 kInput, 137 kProcess, 138 kDraw 139 } fPhase{kReset}; 140 #endif 141 }; 142 #endif // SkGlyphBuffer_DEFINED 143