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 | |
22 | class SkBaseDevice; |
23 | class SkGlyph; |
24 | class SkTextBlob; |
25 | class SkTextBlobRunIterator; |
26 | |
27 | class SkGlyphRun { |
28 | public: |
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 | |
45 | private: |
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 | |
56 | class SkGlyphRunList { |
57 | SkSpan<const SkGlyphRun> fGlyphRuns; |
58 | |
59 | public: |
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 | |
98 | private: |
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 | |
106 | class SkGlyphIDSet { |
107 | public: |
108 | SkSpan<const SkGlyphID> uniquifyGlyphIDs( |
109 | uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs, |
110 | SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices); |
111 | private: |
112 | size_t fUniverseToUniqueSize{0}; |
113 | SkAutoTMalloc<uint16_t> fUniverseToUnique; |
114 | }; |
115 | |
116 | class SkGlyphRunBuilder { |
117 | public: |
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 | |
131 | private: |
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 | |