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 #include "modules/skshaper/include/SkShaper_harfbuzz.h"
9
10 #include "include/core/SkData.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkFontArguments.h"
13 #include "include/core/SkFontMetrics.h"
14 #include "include/core/SkFontMgr.h"
15 #include "include/core/SkFontTypes.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPoint.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkScalar.h"
21 #include "include/core/SkSpan.h"
22 #include "include/core/SkStream.h"
23 #include "include/core/SkString.h"
24 #include "include/core/SkTypeface.h"
25 #include "include/core/SkTypes.h"
26 #include "include/private/base/SkDebug.h"
27 #include "include/private/base/SkMalloc.h"
28 #include "include/private/base/SkMutex.h"
29 #include "include/private/base/SkTArray.h"
30 #include "include/private/base/SkTemplates.h"
31 #include "include/private/base/SkTo.h"
32 #include "include/private/base/SkTypeTraits.h"
33 #include "modules/skshaper/include/SkShaper.h"
34 #include "modules/skunicode/include/SkUnicode.h"
35 #include "src/base/SkTDPQueue.h"
36 #include "src/base/SkUTF.h"
37 #include "src/core/SkLRUCache.h"
38
39 #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
40 #include "modules/skshaper/include/SkShaper_skunicode.h"
41 #endif
42
43 #include <hb-ot.h>
44 #include <hb.h>
45
46 #include <cstdint>
47 #include <cstring>
48 #include <memory>
49 #include <type_traits>
50 #include <utility>
51
52 using namespace skia_private;
53
54 // HB_FEATURE_GLOBAL_START and HB_FEATURE_GLOBAL_END were not added until HarfBuzz 2.0
55 // They would have always worked, they just hadn't been named yet.
56 #if !defined(HB_FEATURE_GLOBAL_START)
57 # define HB_FEATURE_GLOBAL_START 0
58 #endif
59 #if !defined(HB_FEATURE_GLOBAL_END)
60 # define HB_FEATURE_GLOBAL_END ((unsigned int) -1)
61 #endif
62
63 namespace {
64 using HBBlob = std::unique_ptr<hb_blob_t , SkFunctionObject<hb_blob_destroy> >;
65 using HBFace = std::unique_ptr<hb_face_t , SkFunctionObject<hb_face_destroy> >;
66 using HBFont = std::unique_ptr<hb_font_t , SkFunctionObject<hb_font_destroy> >;
67 using HBBuffer = std::unique_ptr<hb_buffer_t, SkFunctionObject<hb_buffer_destroy>>;
68
69 using SkUnicodeBreak = std::unique_ptr<SkBreakIterator>;
70
skhb_position(SkScalar value)71 hb_position_t skhb_position(SkScalar value) {
72 // Treat HarfBuzz hb_position_t as 16.16 fixed-point.
73 constexpr int kHbPosition1 = 1 << 16;
74 return SkScalarRoundToInt(value * kHbPosition1);
75 }
76
skhb_glyph(hb_font_t * hb_font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t variation_selector,hb_codepoint_t * glyph,void * user_data)77 hb_bool_t skhb_glyph(hb_font_t* hb_font,
78 void* font_data,
79 hb_codepoint_t unicode,
80 hb_codepoint_t variation_selector,
81 hb_codepoint_t* glyph,
82 void* user_data) {
83 #ifdef ENABLE_TEXT_ENHANCE
84 RSFont& font = *reinterpret_cast<RSFont*>(font_data);
85 *glyph = font.UnicharToGlyph(unicode);
86 #else
87 SkFont& font = *reinterpret_cast<SkFont*>(font_data);
88 *glyph = font.unicharToGlyph(unicode);
89 #endif
90 return *glyph != 0;
91 }
92
skhb_nominal_glyph(hb_font_t * hb_font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t * glyph,void * user_data)93 hb_bool_t skhb_nominal_glyph(hb_font_t* hb_font,
94 void* font_data,
95 hb_codepoint_t unicode,
96 hb_codepoint_t* glyph,
97 void* user_data) {
98 return skhb_glyph(hb_font, font_data, unicode, 0, glyph, user_data);
99 }
100
skhb_nominal_glyphs(hb_font_t * hb_font,void * font_data,unsigned int count,const hb_codepoint_t * unicodes,unsigned int unicode_stride,hb_codepoint_t * glyphs,unsigned int glyph_stride,void * user_data)101 unsigned skhb_nominal_glyphs(hb_font_t *hb_font, void *font_data,
102 unsigned int count,
103 const hb_codepoint_t *unicodes,
104 unsigned int unicode_stride,
105 hb_codepoint_t *glyphs,
106 unsigned int glyph_stride,
107 void *user_data) {
108 #ifdef ENABLE_TEXT_ENHANCE
109 RSFont& font = *reinterpret_cast<RSFont*>(font_data);
110 #else
111 SkFont& font = *reinterpret_cast<SkFont*>(font_data);
112 #endif
113
114 // Batch call textToGlyphs since entry cost is not cheap.
115 // Copy requred because textToGlyphs is dense and hb is strided.
116 AutoSTMalloc<256, SkUnichar> unicode(count);
117 for (unsigned i = 0; i < count; i++) {
118 unicode[i] = *unicodes;
119 unicodes = SkTAddOffset<const hb_codepoint_t>(unicodes, unicode_stride);
120 }
121 AutoSTMalloc<256, SkGlyphID> glyph(count);
122 #ifdef ENABLE_TEXT_ENHANCE
123 font.TextToGlyphs(unicode.get(), count * sizeof(SkUnichar), RSDrawing::TextEncoding::UTF32,
124 glyph.get(), count);
125 #else
126 font.textToGlyphs(unicode.get(), count * sizeof(SkUnichar), SkTextEncoding::kUTF32,
127 glyph.get(), count);
128 #endif
129
130 // Copy the results back to the sparse array.
131 unsigned int done;
132 for (done = 0; done < count && glyph[done] != 0; done++) {
133 *glyphs = glyph[done];
134 glyphs = SkTAddOffset<hb_codepoint_t>(glyphs, glyph_stride);
135 }
136 // return 'done' to allow HarfBuzz to synthesize with NFC and spaces, return 'count' to avoid
137 return done;
138 }
139
skhb_glyph_h_advance(hb_font_t * hb_font,void * font_data,hb_codepoint_t hbGlyph,void * user_data)140 hb_position_t skhb_glyph_h_advance(hb_font_t* hb_font,
141 void* font_data,
142 hb_codepoint_t hbGlyph,
143 void* user_data) {
144 #ifdef ENABLE_TEXT_ENHANCE
145 RSFont& font = *reinterpret_cast<RSFont*>(font_data);
146 #else
147 SkFont& font = *reinterpret_cast<SkFont*>(font_data);
148 #endif
149
150 SkScalar advance;
151 SkGlyphID skGlyph = SkTo<SkGlyphID>(hbGlyph);
152
153 #ifdef ENABLE_TEXT_ENHANCE
154 font.GetWidths(&skGlyph, 1, &advance);
155 if (!font.IsSubpixel()) {
156 advance = SkScalarRoundToInt(advance);
157 }
158 #else
159 font.getWidths(&skGlyph, 1, &advance);
160 if (!font.isSubpixel()) {
161 advance = SkScalarRoundToInt(advance);
162 }
163 #endif
164 return skhb_position(advance);
165 }
166
skhb_glyph_h_advances(hb_font_t * hb_font,void * font_data,unsigned count,const hb_codepoint_t * glyphs,unsigned int glyph_stride,hb_position_t * advances,unsigned int advance_stride,void * user_data)167 void skhb_glyph_h_advances(hb_font_t* hb_font,
168 void* font_data,
169 unsigned count,
170 const hb_codepoint_t* glyphs,
171 unsigned int glyph_stride,
172 hb_position_t* advances,
173 unsigned int advance_stride,
174 void* user_data) {
175 #ifdef ENABLE_TEXT_ENHANCE
176 RSFont& font = *reinterpret_cast<RSFont*>(font_data);
177 #else
178 SkFont& font = *reinterpret_cast<SkFont*>(font_data);
179 #endif
180
181 // Batch call getWidths since entry cost is not cheap.
182 // Copy requred because getWidths is dense and hb is strided.
183 AutoSTMalloc<256, SkGlyphID> glyph(count);
184 for (unsigned i = 0; i < count; i++) {
185 glyph[i] = *glyphs;
186 glyphs = SkTAddOffset<const hb_codepoint_t>(glyphs, glyph_stride);
187 }
188 AutoSTMalloc<256, SkScalar> advance(count);
189 #ifdef ENABLE_TEXT_ENHANCE
190 font.GetWidths(glyph.get(), count, advance.get());
191 #else
192 font.getWidths(glyph.get(), count, advance.get());
193 #endif
194
195 #ifdef ENABLE_TEXT_ENHANCE
196 if (!font.IsSubpixel()) {
197 #else
198 if (!font.isSubpixel()) {
199 #endif
200 for (unsigned i = 0; i < count; i++) {
201 advance[i] = SkScalarRoundToInt(advance[i]);
202 }
203 }
204
205 // Copy the results back to the sparse array.
206 for (unsigned i = 0; i < count; i++) {
207 *advances = skhb_position(advance[i]);
208 advances = SkTAddOffset<hb_position_t>(advances, advance_stride);
209 }
210 }
211
212 // HarfBuzz callback to retrieve glyph extents, mainly used by HarfBuzz for
213 // fallback mark positioning, i.e. the situation when the font does not have
214 // mark anchors or other mark positioning rules, but instead HarfBuzz is
215 // supposed to heuristically place combining marks around base glyphs. HarfBuzz
216 // does this by measuring "ink boxes" of glyphs, and placing them according to
217 // Unicode mark classes. Above, below, centered or left or right, etc.
218 hb_bool_t skhb_glyph_extents(hb_font_t* hb_font,
219 void* font_data,
220 hb_codepoint_t hbGlyph,
221 hb_glyph_extents_t* extents,
222 void* user_data) {
223 #ifdef ENABLE_TEXT_ENHANCE
224 RSFont& font = *reinterpret_cast<RSFont*>(font_data);
225 #else
226 SkFont& font = *reinterpret_cast<SkFont*>(font_data);
227 #endif
228 SkASSERT(extents);
229
230 #ifdef ENABLE_TEXT_ENHANCE
231 RSRect bounds;
232 SkGlyphID skGlyph = SkTo<SkGlyphID>(hbGlyph);
233
234 font.GetWidths(&skGlyph, 1, nullptr, &bounds);
235 if (!font.IsSubpixel()) {
236 bounds = RSRect(bounds.RoundOut());
237 }
238
239 // Skia is y-down but HarfBuzz is y-up.
240 extents->x_bearing = skhb_position(bounds.left_);
241 extents->y_bearing = skhb_position(-bounds.top_);
242 extents->width = skhb_position(bounds.GetWidth());
243 extents->height = skhb_position(-bounds.GetHeight());
244 #else
245 SkRect sk_bounds;
246 SkGlyphID skGlyph = SkTo<SkGlyphID>(hbGlyph);
247
248 font.getWidths(&skGlyph, 1, nullptr, &sk_bounds);
249 if (!font.isSubpixel()) {
250 sk_bounds.set(sk_bounds.roundOut());
251 }
252
253 // Skia is y-down but HarfBuzz is y-up.
254 extents->x_bearing = skhb_position(sk_bounds.fLeft);
255 extents->y_bearing = skhb_position(-sk_bounds.fTop);
256 extents->width = skhb_position(sk_bounds.width());
257 extents->height = skhb_position(-sk_bounds.height());
258 #endif
259 return true;
260 }
261
262 #define SK_HB_VERSION_CHECK(x, y, z) \
263 (HB_VERSION_MAJOR > (x)) || \
264 (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR > (y)) || \
265 (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR == (y) && HB_VERSION_MICRO >= (z))
266
267 hb_font_funcs_t* skhb_get_font_funcs() {
268 static hb_font_funcs_t* const funcs = []{
269 // HarfBuzz will use the default (parent) implementation if they aren't set.
270 hb_font_funcs_t* const funcs = hb_font_funcs_create();
271 hb_font_funcs_set_variation_glyph_func(funcs, skhb_glyph, nullptr, nullptr);
272 hb_font_funcs_set_nominal_glyph_func(funcs, skhb_nominal_glyph, nullptr, nullptr);
273 #if SK_HB_VERSION_CHECK(2, 0, 0)
274 hb_font_funcs_set_nominal_glyphs_func(funcs, skhb_nominal_glyphs, nullptr, nullptr);
275 #else
276 sk_ignore_unused_variable(skhb_nominal_glyphs);
277 #endif
278 hb_font_funcs_set_glyph_h_advance_func(funcs, skhb_glyph_h_advance, nullptr, nullptr);
279 #if SK_HB_VERSION_CHECK(1, 8, 6)
280 hb_font_funcs_set_glyph_h_advances_func(funcs, skhb_glyph_h_advances, nullptr, nullptr);
281 #else
282 sk_ignore_unused_variable(skhb_glyph_h_advances);
283 #endif
284 hb_font_funcs_set_glyph_extents_func(funcs, skhb_glyph_extents, nullptr, nullptr);
285 hb_font_funcs_make_immutable(funcs);
286 return funcs;
287 }();
288 SkASSERT(funcs);
289 return funcs;
290 }
291
292 hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
293 #ifdef ENABLE_TEXT_ENHANCE
294 RSTypeface& typeface = *reinterpret_cast<RSTypeface*>(user_data);
295
296 auto size = typeface.GetTableSize(tag);
297 if (!size) {
298 return nullptr;
299 }
300 auto data = std::make_unique<char[]>(size);
301 if (!data) {
302 return nullptr;
303 }
304 auto relTableSize = typeface.GetTableData(tag, 0, size, data.get());
305 if (relTableSize != size) {
306 return nullptr;
307 }
308
309 auto rawData = data.release();
310 return hb_blob_create(rawData, size,
311 HB_MEMORY_MODE_READONLY, rawData, [](void* ctx) {
312 std::unique_ptr<char[]>((char*)ctx);
313 });
314 #else
315 SkTypeface& typeface = *reinterpret_cast<SkTypeface*>(user_data);
316
317 auto data = typeface.copyTableData(tag);
318 if (!data) {
319 return nullptr;
320 }
321 SkData* rawData = data.release();
322 return hb_blob_create(reinterpret_cast<char*>(rawData->writable_data()), rawData->size(),
323 HB_MEMORY_MODE_READONLY, rawData, [](void* ctx) {
324 SkSafeUnref(((SkData*)ctx));
325 });
326 #endif
327 }
328
329 #ifdef ENABLE_TEXT_ENHANCE
330 HBFace create_hb_face(const RSTypeface& typeface) {
331 int index = 0;
332 HBFace face;
333 if (!face) {
334 face.reset(hb_face_create_for_tables(
335 skhb_get_table,
336 const_cast<RSTypeface*>(std::make_unique<RSTypeface>(typeface).release()),
337 [](void* user_data){ std::unique_ptr<RSTypeface>(reinterpret_cast<RSTypeface*>(user_data)); }));
338 hb_face_set_index(face.get(), (unsigned)index);
339 }
340 SkASSERT(face);
341 if (!face) {
342 return nullptr;
343 }
344 hb_face_set_upem(face.get(), typeface.GetUnitsPerEm());
345
346 return face;
347 }
348 #else
349 HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
350 size_t size = asset->getLength();
351 HBBlob blob;
352 if (const void* base = asset->getMemoryBase()) {
353 blob.reset(hb_blob_create((const char*)base, SkToUInt(size),
354 HB_MEMORY_MODE_READONLY, asset.release(),
355 [](void* p) { delete (SkStreamAsset*)p; }));
356 } else {
357 // SkDebugf("Extra SkStreamAsset copy\n");
358 void* ptr = size ? sk_malloc_throw(size) : nullptr;
359 asset->read(ptr, size);
360 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
361 HB_MEMORY_MODE_READONLY, ptr, sk_free));
362 }
363 SkASSERT(blob);
364 hb_blob_make_immutable(blob.get());
365 return blob;
366 }
367
368 SkDEBUGCODE(static hb_user_data_key_t gDataIdKey;)
369
370 HBFace create_hb_face(const SkTypeface& typeface) {
371 int index = 0;
372 std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openExistingStream(&index);
373 HBFace face;
374 if (typefaceAsset && typefaceAsset->getMemoryBase()) {
375 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
376 // hb_face_create always succeeds. Check that the format is minimally recognized first.
377 // hb_face_create_for_tables may still create a working hb_face.
378 // See https://github.com/harfbuzz/harfbuzz/issues/248 .
379 unsigned int num_hb_faces = hb_face_count(blob.get());
380 if (0 < num_hb_faces && (unsigned)index < num_hb_faces) {
381 face.reset(hb_face_create(blob.get(), (unsigned)index));
382 // Check the number of glyphs as a basic sanitization step.
383 if (face && hb_face_get_glyph_count(face.get()) == 0) {
384 face.reset();
385 }
386 }
387 }
388 if (!face) {
389 face.reset(hb_face_create_for_tables(
390 skhb_get_table,
391 const_cast<SkTypeface*>(SkRef(&typeface)),
392 [](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
393 hb_face_set_index(face.get(), (unsigned)index);
394 }
395 SkASSERT(face);
396 if (!face) {
397 return nullptr;
398 }
399 hb_face_set_upem(face.get(), typeface.getUnitsPerEm());
400
401 SkDEBUGCODE(
402 hb_face_set_user_data(face.get(), &gDataIdKey, const_cast<SkTypeface*>(&typeface),
403 nullptr, false);
404 )
405
406 return face;
407 }
408 #endif
409
410 #ifdef ENABLE_TEXT_ENHANCE
411 HBFont create_typeface_hb_font(const RSTypeface& typeface) {
412 #else
413 HBFont create_typeface_hb_font(const SkTypeface& typeface) {
414 #endif
415 HBFace face(create_hb_face(typeface));
416 if (!face) {
417 return nullptr;
418 }
419
420 HBFont otFont(hb_font_create(face.get()));
421 SkASSERT(otFont);
422 if (!otFont) {
423 return nullptr;
424 }
425 hb_ot_font_set_funcs(otFont.get());
426 #ifndef ENABLE_TEXT_ENHANCE
427 int axis_count = typeface.getVariationDesignPosition(nullptr, 0);
428 if (axis_count > 0) {
429 AutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
430 if (typeface.getVariationDesignPosition(axis_values, axis_count) == axis_count) {
431 hb_font_set_variations(otFont.get(),
432 reinterpret_cast<hb_variation_t*>(axis_values.get()),
433 axis_count);
434 }
435 }
436 #endif
437
438 return otFont;
439 }
440
441 #ifdef ENABLE_TEXT_ENHANCE
442 HBFont create_sub_hb_font(const RSFont& font, const HBFont& typefaceFont) {
443 // Creating a sub font means that non-available functions
444 // are found from the parent.
445 HBFont skFont(hb_font_create_sub_font(typefaceFont.get()));
446 hb_font_set_funcs(skFont.get(), skhb_get_font_funcs(),
447 reinterpret_cast<void *>(std::make_unique<RSFont>(font).release()),
448 [](void* user_data){ std::unique_ptr<RSFont>(reinterpret_cast<RSFont*>(user_data)); });
449 int scale = skhb_position(font.GetSize());
450 hb_font_set_scale(skFont.get(), scale, scale);
451
452 return skFont;
453 }
454 #else
455 HBFont create_sub_hb_font(const SkFont& font, const HBFont& typefaceFont) {
456 SkDEBUGCODE(
457 hb_face_t* face = hb_font_get_face(typefaceFont.get());
458 void* dataId = hb_face_get_user_data(face, &gDataIdKey);
459 SkASSERT(dataId == font.getTypeface());
460 )
461
462 // Creating a sub font means that non-available functions
463 // are found from the parent.
464 HBFont skFont(hb_font_create_sub_font(typefaceFont.get()));
465 hb_font_set_funcs(skFont.get(), skhb_get_font_funcs(),
466 reinterpret_cast<void *>(new SkFont(font)),
467 [](void* user_data){ delete reinterpret_cast<SkFont*>(user_data); });
468 int scale = skhb_position(font.getSize());
469 hb_font_set_scale(skFont.get(), scale, scale);
470
471 return skFont;
472 }
473 #endif
474
475 /** Replaces invalid utf-8 sequences with REPLACEMENT CHARACTER U+FFFD. */
476 static inline SkUnichar utf8_next(const char** ptr, const char* end) {
477 SkUnichar val = SkUTF::NextUTF8(ptr, end);
478 return val < 0 ? 0xFFFD : val;
479 }
480
481 class SkUnicodeHbScriptRunIterator final: public SkShaper::ScriptRunIterator {
482 public:
483 SkUnicodeHbScriptRunIterator(const char* utf8,
484 size_t utf8Bytes,
485 hb_script_t defaultScript)
486 : fCurrent(utf8)
487 , fBegin(utf8)
488 , fEnd(fCurrent + utf8Bytes)
489 , fCurrentScript(defaultScript) {}
490 hb_script_t hb_script_for_unichar(SkUnichar u) {
491 return hb_unicode_script(hb_unicode_funcs_get_default(), u);
492 }
493 void consume() override {
494 SkASSERT(fCurrent < fEnd);
495 SkUnichar u = utf8_next(&fCurrent, fEnd);
496 fCurrentScript = hb_script_for_unichar(u);
497 while (fCurrent < fEnd) {
498 const char* prev = fCurrent;
499 u = utf8_next(&fCurrent, fEnd);
500 const hb_script_t script = hb_script_for_unichar(u);
501 if (script != fCurrentScript) {
502 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
503 fCurrentScript = script;
504 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
505 continue;
506 } else {
507 fCurrent = prev;
508 break;
509 }
510 }
511 }
512 if (fCurrentScript == HB_SCRIPT_INHERITED) {
513 fCurrentScript = HB_SCRIPT_COMMON;
514 }
515 }
516 size_t endOfCurrentRun() const override {
517 return fCurrent - fBegin;
518 }
519 bool atEnd() const override {
520 return fCurrent == fEnd;
521 }
522
523 SkFourByteTag currentScript() const override {
524 return SkSetFourByteTag(HB_UNTAG(fCurrentScript));
525 }
526 private:
527 char const * fCurrent;
528 char const * const fBegin;
529 char const * const fEnd;
530 hb_script_t fCurrentScript;
531 };
532
533 class RunIteratorQueue {
534 public:
535 void insert(SkShaper::RunIterator* runIterator, int priority) {
536 fEntries.insert({runIterator, priority});
537 }
538
539 bool advanceRuns() {
540 const SkShaper::RunIterator* leastRun = fEntries.peek().runIterator;
541 if (leastRun->atEnd()) {
542 SkASSERT(this->allRunsAreAtEnd());
543 return false;
544 }
545 const size_t leastEnd = leastRun->endOfCurrentRun();
546 SkShaper::RunIterator* currentRun = nullptr;
547 SkDEBUGCODE(size_t previousEndOfCurrentRun);
548 while ((currentRun = fEntries.peek().runIterator)->endOfCurrentRun() <= leastEnd) {
549 int priority = fEntries.peek().priority;
550 fEntries.pop();
551 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
552 currentRun->consume();
553 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
554 fEntries.insert({currentRun, priority});
555 }
556 return true;
557 }
558
559 size_t endOfCurrentRun() const {
560 return fEntries.peek().runIterator->endOfCurrentRun();
561 }
562
563 private:
564 bool allRunsAreAtEnd() const {
565 for (int i = 0; i < fEntries.count(); ++i) {
566 if (!fEntries.at(i).runIterator->atEnd()) {
567 return false;
568 }
569 }
570 return true;
571 }
572
573 struct Entry {
574 SkShaper::RunIterator* runIterator;
575 int priority;
576 };
577 static bool CompareEntry(Entry const& a, Entry const& b) {
578 size_t aEnd = a.runIterator->endOfCurrentRun();
579 size_t bEnd = b.runIterator->endOfCurrentRun();
580 return aEnd < bEnd || (aEnd == bEnd && a.priority < b.priority);
581 }
582 SkTDPQueue<Entry, CompareEntry> fEntries;
583 };
584
585 struct ShapedGlyph {
586 SkGlyphID fID;
587 uint32_t fCluster;
588 SkPoint fOffset;
589 SkVector fAdvance;
590 bool fMayLineBreakBefore;
591 bool fMustLineBreakBefore;
592 bool fHasVisual;
593 bool fGraphemeBreakBefore;
594 bool fUnsafeToBreak;
595 };
596
597 #ifdef ENABLE_TEXT_ENHANCE
598 struct ShapedRun {
599 ShapedRun(SkShaper::RunHandler::Range utf8Range, const RSFont& font, SkBidiIterator::Level level,
600 std::unique_ptr<ShapedGlyph[]> glyphs, size_t numGlyphs, SkVector advance = {0, 0})
601 : fUtf8Range(utf8Range), fFont(font), fLevel(level),
602 fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs), fAdvance(advance)
603 {}
604
605 SkShaper::RunHandler::Range fUtf8Range;
606 RSFont fFont;
607 SkBidiIterator::Level fLevel;
608 std::unique_ptr<ShapedGlyph[]> fGlyphs;
609 size_t fNumGlyphs;
610 SkVector fAdvance;
611 };
612 #else
613 struct ShapedRun {
614 ShapedRun(SkShaper::RunHandler::Range utf8Range, const SkFont& font, SkBidiIterator::Level level,
615 std::unique_ptr<ShapedGlyph[]> glyphs, size_t numGlyphs, SkVector advance = {0, 0})
616 : fUtf8Range(utf8Range), fFont(font), fLevel(level)
617 , fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs), fAdvance(advance)
618 {}
619
620 SkShaper::RunHandler::Range fUtf8Range;
621 SkFont fFont;
622 SkBidiIterator::Level fLevel;
623 std::unique_ptr<ShapedGlyph[]> fGlyphs;
624 size_t fNumGlyphs;
625 SkVector fAdvance;
626
627 static_assert(::sk_is_trivially_relocatable<decltype(fUtf8Range)>::value);
628 static_assert(::sk_is_trivially_relocatable<decltype(fFont)>::value);
629 static_assert(::sk_is_trivially_relocatable<decltype(fLevel)>::value);
630 static_assert(::sk_is_trivially_relocatable<decltype(fGlyphs)>::value);
631 static_assert(::sk_is_trivially_relocatable<decltype(fAdvance)>::value);
632
633 using sk_is_trivially_relocatable = std::true_type;
634 };
635 #endif
636 struct ShapedLine {
637 TArray<ShapedRun> runs;
638 SkVector fAdvance = { 0, 0 };
639 };
640
641 constexpr bool is_LTR(SkBidiIterator::Level level) {
642 return (level & 1) == 0;
643 }
644
645 void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
646 const ShapedRun& run, size_t startGlyphIndex, size_t endGlyphIndex) {
647 SkASSERT(startGlyphIndex <= endGlyphIndex);
648 const size_t glyphLen = endGlyphIndex - startGlyphIndex;
649
650 const auto buffer = handler->runBuffer(runInfo);
651 SkASSERT(buffer.glyphs);
652 SkASSERT(buffer.positions);
653
654 SkVector advance = {0,0};
655 for (size_t i = 0; i < glyphLen; i++) {
656 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
657 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? startGlyphIndex + i
658 : endGlyphIndex - 1 - i];
659 buffer.glyphs[i] = glyph.fID;
660 if (buffer.offsets) {
661 buffer.positions[i] = advance + buffer.point;
662 buffer.offsets[i] = glyph.fOffset;
663 } else {
664 buffer.positions[i] = advance + buffer.point + glyph.fOffset;
665 }
666 if (buffer.clusters) {
667 #ifdef ENABLE_TEXT_ENHANCE
668 // Specail handle for Rtl language's cluster index overall offset
669 size_t clusterUpdatePos = is_LTR(run.fLevel) ? i : i + 1;
670 buffer.clusters[clusterUpdatePos] = glyph.fCluster;
671 #else
672 buffer.clusters[i] = glyph.fCluster;
673 #endif
674 }
675 #ifdef ENABLE_TEXT_ENHANCE
676 if (buffer.advances) {
677 buffer.advances[i] = glyph.fAdvance;
678 }
679 #endif
680 advance += glyph.fAdvance;
681 }
682 handler->commitRunBuffer(runInfo);
683 }
684
685 void emit(SkUnicode* unicode, const ShapedLine& line, SkShaper::RunHandler* handler) {
686 // Reorder the runs and glyphs per line and write them out.
687 handler->beginLine();
688
689 int numRuns = line.runs.size();
690 AutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
691 for (int i = 0; i < numRuns; ++i) {
692 runLevels[i] = line.runs[i].fLevel;
693 }
694 AutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
695 unicode->reorderVisual(runLevels, numRuns, logicalFromVisual);
696
697 for (int i = 0; i < numRuns; ++i) {
698 int logicalIndex = logicalFromVisual[i];
699
700 const auto& run = line.runs[logicalIndex];
701 const SkShaper::RunHandler::RunInfo info = {
702 run.fFont,
703 run.fLevel,
704 run.fAdvance,
705 run.fNumGlyphs,
706 run.fUtf8Range
707 };
708 handler->runInfo(info);
709 }
710 handler->commitRunInfo();
711 for (int i = 0; i < numRuns; ++i) {
712 int logicalIndex = logicalFromVisual[i];
713
714 const auto& run = line.runs[logicalIndex];
715 const SkShaper::RunHandler::RunInfo info = {
716 run.fFont,
717 run.fLevel,
718 run.fAdvance,
719 run.fNumGlyphs,
720 run.fUtf8Range
721 };
722 append(handler, info, run, 0, run.fNumGlyphs);
723 }
724
725 handler->commitLine();
726 }
727
728 struct ShapedRunGlyphIterator {
729 ShapedRunGlyphIterator(const TArray<ShapedRun>& origRuns)
730 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
731 { }
732
733 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
734 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
735 bool operator==(const ShapedRunGlyphIterator& that) const {
736 return fRuns == that.fRuns &&
737 fRunIndex == that.fRunIndex &&
738 fGlyphIndex == that.fGlyphIndex;
739 }
740 bool operator!=(const ShapedRunGlyphIterator& that) const {
741 return fRuns != that.fRuns ||
742 fRunIndex != that.fRunIndex ||
743 fGlyphIndex != that.fGlyphIndex;
744 }
745
746 ShapedGlyph* next() {
747 const TArray<ShapedRun>& runs = *fRuns;
748 SkASSERT(fRunIndex < runs.size());
749 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
750
751 ++fGlyphIndex;
752 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
753 fGlyphIndex = 0;
754 ++fRunIndex;
755 #ifdef ENABLE_TEXT_ENHANCE
756 if (static_cast<size_t>(fRunIndex) >= runs.size()) {
757 #else
758 if (fRunIndex >= runs.size()) {
759 #endif
760 return nullptr;
761 }
762 }
763 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
764 }
765
766 ShapedGlyph* current() {
767 const TArray<ShapedRun>& runs = *fRuns;
768 #ifdef ENABLE_TEXT_ENHANCE
769 if (static_cast<size_t>(fRunIndex) >= runs.size()) {
770 #else
771 if (fRunIndex >= runs.size()) {
772 #endif
773 return nullptr;
774 }
775 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
776 }
777
778 const TArray<ShapedRun>* fRuns;
779 int fRunIndex;
780 size_t fGlyphIndex;
781 };
782
783 class ShaperHarfBuzz : public SkShaper {
784 public:
785 ShaperHarfBuzz(sk_sp<SkUnicode>,
786 HBBuffer,
787 #ifdef ENABLE_TEXT_ENHANCE
788 std::shared_ptr<RSFontMgr>);
789 #else
790 sk_sp<SkFontMgr>);
791 #endif
792
793 protected:
794 sk_sp<SkUnicode> fUnicode;
795
796 ShapedRun shape(const char* utf8, size_t utf8Bytes,
797 const char* utf8Start,
798 const char* utf8End,
799 const BiDiRunIterator&,
800 const LanguageRunIterator&,
801 const ScriptRunIterator&,
802 const FontRunIterator&,
803 const Feature*, size_t featuresSize) const;
804 private:
805 #ifdef ENABLE_TEXT_ENHANCE
806 const std::shared_ptr<RSFontMgr> fFontMgr;
807 #else
808 const sk_sp<SkFontMgr> fFontMgr; // for fallback
809 #endif
810 HBBuffer fBuffer;
811 hb_language_t fUndefinedLanguage;
812
813 #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
814 void shape(const char* utf8, size_t utf8Bytes,
815 #ifdef ENABLE_TEXT_ENHANCE
816 const RSFont&,
817 #else
818 const SkFont&,
819 #endif
820 bool leftToRight,
821 SkScalar width,
822 RunHandler*) const override;
823
824 void shape(const char* utf8Text, size_t textBytes,
825 FontRunIterator&,
826 BiDiRunIterator&,
827 ScriptRunIterator&,
828 LanguageRunIterator&,
829 SkScalar width,
830 RunHandler*) const override;
831 #endif
832
833 void shape(const char* utf8Text, size_t textBytes,
834 FontRunIterator&,
835 BiDiRunIterator&,
836 ScriptRunIterator&,
837 LanguageRunIterator&,
838 const Feature*, size_t featuresSize,
839 SkScalar width,
840 RunHandler*) const override;
841
842 virtual void wrap(char const * const utf8, size_t utf8Bytes,
843 const BiDiRunIterator&,
844 const LanguageRunIterator&,
845 const ScriptRunIterator&,
846 const FontRunIterator&,
847 RunIteratorQueue& runSegmenter,
848 const Feature*, size_t featuresSize,
849 SkScalar width,
850 RunHandler*) const = 0;
851 };
852
853 class ShaperDrivenWrapper : public ShaperHarfBuzz {
854 public:
855 using ShaperHarfBuzz::ShaperHarfBuzz;
856 private:
857 void wrap(char const * const utf8, size_t utf8Bytes,
858 const BiDiRunIterator&,
859 const LanguageRunIterator&,
860 const ScriptRunIterator&,
861 const FontRunIterator&,
862 RunIteratorQueue& runSegmenter,
863 const Feature*, size_t featuresSize,
864 SkScalar width,
865 RunHandler*) const override;
866 };
867
868 class ShapeThenWrap : public ShaperHarfBuzz {
869 public:
870 using ShaperHarfBuzz::ShaperHarfBuzz;
871 private:
872 void wrap(char const * const utf8, size_t utf8Bytes,
873 const BiDiRunIterator&,
874 const LanguageRunIterator&,
875 const ScriptRunIterator&,
876 const FontRunIterator&,
877 RunIteratorQueue& runSegmenter,
878 const Feature*, size_t featuresSize,
879 SkScalar width,
880 RunHandler*) const override;
881 };
882
883 class ShapeDontWrapOrReorder : public ShaperHarfBuzz {
884 public:
885 using ShaperHarfBuzz::ShaperHarfBuzz;
886 private:
887 void wrap(char const * const utf8, size_t utf8Bytes,
888 const BiDiRunIterator&,
889 const LanguageRunIterator&,
890 const ScriptRunIterator&,
891 const FontRunIterator&,
892 RunIteratorQueue& runSegmenter,
893 const Feature*, size_t featuresSize,
894 SkScalar width,
895 RunHandler*) const override;
896 };
897
898
899 ShaperHarfBuzz::ShaperHarfBuzz(sk_sp<SkUnicode> unicode,
900 #ifdef ENABLE_TEXT_ENHANCE
901 HBBuffer buffer, std::shared_ptr<RSFontMgr> fallback) : fUnicode(unicode),
902 fFontMgr(fallback ? std::move(fallback) : RSFontMgr::CreateDefaultFontMgr()),
903 #else
904 HBBuffer buffer, sk_sp<SkFontMgr> fallback) : fUnicode(unicode),
905 fFontMgr(fallback ? std::move(fallback) : SkFontMgr::RefEmpty()),
906 #endif
907 fBuffer(std::move(buffer)),
908 fUndefinedLanguage(hb_language_from_string("und", -1))
909 {
910 #if defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
911 SkASSERT(fUnicode);
912 #endif
913 }
914
915 #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
916 void ShaperHarfBuzz::shape(const char* utf8,
917 size_t utf8Bytes,
918 #ifdef ENABLE_TEXT_ENHANCE
919 const RSFont& srcFont,
920 #else
921 const SkFont& srcFont,
922 #endif
923 bool leftToRight,
924 SkScalar width,
925 RunHandler* handler) const {
926 SkBidiIterator::Level defaultLevel = leftToRight ? SkBidiIterator::kLTR : SkBidiIterator::kRTL;
927 std::unique_ptr<BiDiRunIterator> bidi(
928 SkShapers::unicode::BidiRunIterator(fUnicode, utf8, utf8Bytes, defaultLevel));
929
930 if (!bidi) {
931 return;
932 }
933
934 std::unique_ptr<LanguageRunIterator> language(MakeStdLanguageRunIterator(utf8, utf8Bytes));
935 if (!language) {
936 return;
937 }
938
939 std::unique_ptr<ScriptRunIterator> script(SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes));
940 if (!script) {
941 return;
942 }
943
944 std::unique_ptr<FontRunIterator> font(
945 MakeFontMgrRunIterator(utf8, utf8Bytes, srcFont, fFontMgr));
946 if (!font) {
947 return;
948 }
949
950 this->shape(utf8, utf8Bytes, *font, *bidi, *script, *language, width, handler);
951 }
952
953 void ShaperHarfBuzz::shape(const char* utf8,
954 size_t utf8Bytes,
955 FontRunIterator& font,
956 BiDiRunIterator& bidi,
957 ScriptRunIterator& script,
958 LanguageRunIterator& language,
959 SkScalar width,
960 RunHandler* handler) const {
961 this->shape(utf8, utf8Bytes, font, bidi, script, language, nullptr, 0, width, handler);
962 }
963 #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
964
965 void ShaperHarfBuzz::shape(const char* utf8,
966 size_t utf8Bytes,
967 FontRunIterator& font,
968 BiDiRunIterator& bidi,
969 ScriptRunIterator& script,
970 LanguageRunIterator& language,
971 const Feature* features,
972 size_t featuresSize,
973 SkScalar width,
974 RunHandler* handler) const {
975 SkASSERT(handler);
976 RunIteratorQueue runSegmenter;
977 runSegmenter.insert(&font, 3); // The font iterator is always run last in case of tie.
978 runSegmenter.insert(&bidi, 2);
979 runSegmenter.insert(&script, 1);
980 runSegmenter.insert(&language, 0);
981
982 this->wrap(utf8, utf8Bytes, bidi, language, script, font, runSegmenter,
983 features, featuresSize, width, handler);
984 }
985
986 void ShaperDrivenWrapper::wrap(char const * const utf8, size_t utf8Bytes,
987 const BiDiRunIterator& bidi,
988 const LanguageRunIterator& language,
989 const ScriptRunIterator& script,
990 const FontRunIterator& font,
991 RunIteratorQueue& runSegmenter,
992 const Feature* features, size_t featuresSize,
993 SkScalar width,
994 RunHandler* handler) const
995 {
996 ShapedLine line;
997
998 const char* utf8Start = nullptr;
999 const char* utf8End = utf8;
1000 SkUnicodeBreak lineBreakIterator;
1001 SkString currentLanguage;
1002 while (runSegmenter.advanceRuns()) { // For each item
1003 utf8Start = utf8End;
1004 utf8End = utf8 + runSegmenter.endOfCurrentRun();
1005
1006 #ifdef ENABLE_TEXT_ENHANCE
1007 ShapedRun model(RunHandler::Range(), RSFont(), 0, nullptr, 0);
1008 #else
1009 ShapedRun model(RunHandler::Range(), SkFont(), 0, nullptr, 0);
1010 #endif
1011 bool modelNeedsRegenerated = true;
1012 int modelGlyphOffset = 0;
1013
1014 struct TextProps {
1015 int glyphLen = 0;
1016 SkVector advance = {0, 0};
1017 };
1018 // map from character position to [safe to break, glyph position, advance]
1019 std::unique_ptr<TextProps[]> modelText;
1020 int modelTextOffset = 0;
1021 SkVector modelAdvanceOffset = {0, 0};
1022
1023 while (utf8Start < utf8End) { // While there are still code points left in this item
1024 size_t utf8runLength = utf8End - utf8Start;
1025 if (modelNeedsRegenerated) {
1026 model = shape(utf8, utf8Bytes,
1027 utf8Start, utf8End,
1028 bidi, language, script, font,
1029 features, featuresSize);
1030 modelGlyphOffset = 0;
1031
1032 SkVector advance = {0, 0};
1033 modelText = std::make_unique<TextProps[]>(utf8runLength + 1);
1034 size_t modelStartCluster = utf8Start - utf8;
1035 size_t previousCluster = 0;
1036 for (size_t i = 0; i < model.fNumGlyphs; ++i) {
1037 SkASSERT(modelStartCluster <= model.fGlyphs[i].fCluster);
1038 SkASSERT( model.fGlyphs[i].fCluster < (size_t)(utf8End - utf8));
1039 if (!model.fGlyphs[i].fUnsafeToBreak) {
1040 // Store up to the first glyph in the cluster.
1041 size_t currentCluster = model.fGlyphs[i].fCluster - modelStartCluster;
1042 if (previousCluster != currentCluster) {
1043 previousCluster = currentCluster;
1044 modelText[currentCluster].glyphLen = i;
1045 modelText[currentCluster].advance = advance;
1046 }
1047 }
1048 advance += model.fGlyphs[i].fAdvance;
1049 }
1050 // Assume it is always safe to break after the end of an item
1051 modelText[utf8runLength].glyphLen = model.fNumGlyphs;
1052 modelText[utf8runLength].advance = model.fAdvance;
1053 modelTextOffset = 0;
1054 modelAdvanceOffset = {0, 0};
1055 modelNeedsRegenerated = false;
1056 }
1057
1058 // TODO: break iterator per item, but just reset position if needed?
1059 // Maybe break iterator with model?
1060 if (!lineBreakIterator || !currentLanguage.equals(language.currentLanguage())) {
1061 currentLanguage = language.currentLanguage();
1062 lineBreakIterator = fUnicode->makeBreakIterator(currentLanguage.c_str(),
1063 SkUnicode::BreakType::kLines);
1064 if (!lineBreakIterator) {
1065 return;
1066 }
1067 }
1068 if (!lineBreakIterator->setText(utf8Start, utf8runLength)) {
1069 return;
1070 }
1071 SkBreakIterator& breakIterator = *lineBreakIterator;
1072
1073 #ifdef ENABLE_TEXT_ENHANCE
1074 ShapedRun best(RunHandler::Range(), RSFont(), 0, nullptr, 0,
1075 { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity });
1076 #else
1077 ShapedRun best(RunHandler::Range(), SkFont(), 0, nullptr, 0,
1078 { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity });
1079 #endif
1080 bool bestIsInvalid = true;
1081 bool bestUsesModelForGlyphs = false;
1082 SkScalar widthLeft = width - line.fAdvance.fX;
1083
1084 for (int32_t breakIteratorCurrent = breakIterator.next();
1085 !breakIterator.isDone();
1086 breakIteratorCurrent = breakIterator.next())
1087 {
1088 // TODO: if past a safe to break, future safe to break will be at least as long
1089
1090 // TODO: adjust breakIteratorCurrent by ignorable whitespace
1091 bool candidateUsesModelForGlyphs = false;
1092 ShapedRun candidate = [&](const TextProps& props){
1093 if (props.glyphLen) {
1094 candidateUsesModelForGlyphs = true;
1095 return ShapedRun(RunHandler::Range(utf8Start - utf8, breakIteratorCurrent),
1096 font.currentFont(), bidi.currentLevel(),
1097 std::unique_ptr<ShapedGlyph[]>(),
1098 props.glyphLen - modelGlyphOffset,
1099 props.advance - modelAdvanceOffset);
1100 } else {
1101 return shape(utf8, utf8Bytes,
1102 utf8Start, utf8Start + breakIteratorCurrent,
1103 bidi, language, script, font,
1104 features, featuresSize);
1105 }
1106 }(modelText[breakIteratorCurrent + modelTextOffset]);
1107 auto score = [widthLeft](const ShapedRun& run) -> SkScalar {
1108 if (run.fAdvance.fX < widthLeft) {
1109 return run.fUtf8Range.size();
1110 } else {
1111 return widthLeft - run.fAdvance.fX;
1112 }
1113 };
1114 if (bestIsInvalid || score(best) < score(candidate)) {
1115 best = std::move(candidate);
1116 bestIsInvalid = false;
1117 bestUsesModelForGlyphs = candidateUsesModelForGlyphs;
1118 }
1119 }
1120
1121 // If nothing fit (best score is negative) and the line is not empty
1122 if (width < line.fAdvance.fX + best.fAdvance.fX && !line.runs.empty()) {
1123 emit(fUnicode.get(), line, handler);
1124 line.runs.clear();
1125 line.fAdvance = {0, 0};
1126 } else {
1127 if (bestUsesModelForGlyphs) {
1128 best.fGlyphs = std::make_unique<ShapedGlyph[]>(best.fNumGlyphs);
1129 memcpy(best.fGlyphs.get(), model.fGlyphs.get() + modelGlyphOffset,
1130 best.fNumGlyphs * sizeof(ShapedGlyph));
1131 modelGlyphOffset += best.fNumGlyphs;
1132 modelTextOffset += best.fUtf8Range.size();
1133 modelAdvanceOffset += best.fAdvance;
1134 } else {
1135 modelNeedsRegenerated = true;
1136 }
1137 utf8Start += best.fUtf8Range.size();
1138 line.fAdvance += best.fAdvance;
1139 line.runs.emplace_back(std::move(best));
1140
1141 // If item broken, emit line (prevent remainder from accidentally fitting)
1142 if (utf8Start != utf8End) {
1143 emit(fUnicode.get(), line, handler);
1144 line.runs.clear();
1145 line.fAdvance = {0, 0};
1146 }
1147 }
1148 }
1149 }
1150 emit(fUnicode.get(), line, handler);
1151 }
1152
1153 void ShapeThenWrap::wrap(char const * const utf8, size_t utf8Bytes,
1154 const BiDiRunIterator& bidi,
1155 const LanguageRunIterator& language,
1156 const ScriptRunIterator& script,
1157 const FontRunIterator& font,
1158 RunIteratorQueue& runSegmenter,
1159 const Feature* features, size_t featuresSize,
1160 SkScalar width,
1161 RunHandler* handler) const
1162 {
1163 TArray<ShapedRun> runs;
1164 {
1165 SkString currentLanguage;
1166 SkUnicodeBreak lineBreakIterator;
1167 SkUnicodeBreak graphemeBreakIterator;
1168 bool needIteratorInit = true;
1169 const char* utf8Start = nullptr;
1170 const char* utf8End = utf8;
1171 while (runSegmenter.advanceRuns()) {
1172 utf8Start = utf8End;
1173 utf8End = utf8 + runSegmenter.endOfCurrentRun();
1174
1175 runs.emplace_back(shape(utf8, utf8Bytes,
1176 utf8Start, utf8End,
1177 bidi, language, script, font,
1178 features, featuresSize));
1179 ShapedRun& run = runs.back();
1180
1181 if (needIteratorInit || !currentLanguage.equals(language.currentLanguage())) {
1182 currentLanguage = language.currentLanguage();
1183 lineBreakIterator = fUnicode->makeBreakIterator(currentLanguage.c_str(),
1184 SkUnicode::BreakType::kLines);
1185 if (!lineBreakIterator) {
1186 return;
1187 }
1188 graphemeBreakIterator = fUnicode->makeBreakIterator(currentLanguage.c_str(),
1189 SkUnicode::BreakType::kGraphemes);
1190 if (!graphemeBreakIterator) {
1191 return;
1192 }
1193 needIteratorInit = false;
1194 }
1195 size_t utf8runLength = utf8End - utf8Start;
1196 if (!lineBreakIterator->setText(utf8Start, utf8runLength)) {
1197 return;
1198 }
1199 if (!graphemeBreakIterator->setText(utf8Start, utf8runLength)) {
1200 return;
1201 }
1202
1203 uint32_t previousCluster = 0xFFFFFFFF;
1204 for (size_t i = 0; i < run.fNumGlyphs; ++i) {
1205 ShapedGlyph& glyph = run.fGlyphs[i];
1206 int32_t glyphCluster = glyph.fCluster;
1207
1208 int32_t lineBreakIteratorCurrent = lineBreakIterator->current();
1209 while (!lineBreakIterator->isDone() && lineBreakIteratorCurrent < glyphCluster)
1210 {
1211 lineBreakIteratorCurrent = lineBreakIterator->next();
1212 }
1213 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
1214 lineBreakIteratorCurrent == glyphCluster;
1215
1216 int32_t graphemeBreakIteratorCurrent = graphemeBreakIterator->current();
1217 while (!graphemeBreakIterator->isDone() && graphemeBreakIteratorCurrent < glyphCluster)
1218 {
1219 graphemeBreakIteratorCurrent = graphemeBreakIterator->next();
1220 }
1221 glyph.fGraphemeBreakBefore = glyph.fCluster != previousCluster &&
1222 graphemeBreakIteratorCurrent == glyphCluster;
1223
1224 previousCluster = glyph.fCluster;
1225 }
1226 }
1227 }
1228
1229 // Iterate over the glyphs in logical order to find potential line lengths.
1230 {
1231 /** The position of the beginning of the line. */
1232 ShapedRunGlyphIterator beginning(runs);
1233
1234 /** The position of the candidate line break. */
1235 ShapedRunGlyphIterator candidateLineBreak(runs);
1236 SkScalar candidateLineBreakWidth = 0;
1237
1238 /** The position of the candidate grapheme break. */
1239 ShapedRunGlyphIterator candidateGraphemeBreak(runs);
1240 SkScalar candidateGraphemeBreakWidth = 0;
1241
1242 /** The position of the current location. */
1243 ShapedRunGlyphIterator current(runs);
1244 SkScalar currentWidth = 0;
1245 while (ShapedGlyph* glyph = current.current()) {
1246 // 'Break' at graphemes until a line boundary, then only at line boundaries.
1247 // Only break at graphemes if no line boundary is valid.
1248 if (current != beginning) {
1249 if (glyph->fGraphemeBreakBefore || glyph->fMayLineBreakBefore) {
1250 // TODO: preserve line breaks <= grapheme breaks
1251 // and prevent line breaks inside graphemes
1252 candidateGraphemeBreak = current;
1253 candidateGraphemeBreakWidth = currentWidth;
1254 if (glyph->fMayLineBreakBefore) {
1255 candidateLineBreak = current;
1256 candidateLineBreakWidth = currentWidth;
1257 }
1258 }
1259 }
1260
1261 SkScalar glyphWidth = glyph->fAdvance.fX;
1262 // Break when overwidth, the glyph has a visual representation, and some space is used.
1263 if (width < currentWidth + glyphWidth && glyph->fHasVisual && candidateGraphemeBreakWidth > 0){
1264 if (candidateLineBreak != beginning) {
1265 beginning = candidateLineBreak;
1266 currentWidth -= candidateLineBreakWidth;
1267 candidateGraphemeBreakWidth -= candidateLineBreakWidth;
1268 candidateLineBreakWidth = 0;
1269 } else if (candidateGraphemeBreak != beginning) {
1270 beginning = candidateGraphemeBreak;
1271 candidateLineBreak = beginning;
1272 currentWidth -= candidateGraphemeBreakWidth;
1273 candidateGraphemeBreakWidth = 0;
1274 candidateLineBreakWidth = 0;
1275 } else {
1276 SK_ABORT("");
1277 }
1278
1279 if (width < currentWidth) {
1280 if (width < candidateGraphemeBreakWidth) {
1281 candidateGraphemeBreak = candidateLineBreak;
1282 candidateGraphemeBreakWidth = candidateLineBreakWidth;
1283 }
1284 current = candidateGraphemeBreak;
1285 currentWidth = candidateGraphemeBreakWidth;
1286 }
1287
1288 glyph = beginning.current();
1289 if (glyph) {
1290 glyph->fMustLineBreakBefore = true;
1291 }
1292
1293 } else {
1294 current.next();
1295 currentWidth += glyphWidth;
1296 }
1297 }
1298 }
1299
1300 // Reorder the runs and glyphs per line and write them out.
1301 {
1302 ShapedRunGlyphIterator previousBreak(runs);
1303 ShapedRunGlyphIterator glyphIterator(runs);
1304 int previousRunIndex = -1;
1305 while (glyphIterator.current()) {
1306 const ShapedRunGlyphIterator current = glyphIterator;
1307 ShapedGlyph* nextGlyph = glyphIterator.next();
1308
1309 if (previousRunIndex != current.fRunIndex) {
1310 #ifdef ENABLE_TEXT_ENHANCE
1311 RSFontMetrics metrics;
1312 runs[current.fRunIndex].fFont.GetMetrics(&metrics);
1313 #else
1314 SkFontMetrics metrics;
1315 runs[current.fRunIndex].fFont.getMetrics(&metrics);
1316 #endif
1317 previousRunIndex = current.fRunIndex;
1318 }
1319
1320 // Nothing can be written until the baseline is known.
1321 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
1322 continue;
1323 }
1324
1325 int numRuns = current.fRunIndex - previousBreak.fRunIndex + 1;
1326 AutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
1327 for (int i = 0; i < numRuns; ++i) {
1328 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
1329 }
1330 AutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
1331 fUnicode->reorderVisual(runLevels, numRuns, logicalFromVisual);
1332
1333 // step through the runs in reverse visual order and the glyphs in reverse logical order
1334 // until a visible glyph is found and force them to the end of the visual line.
1335
1336 handler->beginLine();
1337
1338 struct SubRun { const ShapedRun& run; size_t startGlyphIndex; size_t endGlyphIndex; };
1339 auto makeSubRun = [&runs, &previousBreak, ¤t, &logicalFromVisual](size_t visualIndex){
1340 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[visualIndex];
1341 const auto& run = runs[logicalIndex];
1342 size_t startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
1343 ? previousBreak.fGlyphIndex
1344 : 0;
1345 size_t endGlyphIndex = (logicalIndex == current.fRunIndex)
1346 ? current.fGlyphIndex + 1
1347 : run.fNumGlyphs;
1348 return SubRun{ run, startGlyphIndex, endGlyphIndex };
1349 };
1350 auto makeRunInfo = [](const SubRun& sub) {
1351 uint32_t startUtf8 = sub.run.fGlyphs[sub.startGlyphIndex].fCluster;
1352 uint32_t endUtf8 = (sub.endGlyphIndex < sub.run.fNumGlyphs)
1353 ? sub.run.fGlyphs[sub.endGlyphIndex].fCluster
1354 : sub.run.fUtf8Range.end();
1355
1356 SkVector advance = SkVector::Make(0, 0);
1357 for (size_t i = sub.startGlyphIndex; i < sub.endGlyphIndex; ++i) {
1358 advance += sub.run.fGlyphs[i].fAdvance;
1359 }
1360
1361 return RunHandler::RunInfo{
1362 sub.run.fFont,
1363 sub.run.fLevel,
1364 advance,
1365 sub.endGlyphIndex - sub.startGlyphIndex,
1366 RunHandler::Range(startUtf8, endUtf8 - startUtf8)
1367 };
1368 };
1369
1370 for (int i = 0; i < numRuns; ++i) {
1371 handler->runInfo(makeRunInfo(makeSubRun(i)));
1372 }
1373 handler->commitRunInfo();
1374 for (int i = 0; i < numRuns; ++i) {
1375 SubRun sub = makeSubRun(i);
1376 append(handler, makeRunInfo(sub), sub.run, sub.startGlyphIndex, sub.endGlyphIndex);
1377 }
1378
1379 handler->commitLine();
1380
1381 previousRunIndex = -1;
1382 previousBreak = glyphIterator;
1383 }
1384 }
1385 }
1386
1387 void ShapeDontWrapOrReorder::wrap(char const * const utf8, size_t utf8Bytes,
1388 const BiDiRunIterator& bidi,
1389 const LanguageRunIterator& language,
1390 const ScriptRunIterator& script,
1391 const FontRunIterator& font,
1392 RunIteratorQueue& runSegmenter,
1393 const Feature* features, size_t featuresSize,
1394 SkScalar width,
1395 RunHandler* handler) const
1396 {
1397 sk_ignore_unused_variable(width);
1398 TArray<ShapedRun> runs;
1399
1400 const char* utf8Start = nullptr;
1401 const char* utf8End = utf8;
1402 while (runSegmenter.advanceRuns()) {
1403 utf8Start = utf8End;
1404 utf8End = utf8 + runSegmenter.endOfCurrentRun();
1405
1406 runs.emplace_back(shape(utf8, utf8Bytes,
1407 utf8Start, utf8End,
1408 bidi, language, script, font,
1409 features, featuresSize));
1410 }
1411
1412 handler->beginLine();
1413 for (const auto& run : runs) {
1414 const RunHandler::RunInfo info = {
1415 run.fFont,
1416 run.fLevel,
1417 run.fAdvance,
1418 run.fNumGlyphs,
1419 run.fUtf8Range
1420 };
1421 handler->runInfo(info);
1422 }
1423 handler->commitRunInfo();
1424 for (const auto& run : runs) {
1425 const RunHandler::RunInfo info = {
1426 run.fFont,
1427 run.fLevel,
1428 run.fAdvance,
1429 run.fNumGlyphs,
1430 run.fUtf8Range
1431 };
1432 append(handler, info, run, 0, run.fNumGlyphs);
1433 }
1434 handler->commitLine();
1435 }
1436
1437 class HBLockedFaceCache {
1438 public:
1439 HBLockedFaceCache(SkLRUCache<SkTypefaceID, HBFont>& lruCache, SkMutex& mutex)
1440 : fLRUCache(lruCache), fMutex(mutex)
1441 {
1442 fMutex.acquire();
1443 }
1444 HBLockedFaceCache(const HBLockedFaceCache&) = delete;
1445 HBLockedFaceCache& operator=(const HBLockedFaceCache&) = delete;
1446 HBLockedFaceCache& operator=(HBLockedFaceCache&&) = delete;
1447
1448 ~HBLockedFaceCache() {
1449 fMutex.release();
1450 }
1451
1452 HBFont* find(SkTypefaceID fontId) {
1453 return fLRUCache.find(fontId);
1454 }
1455 HBFont* insert(SkTypefaceID fontId, HBFont hbFont) {
1456 return fLRUCache.insert(fontId, std::move(hbFont));
1457 }
1458 void reset() {
1459 fLRUCache.reset();
1460 }
1461 private:
1462 SkLRUCache<SkTypefaceID, HBFont>& fLRUCache;
1463 SkMutex& fMutex;
1464 };
1465 static HBLockedFaceCache get_hbFace_cache() {
1466 static SkMutex gHBFaceCacheMutex;
1467 static SkLRUCache<SkTypefaceID, HBFont> gHBFaceCache(100);
1468 return HBLockedFaceCache(gHBFaceCache, gHBFaceCacheMutex);
1469 }
1470
1471 ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
1472 size_t const utf8Bytes,
1473 char const * const utf8Start,
1474 char const * const utf8End,
1475 const BiDiRunIterator& bidi,
1476 const LanguageRunIterator& language,
1477 const ScriptRunIterator& script,
1478 const FontRunIterator& font,
1479 Feature const * const features, size_t const featuresSize) const
1480 {
1481 size_t utf8runLength = utf8End - utf8Start;
1482 ShapedRun run(RunHandler::Range(utf8Start - utf8, utf8runLength),
1483 font.currentFont(), bidi.currentLevel(), nullptr, 0);
1484
1485 hb_buffer_t* buffer = fBuffer.get();
1486 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
1487 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1488 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
1489
1490 // Documentation for HB_BUFFER_FLAG_BOT/EOT at 763e5466c0a03a7c27020e1e2598e488612529a7.
1491 // Currently BOT forces a dotted circle when first codepoint is a mark; EOT has no effect.
1492 // Avoid adding dotted circle, re-evaluate if BOT/EOT change. See https://skbug.com/9618.
1493 // hb_buffer_set_flags(buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
1494
1495 // Add precontext.
1496 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
1497
1498 // Populate the hb_buffer directly with utf8 cluster indexes.
1499 const char* utf8Current = utf8Start;
1500 while (utf8Current < utf8End) {
1501 unsigned int cluster = utf8Current - utf8;
1502 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
1503 hb_buffer_add(buffer, u, cluster);
1504 }
1505
1506 // Add postcontext.
1507 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
1508
1509 hb_direction_t direction = is_LTR(bidi.currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
1510 hb_buffer_set_direction(buffer, direction);
1511 hb_buffer_set_script(buffer, hb_script_from_iso15924_tag((hb_tag_t)script.currentScript()));
1512 // Buffers with HB_LANGUAGE_INVALID race since hb_language_get_default is not thread safe.
1513 // The user must provide a language, but may provide data hb_language_from_string cannot use.
1514 // Use "und" for the undefined language in this case (RFC5646 4.1 5).
1515 hb_language_t hbLanguage = hb_language_from_string(language.currentLanguage(), -1);
1516 if (hbLanguage == HB_LANGUAGE_INVALID) {
1517 hbLanguage = fUndefinedLanguage;
1518 }
1519 hb_buffer_set_language(buffer, hbLanguage);
1520 hb_buffer_guess_segment_properties(buffer);
1521
1522 // TODO: better cache HBFace (data) / hbfont (typeface)
1523 // An HBFace is expensive (it sanitizes the bits).
1524 // An HBFont is fairly inexpensive.
1525 // An HBFace is actually tied to the data, not the typeface.
1526 // The size of 100 here is completely arbitrary and used to match libtxt.
1527 HBFont hbFont;
1528 {
1529 HBLockedFaceCache cache = get_hbFace_cache();
1530 #ifdef ENABLE_TEXT_ENHANCE
1531 uint32_t dataId = const_cast<RSFont&>(font.currentFont()).GetTypeface()->GetUniqueID();
1532 #else
1533 SkTypefaceID dataId = font.currentFont().getTypeface()->uniqueID();
1534 #endif
1535 HBFont* typefaceFontCached = cache.find(dataId);
1536 if (!typefaceFontCached) {
1537 #ifdef ENABLE_TEXT_ENHANCE
1538 HBFont typefaceFont(create_typeface_hb_font(*const_cast<RSFont&>(font.currentFont()).GetTypeface()));
1539 #else
1540 HBFont typefaceFont(create_typeface_hb_font(*font.currentFont().getTypeface()));
1541 #endif
1542 typefaceFontCached = cache.insert(dataId, std::move(typefaceFont));
1543 }
1544 hbFont = create_sub_hb_font(font.currentFont(), *typefaceFontCached);
1545 }
1546 if (!hbFont) {
1547 return run;
1548 }
1549
1550 STArray<32, hb_feature_t> hbFeatures;
1551 for (const auto& feature : SkSpan(features, featuresSize)) {
1552 if (feature.end < SkTo<size_t>(utf8Start - utf8) ||
1553 SkTo<size_t>(utf8End - utf8) <= feature.start)
1554 {
1555 continue;
1556 }
1557 if (feature.start <= SkTo<size_t>(utf8Start - utf8) &&
1558 SkTo<size_t>(utf8End - utf8) <= feature.end)
1559 {
1560 hbFeatures.push_back({ (hb_tag_t)feature.tag, feature.value,
1561 HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END});
1562 } else {
1563 hbFeatures.push_back({ (hb_tag_t)feature.tag, feature.value,
1564 SkTo<unsigned>(feature.start), SkTo<unsigned>(feature.end)});
1565 }
1566 }
1567
1568 hb_shape(hbFont.get(), buffer, hbFeatures.data(), hbFeatures.size());
1569 unsigned len = hb_buffer_get_length(buffer);
1570 if (len == 0) {
1571 return run;
1572 }
1573
1574 if (direction == HB_DIRECTION_RTL) {
1575 // Put the clusters back in logical order.
1576 // Note that the advances remain ltr.
1577 hb_buffer_reverse(buffer);
1578 }
1579 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
1580 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
1581
1582 run = ShapedRun(RunHandler::Range(utf8Start - utf8, utf8runLength),
1583 font.currentFont(), bidi.currentLevel(),
1584 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]), len);
1585
1586 // Undo skhb_position with (1.0/(1<<16)) and scale as needed.
1587 AutoSTArray<32, SkGlyphID> glyphIDs(len);
1588 for (unsigned i = 0; i < len; i++) {
1589 glyphIDs[i] = info[i].codepoint;
1590 }
1591 #ifdef ENABLE_TEXT_ENHANCE
1592 AutoSTArray<32, RSRect> glyphBounds(len);
1593 run.fFont.GetWidths(glyphIDs.get(), len, nullptr, glyphBounds.get());
1594 #else
1595 AutoSTArray<32, SkRect> glyphBounds(len);
1596 SkPaint p;
1597 run.fFont.getBounds(glyphIDs.get(), len, glyphBounds.get(), &p);
1598 #endif
1599
1600 #ifdef ENABLE_TEXT_ENHANCE
1601 double SkScalarFromHBPosX = +(1.52587890625e-5) * run.fFont.GetScaleX();
1602 #else
1603 double SkScalarFromHBPosX = +(1.52587890625e-5) * run.fFont.getScaleX();
1604 #endif
1605 double SkScalarFromHBPosY = -(1.52587890625e-5); // HarfBuzz y-up, Skia y-down
1606 SkVector runAdvance = { 0, 0 };
1607 for (unsigned i = 0; i < len; i++) {
1608 ShapedGlyph& glyph = run.fGlyphs[i];
1609 glyph.fID = info[i].codepoint;
1610 glyph.fCluster = info[i].cluster;
1611 glyph.fOffset.fX = pos[i].x_offset * SkScalarFromHBPosX;
1612 glyph.fOffset.fY = pos[i].y_offset * SkScalarFromHBPosY;
1613 glyph.fAdvance.fX = pos[i].x_advance * SkScalarFromHBPosX;
1614 glyph.fAdvance.fY = pos[i].y_advance * SkScalarFromHBPosY;
1615
1616 #ifdef ENABLE_TEXT_ENHANCE
1617 glyph.fHasVisual = !glyphBounds[i].IsEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1618 #else
1619 glyph.fHasVisual = !glyphBounds[i].isEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1620 #endif
1621 #if SK_HB_VERSION_CHECK(1, 5, 0)
1622 glyph.fUnsafeToBreak = info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
1623 #else
1624 glyph.fUnsafeToBreak = false;
1625 #endif
1626 glyph.fMustLineBreakBefore = false;
1627
1628 runAdvance += glyph.fAdvance;
1629 }
1630 run.fAdvance = runAdvance;
1631
1632 return run;
1633 }
1634 } // namespace
1635
1636 #if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
1637
1638 #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
1639 #include "modules/skunicode/include/SkUnicode_icu.h"
1640 #endif
1641
1642 #if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
1643 #include "modules/skunicode/include/SkUnicode_libgrapheme.h"
1644 #endif
1645
1646 #if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
1647 #include "modules/skunicode/include/SkUnicode_icu4x.h"
1648 #endif
1649
1650 static sk_sp<SkUnicode> get_unicode() {
1651 #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
1652 if (auto unicode = SkUnicodes::ICU::Make()) {
1653 return unicode;
1654 }
1655 #endif // defined(SK_UNICODE_ICU_IMPLEMENTATION)
1656 #if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
1657 if (auto unicode = SkUnicodes::Libgrapheme::Make()) {
1658 return unicode;
1659 }
1660 #endif
1661 #if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
1662 if (auto unicode = SkUnicodes::ICU4X::Make()) {
1663 return unicode;
1664 }
1665 #endif
1666 return nullptr;
1667 }
1668
1669 #ifdef ENABLE_DRAWING_ADAPTER
1670 namespace SkiaRsText {
1671 #endif
1672 std::unique_ptr<SkShaper::ScriptRunIterator>
1673 SkShaper::MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1674 return SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes);
1675 }
1676
1677 std::unique_ptr<SkShaper::ScriptRunIterator>
1678 SkShaper::MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1679 return SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes);
1680 }
1681
1682 std::unique_ptr<SkShaper::ScriptRunIterator> SkShaper::MakeSkUnicodeHbScriptRunIterator(
1683 const char* utf8, size_t utf8Bytes, SkFourByteTag script) {
1684 return SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes, script);
1685 }
1686
1687 #ifdef ENABLE_TEXT_ENHANCE
1688 std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(std::shared_ptr<RSFontMgr> fontmgr) {
1689 return SkShapers::HB::ShaperDrivenWrapper(get_unicode(), fontmgr);
1690 }
1691
1692 std::unique_ptr<SkShaper> SkShaper::MakeShapeThenWrap(std::shared_ptr<RSFontMgr> fontmgr) {
1693 return SkShapers::HB::ShapeThenWrap(get_unicode(), fontmgr);
1694 }
1695 #else
1696 std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fontmgr) {
1697 return SkShapers::HB::ShaperDrivenWrapper(get_unicode(), fontmgr);
1698 }
1699
1700 std::unique_ptr<SkShaper> SkShaper::MakeShapeThenWrap(sk_sp<SkFontMgr> fontmgr) {
1701 return SkShapers::HB::ShapeThenWrap(get_unicode(), fontmgr);
1702 }
1703 #endif // ENABLE_TEXT_ENHANCE
1704
1705 void SkShaper::PurgeHarfBuzzCache() { SkShapers::HB::PurgeCaches(); }
1706 #endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
1707
1708 namespace SkShapers::HB {
1709 #ifdef ENABLE_TEXT_ENHANCE
1710 std::unique_ptr<SkShaper> ShaperDrivenWrapper(sk_sp<SkUnicode> unicode,
1711 std::shared_ptr<RSFontMgr> fallback) {
1712 #else
1713 std::unique_ptr<SkShaper> ShaperDrivenWrapper(sk_sp<SkUnicode> unicode,
1714 sk_sp<SkFontMgr> fallback) {
1715 #endif
1716 if (!unicode) {
1717 return nullptr;
1718 }
1719 HBBuffer buffer(hb_buffer_create());
1720 if (!buffer) {
1721 SkDEBUGF("Could not create hb_buffer");
1722 return nullptr;
1723 }
1724 return std::make_unique<::ShaperDrivenWrapper>(
1725 unicode, std::move(buffer), std::move(fallback));
1726 }
1727
1728 #ifdef ENABLE_TEXT_ENHANCE
1729 std::unique_ptr<SkShaper> ShapeThenWrap(sk_sp<SkUnicode> unicode,
1730 std::shared_ptr<RSFontMgr> fallback) {
1731
1732 #else
1733 std::unique_ptr<SkShaper> ShapeThenWrap(sk_sp<SkUnicode> unicode,
1734 sk_sp<SkFontMgr> fallback) {
1735 #endif
1736 if (!unicode) {
1737 return nullptr;
1738 }
1739 HBBuffer buffer(hb_buffer_create());
1740 if (!buffer) {
1741 SkDEBUGF("Could not create hb_buffer");
1742 return nullptr;
1743 }
1744 return std::make_unique<::ShapeThenWrap>(
1745 unicode, std::move(buffer), std::move(fallback));
1746 }
1747
1748 #ifdef ENABLE_TEXT_ENHANCE
1749 std::unique_ptr<SkShaper> ShapeDontWrapOrReorder(sk_sp<SkUnicode> unicode,
1750 std::shared_ptr<RSFontMgr> fallback) {
1751 #else
1752 std::unique_ptr<SkShaper> ShapeDontWrapOrReorder(sk_sp<SkUnicode> unicode,
1753 sk_sp<SkFontMgr> fallback) {
1754 #endif
1755 if (!unicode) {
1756 return nullptr;
1757 }
1758 HBBuffer buffer(hb_buffer_create());
1759 if (!buffer) {
1760 SkDEBUGF("Could not create hb_buffer");
1761 return nullptr;
1762 }
1763 return std::make_unique<::ShapeDontWrapOrReorder>(
1764 unicode, std::move(buffer), std::move(fallback));
1765 }
1766
1767 std::unique_ptr<SkShaper::ScriptRunIterator> ScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1768 return std::make_unique<SkUnicodeHbScriptRunIterator>(utf8, utf8Bytes, HB_SCRIPT_UNKNOWN);
1769 }
1770 std::unique_ptr<SkShaper::ScriptRunIterator> ScriptRunIterator(const char* utf8,
1771 size_t utf8Bytes,
1772 SkFourByteTag script) {
1773 return std::make_unique<SkUnicodeHbScriptRunIterator>(
1774 utf8, utf8Bytes, hb_script_from_iso15924_tag((hb_tag_t)script));
1775 }
1776
1777 void PurgeCaches() {
1778 HBLockedFaceCache cache = get_hbFace_cache();
1779 cache.reset();
1780 }
1781 } // namespace SkShapers::HB
1782 #ifdef ENABLE_DRAWING_ADAPTER
1783 } // namespace SkiaRsText
1784 #endif // ENABLE_DRAWING_ADAPTER