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
55namespace sknonstd {
56template <> struct is_bitmask_enum<hb_buffer_flags_t> : std::true_type {};
57}  // namespace sknonstd
58
59namespace {
60template <typename T,typename P,P* p> using resource = std::unique_ptr<T, SkFunctionWrapper<P, p>>;
61using HBBlob   = resource<hb_blob_t     , decltype(hb_blob_destroy)  , hb_blob_destroy  >;
62using HBFace   = resource<hb_face_t     , decltype(hb_face_destroy)  , hb_face_destroy  >;
63using HBFont   = resource<hb_font_t     , decltype(hb_font_destroy)  , hb_font_destroy  >;
64using HBBuffer = resource<hb_buffer_t   , decltype(hb_buffer_destroy), hb_buffer_destroy>;
65
66using SkUnicodeBidi = std::unique_ptr<SkBidiIterator>;
67using SkUnicodeBreak = std::unique_ptr<SkBreakIterator>;
68
69hb_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
75hb_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
93hb_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
101unsigned 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
140hb_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
167void 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.
218hb_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
267hb_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
292hb_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
330HBBlob 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
349SkDEBUGCODE(static hb_user_data_key_t gDataIdKey;)
350
351HBFace 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
390HBFace 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
411HBFont create_typeface_hb_font(const SkTypeface& typeface) {
412#else
413HBFont 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
442HBFont 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
461HBFont 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. */
476static 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
481class SkUnicodeBidiRunIterator final : public SkShaper::BiDiRunIterator {
482public:
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    }
518private:
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
527class SkUnicodeHbScriptRunIterator final: public SkShaper::ScriptRunIterator {
528public:
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    }
572private:
573    char const * fCurrent;
574    char const * const fBegin;
575    char const * const fEnd;
576    hb_script_t fCurrentScript;
577};
578
579class RunIteratorQueue {
580public:
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
609private:
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
631struct 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
643struct 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
658struct 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
673struct ShapedLine {
674    SkTArray<ShapedRun> runs;
675    SkVector fAdvance = { 0, 0 };
676};
677
678constexpr bool is_LTR(SkBidiIterator::Level level) {
679    return (level & 1) == 0;
680}
681
682void 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
711void 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
754struct 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
801class ShaperHarfBuzz : public SkShaper {
802public:
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
813protected:
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;
826private:
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
873class ShaperDrivenWrapper : public ShaperHarfBuzz {
874public:
875    using ShaperHarfBuzz::ShaperHarfBuzz;
876private:
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
888class ShapeThenWrap : public ShaperHarfBuzz {
889public:
890    using ShaperHarfBuzz::ShaperHarfBuzz;
891private:
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
903class ShapeDontWrapOrReorder : public ShaperHarfBuzz {
904public:
905    using ShaperHarfBuzz::ShaperHarfBuzz;
906private:
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
919static std::unique_ptr<SkShaper> MakeHarfBuzz(sk_sp<SkFontMgr> fontmgr, bool correct) {
920#else
921static 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
954ShaperHarfBuzz::ShaperHarfBuzz(std::unique_ptr<SkUnicode> unicode,
955    SkUnicodeBreak lineIter, SkUnicodeBreak graphIter, HBBuffer buffer, sk_sp<SkFontMgr> fontmgr)
956#else
957ShaperHarfBuzz::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
968void 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
1014void 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
1025void 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
1045void 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
1202void 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
1419void 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
1469class HBLockedFaceCache {
1470public:
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    }
1495private:
1496    SkLRUCache<uint32_t, HBFont>& fLRUCache;
1497    SkMutex& fMutex;
1498};
1499static HBLockedFaceCache get_hbFace_cache() {
1500    static SkMutex gHBFaceCacheMutex;
1501    static SkLRUCache<uint32_t, HBFont> gHBFaceCache(100);
1502    return HBLockedFaceCache(gHBFaceCache, gHBFaceCacheMutex);
1503}
1504
1505ShapedRun 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
1675namespace SkiaRsText {
1676#endif
1677std::unique_ptr<SkShaper::BiDiRunIterator>
1678SkShaper::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
1689std::unique_ptr<SkShaper::BiDiRunIterator>
1690SkShaper::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
1717std::unique_ptr<SkShaper::ScriptRunIterator>
1718SkShaper::MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1719    return SkShaper::MakeSkUnicodeHbScriptRunIterator(utf8, utf8Bytes);
1720}
1721
1722std::unique_ptr<SkShaper::ScriptRunIterator>
1723SkShaper::MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1724    return std::make_unique<SkUnicodeHbScriptRunIterator>(utf8, utf8Bytes, HB_SCRIPT_UNKNOWN);
1725}
1726
1727std::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
1734std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fontmgr) {
1735    return MakeHarfBuzz(std::move(fontmgr), true);
1736}
1737std::unique_ptr<SkShaper> SkShaper::MakeShapeThenWrap(sk_sp<SkFontMgr> fontmgr) {
1738    return MakeHarfBuzz(std::move(fontmgr), false);
1739}
1740#else
1741std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(std::shared_ptr<RSFontMgr> fontmgr) {
1742    return MakeHarfBuzz(std::move(fontmgr), true);
1743}
1744std::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
1749std::unique_ptr<SkShaper> SkShaper::MakeShapeDontWrapOrReorder(std::unique_ptr<SkUnicode> unicode,
1750                                                               sk_sp<SkFontMgr> fontmgr) {
1751#else
1752std::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
1769void SkShaper::PurgeHarfBuzzCache() {
1770    HBLockedFaceCache cache = get_hbFace_cache();
1771    cache.reset();
1772}
1773#ifdef USE_SKIA_TXT
1774} // namespace SkiaRsText
1775#endif