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