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 "include/core/SkFont.h" 15 #include "include/core/SkPaint.h" 16 #include "include/core/SkPoint.h" 17 #include "include/core/SkRSXform.h" 18 #include "include/core/SkSpan.h" 19 #include "include/core/SkTypes.h" 20 #include "include/private/SkTemplates.h" 21 #include "src/core/SkZip.h" 22 23 class SkBaseDevice; 24 class SkGlyph; 25 class SkTextBlob; 26 class SkTextBlobRunIterator; 27 28 class SkGlyphRun { 29 public: 30 SkGlyphRun() = default; 31 SkGlyphRun(const SkFont& font, 32 SkSpan<const SkPoint> positions, 33 SkSpan<const SkGlyphID> glyphIDs, 34 SkSpan<const char> text, 35 SkSpan<const uint32_t> clusters, 36 SkSpan<const SkVector> scaledRotations); 37 38 SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font); 39 runSize()40 size_t runSize() const { return fSource.size(); } positions()41 SkSpan<const SkPoint> positions() const { return fSource.get<1>(); } glyphsIDs()42 SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); } source()43 SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; } font()44 const SkFont& font() const { return fFont; } clusters()45 SkSpan<const uint32_t> clusters() const { return fClusters; } text()46 SkSpan<const char> text() const { return fText; } scaledRotations()47 SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; } 48 SkRect sourceBounds(const SkPaint& paint) const; 49 50 private: 51 // GlyphIDs and positions. 52 const SkZip<const SkGlyphID, const SkPoint> fSource; 53 // Original text from SkTextBlob if present. Will be empty of not present. 54 const SkSpan<const char> fText; 55 // Original clusters from SkTextBlob if present. Will be empty if not present. 56 const SkSpan<const uint32_t> fClusters; 57 // Possible RSXForm information 58 const SkSpan<const SkVector> fScaledRotations; 59 // Font for this run modified to have glyph encoding and left alignment. 60 SkFont fFont; 61 }; 62 63 class SkGlyphRunList { 64 SkSpan<const SkGlyphRun> fGlyphRuns; 65 66 public: 67 SkGlyphRunList(); 68 // Blob maybe null. 69 SkGlyphRunList( 70 const SkTextBlob* blob, 71 SkRect bounds, 72 SkPoint origin, 73 SkSpan<const SkGlyphRun> glyphRunList); 74 75 SkGlyphRunList(const SkGlyphRun& glyphRun, const SkRect& bounds, SkPoint origin); 76 77 78 79 uint64_t uniqueID() const; 80 bool anyRunsLCD() const; 81 void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; 82 canCache()83 bool canCache() const { return fOriginalTextBlob != nullptr; } runCount()84 size_t runCount() const { return fGlyphRuns.size(); } totalGlyphCount()85 size_t totalGlyphCount() const { 86 size_t glyphCount = 0; 87 for (const SkGlyphRun& run : *this) { 88 glyphCount += run.runSize(); 89 } 90 return glyphCount; 91 } 92 hasRSXForm()93 bool hasRSXForm() const { 94 for (const SkGlyphRun& run : *this) { 95 if (!run.scaledRotations().empty()) { return true; } 96 } 97 return false; 98 } 99 100 sk_sp<SkTextBlob> makeBlob() const; 101 origin()102 SkPoint origin() const { return fOrigin; } sourceBounds()103 SkRect sourceBounds() const { return fSourceBounds; } blob()104 const SkTextBlob* blob() const { return fOriginalTextBlob; } 105 106 auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } 107 auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } 108 auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); } 109 auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); } 110 auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } 111 auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } 112 auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } 113 114 private: 115 // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It 116 // should be used for nothing else 117 const SkTextBlob* fOriginalTextBlob{nullptr}; 118 const SkRect fSourceBounds{SkRect::MakeEmpty()}; 119 const SkPoint fOrigin = {0, 0}; 120 }; 121 122 class SkGlyphRunBuilder { 123 public: 124 const SkGlyphRunList& textToGlyphRunList(const SkFont& font, 125 const SkPaint& paint, 126 const void* bytes, 127 size_t byteLength, 128 SkPoint origin, 129 SkTextEncoding encoding = SkTextEncoding::kUTF8); 130 const SkGlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin); 131 std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>> 132 convertRSXForm(SkSpan<const SkRSXform> xforms); 133 empty()134 bool empty() const { return fGlyphRunListStorage.empty(); } 135 136 private: 137 void initialize(const SkTextBlob& blob); 138 void prepareBuffers(int positionCount, int RSXFormCount); 139 140 SkSpan<const SkGlyphID> textToGlyphIDs( 141 const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding); 142 143 void makeGlyphRun( 144 const SkFont& font, 145 SkSpan<const SkGlyphID> glyphIDs, 146 SkSpan<const SkPoint> positions, 147 SkSpan<const char> text, 148 SkSpan<const uint32_t> clusters, 149 SkSpan<const SkVector> scaledRotations); 150 151 const SkGlyphRunList& makeGlyphRunList( 152 const SkTextBlob* blob, const SkRect& bounds, SkPoint origin); 153 154 int fMaxTotalRunSize{0}; 155 SkAutoTMalloc<SkPoint> fPositions; 156 int fMaxScaledRotations{0}; 157 SkAutoTMalloc<SkVector> fScaledRotations; 158 159 std::vector<SkGlyphRun> fGlyphRunListStorage; 160 SkGlyphRunList fGlyphRunList; 161 162 // Used as a temporary for preparing using utfN text. This implies that only one run of 163 // glyph ids will ever be needed because blobs are already glyph based. 164 std::vector<SkGlyphID> fScratchGlyphIDs; 165 }; 166 167 #endif // SkGlyphRun_DEFINED 168