1 /*
2 * Copyright 2018 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 #include "include/core/SkFont.h"
9 #include "include/core/SkFontMetrics.h"
10 #include "include/core/SkFontMgr.h"
11 #include "include/core/SkFontStyle.h"
12 #include "include/core/SkString.h"
13 #include "include/core/SkTypeface.h"
14 #include "include/private/SkTFitsIn.h"
15 #include "modules/skshaper/include/SkShaper.h"
16
17 #ifdef SK_UNICODE_AVAILABLE
18 #include "modules/skunicode/include/SkUnicode.h"
19 #endif
20 #include "src/utils/SkUTF.h"
21 #include "src/core/SkTextBlobPriv.h"
22
23 #include <limits.h>
24 #include <string.h>
25 #include <locale>
26 #include <string>
27 #include <utility>
28
29 #ifdef USE_SKIA_TXT
30 namespace {
GetRSTypefaceOrDefault(std::shared_ptr<RSTypeface> typeface)31 std::shared_ptr<RSTypeface> GetRSTypefaceOrDefault(std::shared_ptr<RSTypeface> typeface) {
32 if (typeface) {
33 return typeface;
34 } else {
35 return RSTypeface::MakeDefault();
36 }
37 }
38 }
39 #endif
40
41 #ifdef USE_SKIA_TXT
42 namespace SkiaRsText {
43 #endif
44 #ifndef USE_SKIA_TXT
Make(sk_sp<SkFontMgr> fontmgr)45 std::unique_ptr<SkShaper> SkShaper::Make(sk_sp<SkFontMgr> fontmgr) {
46 #else
47 std::unique_ptr<SkShaper> SkShaper::Make(std::shared_ptr<RSFontMgr> fontmgr) {
48 #endif
49 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
50 std::unique_ptr<SkShaper> shaper = SkShaper::MakeShaperDrivenWrapper(std::move(fontmgr));
51 if (shaper) {
52 return shaper;
53 }
54 #elif defined(SK_SHAPER_CORETEXT_AVAILABLE)
55 if (auto shaper = SkShaper::MakeCoreText()) {
56 return shaper;
57 }
58 #endif
59 return SkShaper::MakePrimitive();
60 }
61
62 void SkShaper::PurgeCaches() {
63 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
64 PurgeHarfBuzzCache();
65 #endif
66 }
67
68 std::unique_ptr<SkShaper::BiDiRunIterator>
69 SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
70 #ifdef SK_UNICODE_AVAILABLE
71 auto unicode = SkUnicode::Make();
72 if (!unicode) {
73 return nullptr;
74 }
75 std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
76 SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
77 utf8,
78 utf8Bytes,
79 bidiLevel);
80 if (bidi) {
81 return bidi;
82 }
83 #endif
84 return std::make_unique<SkShaper::TrivialBiDiRunIterator>(bidiLevel, utf8Bytes);
85 }
86
87 std::unique_ptr<SkShaper::ScriptRunIterator>
88 SkShaper::MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag scriptTag) {
89 #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE)
90 auto unicode = SkUnicode::Make();
91 if (!unicode) {
92 return nullptr;
93 }
94 std::unique_ptr<SkShaper::ScriptRunIterator> script =
95 SkShaper::MakeSkUnicodeHbScriptRunIterator(utf8, utf8Bytes, scriptTag);
96 if (script) {
97 return script;
98 }
99 #endif
100 return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
101 }
102
103 SkShaper::SkShaper() {}
104 SkShaper::~SkShaper() {}
105
106 /** Replaces invalid utf-8 sequences with REPLACEMENT CHARACTER U+FFFD. */
107 static inline SkUnichar utf8_next(const char** ptr, const char* end) {
108 SkUnichar val = SkUTF::NextUTF8(ptr, end);
109 return val < 0 ? 0xFFFD : val;
110 }
111
112 #ifndef USE_SKIA_TXT
113 class FontMgrRunIterator final : public SkShaper::FontRunIterator {
114 public:
115 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
116 const SkFont& font, sk_sp<SkFontMgr> fallbackMgr,
117 const char* requestName, SkFontStyle requestStyle,
118 const SkShaper::LanguageRunIterator* lang)
119 : fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
120 , fFallbackMgr(std::move(fallbackMgr))
121 , fFont(font)
122 , fFallbackFont(fFont)
123 , fCurrentFont(nullptr)
124 , fRequestName(requestName)
125 , fRequestStyle(requestStyle)
126 , fLanguage(lang)
127 {
128 fFont.setTypeface(font.refTypefaceOrDefault());
129 fFallbackFont.setTypeface(nullptr);
130 }
131 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
132 const SkFont& font, sk_sp<SkFontMgr> fallbackMgr)
133 : FontMgrRunIterator(utf8, utf8Bytes, font, std::move(fallbackMgr),
134 nullptr, font.refTypefaceOrDefault()->fontStyle(), nullptr)
135 {}
136
137 void consume() override {
138 SkASSERT(fCurrent < fEnd);
139 SkASSERT(!fLanguage || this->endOfCurrentRun() <= fLanguage->endOfCurrentRun());
140 SkUnichar u = utf8_next(&fCurrent, fEnd);
141 // If the starting typeface can handle this character, use it.
142 if (fFont.unicharToGlyph(u)) {
143 fCurrentFont = &fFont;
144 // If the current fallback can handle this character, use it.
145 } else if (fFallbackFont.getTypeface() && fFallbackFont.unicharToGlyph(u)) {
146 fCurrentFont = &fFallbackFont;
147 // If not, try to find a fallback typeface
148 } else {
149 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
150 int languageCount = fLanguage ? 1 : 0;
151 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
152 fRequestName, fRequestStyle, &language, languageCount, u));
153 if (candidate) {
154 fFallbackFont.setTypeface(std::move(candidate));
155 fCurrentFont = &fFallbackFont;
156 } else {
157 fCurrentFont = &fFont;
158 }
159 }
160
161 while (fCurrent < fEnd) {
162 const char* prev = fCurrent;
163 u = utf8_next(&fCurrent, fEnd);
164
165 // End run if not using initial typeface and initial typeface has this character.
166 if (fCurrentFont->getTypeface() != fFont.getTypeface() && fFont.unicharToGlyph(u)) {
167 fCurrent = prev;
168 return;
169 }
170
171 // End run if current typeface does not have this character and some other font does.
172 if (!fCurrentFont->unicharToGlyph(u)) {
173 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
174 int languageCount = fLanguage ? 1 : 0;
175 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
176 fRequestName, fRequestStyle, &language, languageCount, u));
177 if (candidate) {
178 fCurrent = prev;
179 return;
180 }
181 }
182 }
183 }
184 size_t endOfCurrentRun() const override {
185 return fCurrent - fBegin;
186 }
187 bool atEnd() const override {
188 return fCurrent == fEnd;
189 }
190
191 const SkFont& currentFont() const override {
192 return *fCurrentFont;
193 }
194
195 private:
196 char const * fCurrent;
197 char const * const fBegin;
198 char const * const fEnd;
199 sk_sp<SkFontMgr> const fFallbackMgr;
200 SkFont fFont;
201 SkFont fFallbackFont;
202 SkFont* fCurrentFont;
203 char const * const fRequestName;
204 SkFontStyle const fRequestStyle;
205 SkShaper::LanguageRunIterator const * const fLanguage;
206 };
207 #else
208 class FontMgrRunIterator final : public SkShaper::FontRunIterator {
209 public:
210 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
211 const RSFont& font, std::shared_ptr<RSFontMgr> fallbackMgr,
212 const char* requestName, RSFontStyle requestStyle,
213 const SkShaper::LanguageRunIterator* lang)
214 : fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
215 , fFallbackMgr(std::move(fallbackMgr))
216 , fFont(font)
217 , fFallbackFont(fFont)
218 , fCurrentFont(nullptr)
219 , fRequestName(requestName)
220 , fRequestStyle(requestStyle)
221 , fLanguage(lang)
222 {
223 fFont.SetTypeface(GetRSTypefaceOrDefault(const_cast<RSFont&>(font).GetTypeface()));
224 fFallbackFont.SetTypeface(nullptr);
225 }
226 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
227 const RSFont& font, std::shared_ptr<RSFontMgr> fallbackMgr)
228 : FontMgrRunIterator(
229 utf8, utf8Bytes, font, std::move(fallbackMgr), nullptr,
230 GetRSTypefaceOrDefault(const_cast<RSFont&>(font).GetTypeface())->GetFontStyle(), nullptr)
231 {}
232
233 void consume() override {
234 SkASSERT(fCurrent < fEnd);
235 SkASSERT(!fLanguage || this->endOfCurrentRun() <= fLanguage->endOfCurrentRun());
236 SkUnichar u = utf8_next(&fCurrent, fEnd);
237 // If the starting typeface can handle this character, use it.
238 if (fFont.UnicharToGlyph(u)) {
239 fCurrentFont = &fFont;
240 // If the current fallback can handle this character, use it.
241 } else if (fFallbackFont.GetTypeface() && fFallbackFont.UnicharToGlyph(u)) {
242 fCurrentFont = &fFallbackFont;
243 // If not, try to find a fallback typeface
244 } else {
245 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
246 int languageCount = fLanguage ? 1 : 0;
247 std::shared_ptr<RSTypeface> candidate(fFallbackMgr->MatchFamilyStyleCharacter(
248 fRequestName, fRequestStyle, &language, languageCount, u));
249 if (candidate) {
250 fFallbackFont.SetTypeface(std::move(candidate));
251 fCurrentFont = &fFallbackFont;
252 } else {
253 fCurrentFont = &fFont;
254 }
255 }
256
257 while (fCurrent < fEnd) {
258 const char* prev = fCurrent;
259 u = utf8_next(&fCurrent, fEnd);
260 // End run if not using initial typeface and initial typeface has this character.
261 if (fCurrentFont->GetTypeface() != fFont.GetTypeface() && fFont.UnicharToGlyph(u)) {
262 fCurrent = prev;
263 return;
264 }
265
266 // End run if current typeface does not have this character and some other font does.
267 if (!fCurrentFont->UnicharToGlyph(u)) {
268 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
269 int languageCount = fLanguage ? 1 : 0;
270 std::shared_ptr<RSTypeface> candidate(fFallbackMgr->MatchFamilyStyleCharacter(
271 fRequestName, fRequestStyle, &language, languageCount, u));
272 if (candidate) {
273 fCurrent = prev;
274 return;
275 }
276 }
277 }
278 }
279 size_t endOfCurrentRun() const override {
280 return fCurrent - fBegin;
281 }
282 bool atEnd() const override {
283 return fCurrent == fEnd;
284 }
285
286 const RSFont& currentFont() const override {
287 return *fCurrentFont;
288 }
289
290 private:
291 char const * fCurrent;
292 char const * const fBegin;
293 char const * const fEnd;
294 std::shared_ptr<RSFontMgr> const fFallbackMgr;
295 RSFont fFont;
296 RSFont fFallbackFont;
297 RSFont* fCurrentFont;
298 char const * const fRequestName;
299 RSFontStyle const fRequestStyle;
300 SkShaper::LanguageRunIterator const * const fLanguage;
301 };
302 #endif
303
304 #ifndef USE_SKIA_TXT
305 std::unique_ptr<SkShaper::FontRunIterator>
306 SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
307 const SkFont& font, sk_sp<SkFontMgr> fallback)
308 {
309 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback));
310 }
311
312 std::unique_ptr<SkShaper::FontRunIterator>
313 SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, const SkFont& font,
314 sk_sp<SkFontMgr> fallback,
315 const char* requestName, SkFontStyle requestStyle,
316 const SkShaper::LanguageRunIterator* language)
317 {
318 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback),
319 requestName, requestStyle, language);
320 }
321 #else
322 std::unique_ptr<SkShaper::FontRunIterator>
323 SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
324 const RSFont& font, std::shared_ptr<RSFontMgr> fallback)
325 {
326 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback));
327 }
328
329 std::unique_ptr<SkShaper::FontRunIterator>
330 SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, const RSFont& font,
331 std::shared_ptr<RSFontMgr> fallback,
332 const char* requestName, RSFontStyle requestStyle,
333 const SkShaper::LanguageRunIterator* language)
334 {
335 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback),
336 requestName, requestStyle, language);
337 }
338 #endif
339
340 std::unique_ptr<SkShaper::LanguageRunIterator>
341 SkShaper::MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes) {
342 return std::make_unique<TrivialLanguageRunIterator>(std::locale().name().c_str(), utf8Bytes);
343 }
344
345 #ifndef USE_SKIA_TXT
346 void SkTextBlobBuilderRunHandler::beginLine() {
347 fCurrentPosition = fOffset;
348 fMaxRunAscent = 0;
349 fMaxRunDescent = 0;
350 fMaxRunLeading = 0;
351 }
352 void SkTextBlobBuilderRunHandler::runInfo(const RunInfo& info) {
353 SkFontMetrics metrics;
354 info.fFont.getMetrics(&metrics);
355 fMaxRunAscent = std::min(fMaxRunAscent, metrics.fAscent);
356 fMaxRunDescent = std::max(fMaxRunDescent, metrics.fDescent);
357 fMaxRunLeading = std::max(fMaxRunLeading, metrics.fLeading);
358 }
359
360 void SkTextBlobBuilderRunHandler::commitRunInfo() {
361 fCurrentPosition.fY -= fMaxRunAscent;
362 }
363
364 SkShaper::RunHandler::Buffer SkTextBlobBuilderRunHandler::runBuffer(const RunInfo& info) {
365 int glyphCount = SkTFitsIn<int>(info.glyphCount) ? info.glyphCount : INT_MAX;
366 int utf8RangeSize = SkTFitsIn<int>(info.utf8Range.size()) ? info.utf8Range.size() : INT_MAX;
367
368 const auto& runBuffer = fBuilder.allocRunTextPos(info.fFont, glyphCount, utf8RangeSize);
369 if (runBuffer.utf8text && fUtf8Text) {
370 memcpy(runBuffer.utf8text, fUtf8Text + info.utf8Range.begin(), utf8RangeSize);
371 }
372 fClusters = runBuffer.clusters;
373 fGlyphCount = glyphCount;
374 fClusterOffset = info.utf8Range.begin();
375
376 return { runBuffer.glyphs,
377 runBuffer.points(),
378 nullptr,
379 runBuffer.clusters,
380 fCurrentPosition };
381 }
382
383 void SkTextBlobBuilderRunHandler::commitRunBuffer(const RunInfo& info) {
384 SkASSERT(0 <= fClusterOffset);
385 for (int i = 0; i < fGlyphCount; ++i) {
386 SkASSERT(fClusters[i] >= (unsigned)fClusterOffset);
387 fClusters[i] -= fClusterOffset;
388 }
389 fCurrentPosition += info.fAdvance;
390 }
391 void SkTextBlobBuilderRunHandler::commitLine() {
392 fOffset += { 0, fMaxRunDescent + fMaxRunLeading - fMaxRunAscent };
393 }
394
395 sk_sp<SkTextBlob> SkTextBlobBuilderRunHandler::makeBlob() {
396 return fBuilder.make();
397 }
398 #endif
399 #ifdef USE_SKIA_TXT
400 } // namespace SkiaRsText
401 #endif
402