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