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