1 /* 2 * Copyright 2018 The Android Open Source Project 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 SkGlyphRun_DEFINED 9 #define SkGlyphRun_DEFINED 10 11 #include <functional> 12 #include <vector> 13 14 #include "SkFont.h" 15 #include "SkPaint.h" 16 #include "SkPoint.h" 17 #include "SkSpan.h" 18 #include "SkTemplates.h" 19 #include "SkTypes.h" 20 21 class SkBaseDevice; 22 class SkGlyph; 23 class SkTextBlob; 24 25 class SkGlyphRun { 26 public: 27 SkGlyphRun() = default; 28 SkGlyphRun(const SkFont& font, 29 SkSpan<const SkPoint> positions, 30 SkSpan<const SkGlyphID> glyphIDs, 31 SkSpan<const char> text, 32 SkSpan<const uint32_t> clusters); 33 SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font); 34 35 void filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions); 36 37 size_t runSize() const { return fGlyphIDs.size(); } 38 SkSpan<const SkPoint> positions() const { return fPositions.toConst(); } 39 SkSpan<const SkGlyphID> glyphsIDs() const { return fGlyphIDs; } 40 const SkFont& font() const { return fFont; } 41 SkSpan<const uint32_t> clusters() const { return fClusters; } 42 SkSpan<const char> text() const { return fText; } 43 44 private: 45 // Positions of each glyph. 46 const SkSpan<const SkPoint> fPositions; 47 // This is temporary while converting from the old per glyph code to the bulk code. 48 const SkSpan<const SkGlyphID> fGlyphIDs; 49 // Original text from SkTextBlob if present. Will be empty of not present. 50 const SkSpan<const char> fText; 51 // Original clusters from SkTextBlob if present. Will be empty if not present. 52 const SkSpan<const uint32_t> fClusters; 53 // Paint for this run modified to have glyph encoding and left alignment. 54 SkFont fFont; 55 }; 56 57 class SkGlyphRunList { 58 const SkPaint* fOriginalPaint{nullptr}; // This should be deleted soon. 59 // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It 60 // should be used for nothing else 61 const SkTextBlob* fOriginalTextBlob{nullptr}; 62 SkPoint fOrigin = {0, 0}; 63 SkSpan<const SkGlyphRun> fGlyphRuns; 64 65 public: 66 SkGlyphRunList(); 67 // Blob maybe null. 68 SkGlyphRunList( 69 const SkPaint& paint, 70 const SkTextBlob* blob, 71 SkPoint origin, 72 SkSpan<const SkGlyphRun> glyphRunList); 73 74 SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint); 75 76 uint64_t uniqueID() const; 77 bool anyRunsLCD() const; 78 bool anyRunsSubpixelPositioned() const; 79 void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; 80 81 bool canCache() const { return fOriginalTextBlob != nullptr; } 82 size_t runCount() const { return fGlyphRuns.size(); } 83 size_t totalGlyphCount() const { 84 size_t glyphCount = 0; 85 for(const auto& run : fGlyphRuns) { 86 glyphCount += run.runSize(); 87 } 88 return glyphCount; 89 } 90 bool allFontsFinite() const; 91 92 SkPoint origin() const { return fOrigin; } 93 const SkPaint& paint() const { return *fOriginalPaint; } 94 const SkTextBlob* blob() const { return fOriginalTextBlob; } 95 96 auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } 97 auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } 98 auto begin() const -> decltype(fGlyphRuns.cbegin()) { return fGlyphRuns.cbegin(); } 99 auto end() const -> decltype(fGlyphRuns.cend()) { return fGlyphRuns.cend(); } 100 auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } 101 auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } 102 auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } 103 }; 104 105 class SkGlyphIDSet { 106 public: 107 SkSpan<const SkGlyphID> uniquifyGlyphIDs( 108 uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs, 109 SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices); 110 private: 111 size_t fUniverseToUniqueSize{0}; 112 SkAutoTMalloc<uint16_t> fUniverseToUnique; 113 }; 114 115 class SkGlyphRunBuilder { 116 public: 117 void drawTextUTF8( 118 const SkPaint& paint, const SkFont&, const void* bytes, size_t byteLength, SkPoint origin); 119 void drawGlyphsWithPositions( 120 const SkPaint&, const SkFont&, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos); 121 void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkBaseDevice*); 122 123 const SkGlyphRunList& useGlyphRunList(); 124 125 bool empty() const { return fGlyphRunListStorage.size() == 0; } 126 127 static void DispatchBlob(SkGlyphRunBuilder* builder, const SkPaint& paint, 128 const SkTextBlob& blob, SkPoint origin, SkBaseDevice* device); 129 130 private: 131 void initialize(size_t totalRunSize); 132 SkSpan<const SkGlyphID> textToGlyphIDs( 133 const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding); 134 135 void makeGlyphRun( 136 const SkFont& font, 137 SkSpan<const SkGlyphID> glyphIDs, 138 SkSpan<const SkPoint> positions, 139 SkSpan<const char> text, 140 SkSpan<const uint32_t> clusters); 141 142 void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin); 143 144 void simplifyDrawText( 145 const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, 146 SkPoint origin, SkPoint* positions, 147 SkSpan<const char> text = SkSpan<const char>{}, 148 SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); 149 void simplifyDrawPosTextH( 150 const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, 151 const SkScalar* xpos, SkScalar constY, SkPoint* positions, 152 SkSpan<const char> text = SkSpan<const char>{}, 153 SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); 154 void simplifyDrawPosText( 155 const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, 156 const SkPoint* pos, 157 SkSpan<const char> text = SkSpan<const char>{}, 158 SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); 159 160 size_t fMaxTotalRunSize{0}; 161 SkAutoTMalloc<SkPoint> fPositions; 162 163 std::vector<SkGlyphRun> fGlyphRunListStorage; 164 SkGlyphRunList fGlyphRunList; 165 166 // Used as a temporary for preparing using utfN text. This implies that only one run of 167 // glyph ids will ever be needed because blobs are already glyph based. 168 std::vector<SkGlyphID> fScratchGlyphIDs; 169 170 // Used as temporary storage for calculating positions for drawText. 171 std::vector<SkPoint> fScratchAdvances; 172 173 // Used for collecting the set of unique glyphs. 174 SkGlyphIDSet fGlyphIDSet; 175 SkAutoTMalloc<SkGlyphID> fUniqueGlyphIDs; 176 SkAutoTMalloc<uint16_t> fUniqueGlyphIDIndices; 177 }; 178 179 #endif // SkGlyphRun_DEFINED 180