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