1 | /* |
2 | * Copyright 2016 Google Inc. |
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 SkShaper_DEFINED |
9 | #define SkShaper_DEFINED |
10 | |
11 | #include "include/core/SkFontMgr.h" |
12 | #include "include/core/SkPoint.h" |
13 | #include "include/core/SkRefCnt.h" |
14 | #include "include/core/SkScalar.h" |
15 | #include "include/core/SkTextBlob.h" |
16 | #include "include/core/SkTypes.h" |
17 | |
18 | #include <memory> |
19 | |
20 | #if !defined(SKSHAPER_IMPLEMENTATION) |
21 | #define SKSHAPER_IMPLEMENTATION 0 |
22 | #endif |
23 | |
24 | #if !defined(SKSHAPER_API) |
25 | #if defined(SKSHAPER_DLL) |
26 | #if defined(_MSC_VER) |
27 | #if SKSHAPER_IMPLEMENTATION |
28 | #define SKSHAPER_API __declspec(dllexport) |
29 | #else |
30 | #define SKSHAPER_API __declspec(dllimport) |
31 | #endif |
32 | #else |
33 | #define SKSHAPER_API __attribute__((visibility("default"))) |
34 | #endif |
35 | #else |
36 | #define SKSHAPER_API |
37 | #endif |
38 | #endif |
39 | |
40 | class SkFont; |
41 | class SkFontMgr; |
42 | |
43 | /** |
44 | Shapes text using HarfBuzz and places the shaped text into a |
45 | client-managed buffer. |
46 | |
47 | If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs. |
48 | */ |
49 | class SKSHAPER_API SkShaper { |
50 | public: |
51 | static std::unique_ptr<SkShaper> MakePrimitive(); |
52 | #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE |
53 | static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr); |
54 | static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr); |
55 | static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr); |
56 | #endif |
57 | #ifdef SK_SHAPER_CORETEXT_AVAILABLE |
58 | static std::unique_ptr<SkShaper> MakeCoreText(); |
59 | #endif |
60 | |
61 | static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr); |
62 | |
63 | SkShaper(); |
64 | virtual ~SkShaper(); |
65 | |
66 | class RunIterator { |
67 | public: |
68 | virtual ~RunIterator() = default; |
69 | /** Set state to that of current run and move iterator to end of that run. */ |
70 | virtual void consume() = 0; |
71 | /** Offset to one past the last (utf8) element in the current run. */ |
72 | virtual size_t endOfCurrentRun() const = 0; |
73 | /** Return true if consume should no longer be called. */ |
74 | virtual bool atEnd() const = 0; |
75 | }; |
76 | class FontRunIterator : public RunIterator { |
77 | public: |
78 | virtual const SkFont& currentFont() const = 0; |
79 | }; |
80 | class BiDiRunIterator : public RunIterator { |
81 | public: |
82 | /** The unicode bidi embedding level (even ltr, odd rtl) */ |
83 | virtual uint8_t currentLevel() const = 0; |
84 | }; |
85 | class ScriptRunIterator : public RunIterator { |
86 | public: |
87 | /** Should be iso15924 codes. */ |
88 | virtual SkFourByteTag currentScript() const = 0; |
89 | }; |
90 | class LanguageRunIterator : public RunIterator { |
91 | public: |
92 | /** Should be BCP-47, c locale names may also work. */ |
93 | virtual const char* currentLanguage() const = 0; |
94 | }; |
95 | struct Feature { |
96 | SkFourByteTag tag; |
97 | uint32_t value; |
98 | size_t start; // Offset to the start (utf8) element of the run. |
99 | size_t end; // Offset to one past the last (utf8) element of the run. |
100 | }; |
101 | |
102 | private: |
103 | template <typename RunIteratorSubclass> |
104 | class TrivialRunIterator : public RunIteratorSubclass { |
105 | public: |
106 | static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, "" ); |
107 | TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {} |
108 | void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; } |
109 | size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } |
110 | bool atEnd() const override { return fAtEnd; } |
111 | private: |
112 | size_t fEnd; |
113 | bool fAtEnd; |
114 | }; |
115 | |
116 | public: |
117 | static std::unique_ptr<FontRunIterator> |
118 | MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, |
119 | const SkFont& font, sk_sp<SkFontMgr> fallback); |
120 | static std::unique_ptr<SkShaper::FontRunIterator> |
121 | MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, |
122 | const SkFont& font, sk_sp<SkFontMgr> fallback, |
123 | const char* requestName, SkFontStyle requestStyle, |
124 | const SkShaper::LanguageRunIterator*); |
125 | class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { |
126 | public: |
127 | TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) |
128 | : TrivialRunIterator(utf8Bytes), fFont(font) {} |
129 | const SkFont& currentFont() const override { return fFont; } |
130 | private: |
131 | SkFont fFont; |
132 | }; |
133 | |
134 | static std::unique_ptr<BiDiRunIterator> |
135 | MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); |
136 | #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE |
137 | static std::unique_ptr<BiDiRunIterator> |
138 | MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); |
139 | #endif |
140 | class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { |
141 | public: |
142 | TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) |
143 | : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} |
144 | uint8_t currentLevel() const override { return fBidiLevel; } |
145 | private: |
146 | uint8_t fBidiLevel; |
147 | }; |
148 | |
149 | static std::unique_ptr<ScriptRunIterator> |
150 | MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); |
151 | #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE |
152 | static std::unique_ptr<ScriptRunIterator> |
153 | MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); |
154 | #endif |
155 | class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { |
156 | public: |
157 | TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) |
158 | : TrivialRunIterator(utf8Bytes), fScript(script) {} |
159 | SkFourByteTag currentScript() const override { return fScript; } |
160 | private: |
161 | SkFourByteTag fScript; |
162 | }; |
163 | |
164 | static std::unique_ptr<LanguageRunIterator> |
165 | MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); |
166 | class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { |
167 | public: |
168 | TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) |
169 | : TrivialRunIterator(utf8Bytes), fLanguage(language) {} |
170 | const char* currentLanguage() const override { return fLanguage.c_str(); } |
171 | private: |
172 | SkString fLanguage; |
173 | }; |
174 | |
175 | class RunHandler { |
176 | public: |
177 | virtual ~RunHandler() = default; |
178 | |
179 | struct Range { |
180 | constexpr Range() : fBegin(0), fSize(0) {} |
181 | constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} |
182 | size_t fBegin; |
183 | size_t fSize; |
184 | constexpr size_t begin() const { return fBegin; } |
185 | constexpr size_t end() const { return begin() + size(); } |
186 | constexpr size_t size() const { return fSize; } |
187 | }; |
188 | |
189 | struct RunInfo { |
190 | const SkFont& fFont; |
191 | uint8_t fBidiLevel; |
192 | SkVector fAdvance; |
193 | size_t glyphCount; |
194 | Range utf8Range; |
195 | }; |
196 | |
197 | struct Buffer { |
198 | SkGlyphID* glyphs; // required |
199 | SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] |
200 | // if ( offsets) positions[i+1]-positions[i] are advances |
201 | SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] |
202 | uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] |
203 | SkPoint point; // offset to add to all positions |
204 | }; |
205 | |
206 | /** Called when beginning a line. */ |
207 | virtual void beginLine() = 0; |
208 | |
209 | /** Called once for each run in a line. Can compute baselines and offsets. */ |
210 | virtual void runInfo(const RunInfo&) = 0; |
211 | |
212 | /** Called after all runInfo calls for a line. */ |
213 | virtual void commitRunInfo() = 0; |
214 | |
215 | /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ |
216 | virtual Buffer runBuffer(const RunInfo&) = 0; |
217 | |
218 | /** Called after each runBuffer is filled out. */ |
219 | virtual void commitRunBuffer(const RunInfo&) = 0; |
220 | |
221 | /** Called when ending a line. */ |
222 | virtual void commitLine() = 0; |
223 | }; |
224 | |
225 | virtual void shape(const char* utf8, size_t utf8Bytes, |
226 | const SkFont& srcFont, |
227 | bool leftToRight, |
228 | SkScalar width, |
229 | RunHandler*) const = 0; |
230 | |
231 | virtual void shape(const char* utf8, size_t utf8Bytes, |
232 | FontRunIterator&, |
233 | BiDiRunIterator&, |
234 | ScriptRunIterator&, |
235 | LanguageRunIterator&, |
236 | SkScalar width, |
237 | RunHandler*) const = 0; |
238 | |
239 | virtual void shape(const char* utf8, size_t utf8Bytes, |
240 | FontRunIterator&, |
241 | BiDiRunIterator&, |
242 | ScriptRunIterator&, |
243 | LanguageRunIterator&, |
244 | const Feature* features, size_t featuresSize, |
245 | SkScalar width, |
246 | RunHandler*) const = 0; |
247 | |
248 | private: |
249 | SkShaper(const SkShaper&) = delete; |
250 | SkShaper& operator=(const SkShaper&) = delete; |
251 | }; |
252 | |
253 | /** |
254 | * Helper for shaping text directly into a SkTextBlob. |
255 | */ |
256 | class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { |
257 | public: |
258 | SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) |
259 | : fUtf8Text(utf8Text) |
260 | , fOffset(offset) {} |
261 | sk_sp<SkTextBlob> makeBlob(); |
262 | SkPoint endPoint() { return fOffset; } |
263 | |
264 | void beginLine() override; |
265 | void runInfo(const RunInfo&) override; |
266 | void commitRunInfo() override; |
267 | Buffer runBuffer(const RunInfo&) override; |
268 | void commitRunBuffer(const RunInfo&) override; |
269 | void commitLine() override; |
270 | |
271 | private: |
272 | SkTextBlobBuilder fBuilder; |
273 | char const * const fUtf8Text; |
274 | uint32_t* fClusters; |
275 | int fClusterOffset; |
276 | int fGlyphCount; |
277 | SkScalar fMaxRunAscent; |
278 | SkScalar fMaxRunDescent; |
279 | SkScalar fMaxRunLeading; |
280 | SkPoint fCurrentPosition; |
281 | SkPoint fOffset; |
282 | }; |
283 | |
284 | #endif // SkShaper_DEFINED |
285 | |