2 * Copyright 2018 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkGlyphRun_DEFINED
9 #define SkGlyphRun_DEFINED
15 #include "include/core/SkFont.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPoint.h"
18 #include "include/core/SkRSXform.h"
19 #include "include/core/SkSpan.h"
20 #include "include/core/SkTypes.h"
21 #include "include/private/SkTemplates.h"
22 #include "src/core/SkGlyphBuffer.h"
23 #include "src/core/SkZip.h"
29 class SkGlyphRunBuilder;
31 class SkTextBlobRunIterator;
33 class SkSubRunBuffers {
37 ScopedBuffers(SkSubRunBuffers* painter, size_t size);
39 std::tuple<SkDrawableGlyphBuffer*, SkSourceGlyphBuffer*> buffers() {
40 return {&fBuffers->fAccepted, &fBuffers->fRejected};
44 SkSubRunBuffers* const fBuffers;
46 static ScopedBuffers SK_WARN_UNUSED_RESULT EnsureBuffers(const SkGlyphRunList& glyphRunList);
49 SkDrawableGlyphBuffer fAccepted;
50 SkSourceGlyphBuffer fRejected;
55 SkGlyphRun(const SkFont& font,
56 SkSpan<const SkPoint> positions,
57 SkSpan<const SkGlyphID> glyphIDs,
58 SkSpan<const char> text,
59 SkSpan<const uint32_t> clusters,
60 SkSpan<const SkVector> scaledRotations);
62 SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
64 size_t runSize() const { return fSource.size(); }
65 SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
66 SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
67 SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
68 const SkFont& font() const { return fFont; }
69 SkSpan<const uint32_t> clusters() const { return fClusters; }
70 SkSpan<const char> text() const { return fText; }
71 SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }
72 SkRect sourceBounds(const SkPaint& paint) const;
75 // GlyphIDs and positions.
76 const SkZip<const SkGlyphID, const SkPoint> fSource;
77 // Original text from SkTextBlob if present. Will be empty of not present.
78 const SkSpan<const char> fText;
79 // Original clusters from SkTextBlob if present. Will be empty if not present.
80 const SkSpan<const uint32_t> fClusters;
81 // Possible RSXForm information
82 const SkSpan<const SkVector> fScaledRotations;
83 // Font for this run modified to have glyph encoding and left alignment.
87 class SkGlyphRunList {
88 SkSpan<const SkGlyphRun> fGlyphRuns;
93 const SkTextBlob* blob,
96 SkSpan<const SkGlyphRun> glyphRunList,
97 SkGlyphRunBuilder* builder);
99 SkGlyphRunList(const SkGlyphRun& glyphRun,
100 const SkRect& bounds,
102 SkGlyphRunBuilder* builder);
103 uint64_t uniqueID() const;
104 bool anyRunsLCD() const;
105 void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
107 bool canCache() const { return fOriginalTextBlob != nullptr; }
108 size_t runCount() const { return fGlyphRuns.size(); }
109 size_t totalGlyphCount() const {
110 size_t glyphCount = 0;
111 for (const SkGlyphRun& run : *this) {
112 glyphCount += run.runSize();
117 bool hasRSXForm() const {
118 for (const SkGlyphRun& run : *this) {
119 if (!run.scaledRotations().empty()) { return true; }
124 sk_sp<SkTextBlob> makeBlob() const;
126 SkPoint origin() const { return fOrigin; }
127 SkRect sourceBounds() const { return fSourceBounds; }
128 const SkTextBlob* blob() const { return fOriginalTextBlob; }
129 SkGlyphRunBuilder* builder() const { return fBuilder; }
130 SkSubRunBuffers* buffers() const;
132 auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); }
133 auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); }
134 auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); }
135 auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); }
136 auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); }
137 auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); }
138 auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; }
141 // The text blob is needed to hook up the call back that the SkTextBlob destructor calls. It
142 // should be used for nothing else.
143 const SkTextBlob* fOriginalTextBlob{nullptr};
144 const SkRect fSourceBounds{SkRect::MakeEmpty()};
145 const SkPoint fOrigin = {0, 0};
146 SkGlyphRunBuilder* const fBuilder;
149 class SkGlyphRunBuilder {
151 SkGlyphRunList makeGlyphRunList(
152 const SkGlyphRun& run, SkRect bounds, SkPoint origin);
153 const SkGlyphRunList& textToGlyphRunList(const SkFont& font,
154 const SkPaint& paint,
158 SkTextEncoding encoding = SkTextEncoding::kUTF8);
159 const SkGlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin);
160 std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
161 convertRSXForm(SkSpan<const SkRSXform> xforms);
163 bool empty() const { return fGlyphRunListStorage.empty(); }
164 SkSubRunBuffers* buffers() { return &fSubRunBuffers; }
167 void initialize(const SkTextBlob& blob);
168 void prepareBuffers(int positionCount, int RSXFormCount);
170 SkSpan<const SkGlyphID> textToGlyphIDs(
171 const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
175 SkSpan<const SkGlyphID> glyphIDs,
176 SkSpan<const SkPoint> positions,
177 SkSpan<const char> text,
178 SkSpan<const uint32_t> clusters,
179 SkSpan<const SkVector> scaledRotations);
181 const SkGlyphRunList& setGlyphRunList(
182 const SkTextBlob* blob, const SkRect& bounds, SkPoint origin);
184 int fMaxTotalRunSize{0};
185 SkAutoTMalloc<SkPoint> fPositions;
186 int fMaxScaledRotations{0};
187 SkAutoTMalloc<SkVector> fScaledRotations;
189 std::vector<SkGlyphRun> fGlyphRunListStorage;
190 std::optional<SkGlyphRunList> fGlyphRunList; // Defaults to no value;
192 // Used as a temporary for preparing using utfN text. This implies that only one run of
193 // glyph ids will ever be needed because blobs are already glyph based.
194 std::vector<SkGlyphID> fScratchGlyphIDs;
196 SkSubRunBuffers fSubRunBuffers;
199 inline SkSubRunBuffers* SkGlyphRunList::buffers() const { return fBuilder->buffers(); }
201 #endif // SkGlyphRun_DEFINED