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