• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkFontArguments.h"
9 #include "SkFontMgr.h"
10 #include "SkLoadICU.h"
11 #include "SkMalloc.h"
12 #include "SkOnce.h"
13 #include "SkFont.h"
14 #include "SkFontMetrics.h"
15 #include "SkPoint.h"
16 #include "SkRefCnt.h"
17 #include "SkScalar.h"
18 #include "SkShaper.h"
19 #include "SkStream.h"
20 #include "SkString.h"
21 #include "SkTArray.h"
22 #include "SkTDPQueue.h"
23 #include "SkTFitsIn.h"
24 #include "SkTLazy.h"
25 #include "SkTemplates.h"
26 #include "SkTo.h"
27 #include "SkTypeface.h"
28 #include "SkTypes.h"
29 #include "SkUTF.h"
30 
31 #include <hb.h>
32 #include <hb-ot.h>
33 #include <unicode/ubrk.h>
34 #include <unicode/ubidi.h>
35 #include <unicode/ustring.h>
36 #include <unicode/urename.h>
37 #include <unicode/utext.h>
38 #include <unicode/utypes.h>
39 
40 #include <memory>
41 #include <utility>
42 #include <cstring>
43 
44 namespace {
45 template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
46 using HBBlob   = resource<hb_blob_t     , hb_blob_destroy  >;
47 using HBFace   = resource<hb_face_t     , hb_face_destroy  >;
48 using HBFont   = resource<hb_font_t     , hb_font_destroy  >;
49 using HBBuffer = resource<hb_buffer_t   , hb_buffer_destroy>;
50 using ICUBiDi  = resource<UBiDi         , ubidi_close      >;
51 using ICUBrk   = resource<UBreakIterator, ubrk_close      >;
52 
stream_to_blob(std::unique_ptr<SkStreamAsset> asset)53 HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
54     size_t size = asset->getLength();
55     HBBlob blob;
56     if (const void* base = asset->getMemoryBase()) {
57         blob.reset(hb_blob_create((char*)base, SkToUInt(size),
58                                   HB_MEMORY_MODE_READONLY, asset.release(),
59                                   [](void* p) { delete (SkStreamAsset*)p; }));
60     } else {
61         // SkDebugf("Extra SkStreamAsset copy\n");
62         void* ptr = size ? sk_malloc_throw(size) : nullptr;
63         asset->read(ptr, size);
64         blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
65                                   HB_MEMORY_MODE_READONLY, ptr, sk_free));
66     }
67     SkASSERT(blob);
68     hb_blob_make_immutable(blob.get());
69     return blob;
70 }
71 
create_hb_font(SkTypeface * tf)72 HBFont create_hb_font(SkTypeface* tf) {
73     if (!tf) {
74         return nullptr;
75     }
76     int index;
77     std::unique_ptr<SkStreamAsset> typefaceAsset(tf->openStream(&index));
78     if (!typefaceAsset) {
79         SkString name;
80         tf->getFamilyName(&name);
81         SkDebugf("Typeface '%s' has no data :(\n", name.c_str());
82         return nullptr;
83     }
84     HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
85     HBFace face(hb_face_create(blob.get(), (unsigned)index));
86     SkASSERT(face);
87     if (!face) {
88         return nullptr;
89     }
90     hb_face_set_index(face.get(), (unsigned)index);
91     hb_face_set_upem(face.get(), tf->getUnitsPerEm());
92 
93     HBFont font(hb_font_create(face.get()));
94     SkASSERT(font);
95     if (!font) {
96         return nullptr;
97     }
98     hb_ot_font_set_funcs(font.get());
99     int axis_count = tf->getVariationDesignPosition(nullptr, 0);
100     if (axis_count > 0) {
101         SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
102         if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
103             hb_font_set_variations(font.get(),
104                                    reinterpret_cast<hb_variation_t*>(axis_values.get()),
105                                    axis_count);
106         }
107     }
108     return font;
109 }
110 
111 /** this version replaces invalid utf-8 sequences with code point U+FFFD. */
utf8_next(const char ** ptr,const char * end)112 static inline SkUnichar utf8_next(const char** ptr, const char* end) {
113     SkUnichar val = SkUTF::NextUTF8(ptr, end);
114     if (val < 0) {
115         return 0xFFFD;  // REPLACEMENT CHARACTER
116     }
117     return val;
118 }
119 
120 class RunIterator {
121 public:
~RunIterator()122     virtual ~RunIterator() {}
123     virtual void consume() = 0;
124     // Pointer one past the last (utf8) element in the current run.
125     virtual const char* endOfCurrentRun() const = 0;
126     virtual bool atEnd() const = 0;
operator <(const RunIterator & that) const127     bool operator<(const RunIterator& that) const {
128         return this->endOfCurrentRun() < that.endOfCurrentRun();
129     }
130 };
131 
132 class BiDiRunIterator : public RunIterator {
133 public:
Make(const char * utf8,size_t utf8Bytes,UBiDiLevel level)134     static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
135         SkTLazy<BiDiRunIterator> ret;
136 
137         // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
138         // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
139         if (!SkTFitsIn<int32_t>(utf8Bytes)) {
140             SkDebugf("Bidi error: text too long");
141             return ret;
142         }
143 
144         UErrorCode status = U_ZERO_ERROR;
145 
146         // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
147         int32_t utf16Units;
148         u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
149         status = U_ZERO_ERROR;
150         std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
151         u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
152         if (U_FAILURE(status)) {
153             SkDebugf("Invalid utf8 input: %s", u_errorName(status));
154             return ret;
155         }
156 
157         ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
158         if (U_FAILURE(status)) {
159             SkDebugf("Bidi error: %s", u_errorName(status));
160             return ret;
161         }
162         SkASSERT(bidi);
163 
164         // The required lifetime of utf16 isn't well documented.
165         // It appears it isn't used after ubidi_setPara except through ubidi_getText.
166         ubidi_setPara(bidi.get(), utf16.get(), utf16Units, level, nullptr, &status);
167         if (U_FAILURE(status)) {
168             SkDebugf("Bidi error: %s", u_errorName(status));
169             return ret;
170         }
171 
172         ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
173         return ret;
174     }
BiDiRunIterator(const char * utf8,const char * end,ICUBiDi bidi)175     BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
176         : fBidi(std::move(bidi))
177         , fEndOfCurrentRun(utf8)
178         , fEndOfAllRuns(end)
179         , fUTF16LogicalPosition(0)
180         , fLevel(UBIDI_DEFAULT_LTR)
181     {}
consume()182     void consume() override {
183         SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
184         int32_t endPosition = ubidi_getLength(fBidi.get());
185         fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
186         SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
187         fUTF16LogicalPosition += SkUTF::ToUTF16(u);
188         UBiDiLevel level;
189         while (fUTF16LogicalPosition < endPosition) {
190             level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
191             if (level != fLevel) {
192                 break;
193             }
194             u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
195             fUTF16LogicalPosition += SkUTF::ToUTF16(u);
196         }
197     }
endOfCurrentRun() const198     const char* endOfCurrentRun() const override {
199         return fEndOfCurrentRun;
200     }
atEnd() const201     bool atEnd() const override {
202         return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
203     }
204 
currentLevel() const205     UBiDiLevel currentLevel() const {
206         return fLevel;
207     }
208 private:
209     ICUBiDi fBidi;
210     const char* fEndOfCurrentRun;
211     const char* fEndOfAllRuns;
212     int32_t fUTF16LogicalPosition;
213     UBiDiLevel fLevel;
214 };
215 
216 class ScriptRunIterator : public RunIterator {
217 public:
Make(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)218     static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
219                                            hb_unicode_funcs_t* hbUnicode)
220     {
221         SkTLazy<ScriptRunIterator> ret;
222         ret.init(utf8, utf8Bytes, hbUnicode);
223         return ret;
224     }
ScriptRunIterator(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)225     ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
226         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
227         , fHBUnicode(hbUnicode)
228         , fCurrentScript(HB_SCRIPT_UNKNOWN)
229     {}
consume()230     void consume() override {
231         SkASSERT(fCurrent < fEnd);
232         SkUnichar u = utf8_next(&fCurrent, fEnd);
233         fCurrentScript = hb_unicode_script(fHBUnicode, u);
234         while (fCurrent < fEnd) {
235             const char* prev = fCurrent;
236             u = utf8_next(&fCurrent, fEnd);
237             const hb_script_t script = hb_unicode_script(fHBUnicode, u);
238             if (script != fCurrentScript) {
239                 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
240                     fCurrentScript = script;
241                 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
242                     continue;
243                 } else {
244                     fCurrent = prev;
245                     break;
246                 }
247             }
248         }
249         if (fCurrentScript == HB_SCRIPT_INHERITED) {
250             fCurrentScript = HB_SCRIPT_COMMON;
251         }
252     }
endOfCurrentRun() const253     const char* endOfCurrentRun() const override {
254         return fCurrent;
255     }
atEnd() const256     bool atEnd() const override {
257         return fCurrent == fEnd;
258     }
259 
currentScript() const260     hb_script_t currentScript() const {
261         return fCurrentScript;
262     }
263 private:
264     const char* fCurrent;
265     const char* fEnd;
266     hb_unicode_funcs_t* fHBUnicode;
267     hb_script_t fCurrentScript;
268 };
269 
270 class FontRunIterator : public RunIterator {
271 public:
Make(const char * utf8,size_t utf8Bytes,sk_sp<SkTypeface> typeface,hb_font_t * hbFace,sk_sp<SkFontMgr> fallbackMgr)272     static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
273                                          sk_sp<SkTypeface> typeface,
274                                          hb_font_t* hbFace,
275                                          sk_sp<SkFontMgr> fallbackMgr)
276     {
277         SkTLazy<FontRunIterator> ret;
278         ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
279         return ret;
280     }
FontRunIterator(const char * utf8,size_t utf8Bytes,sk_sp<SkTypeface> typeface,hb_font_t * hbFace,sk_sp<SkFontMgr> fallbackMgr)281     FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
282                     hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
283         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
284         , fFallbackMgr(std::move(fallbackMgr))
285         , fHBFont(hbFace), fTypeface(std::move(typeface))
286         , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
287         , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
288     {}
consume()289     void consume() override {
290         SkASSERT(fCurrent < fEnd);
291         SkUnichar u = utf8_next(&fCurrent, fEnd);
292         // If the starting typeface can handle this character, use it.
293         if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
294             fCurrentTypeface = fTypeface.get();
295             fCurrentHBFont = fHBFont;
296         // If the current fallback can handle this character, use it.
297         } else if (fFallbackTypeface &&
298                    fFallbackTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
299         {
300             fCurrentTypeface = fFallbackTypeface.get();
301             fCurrentHBFont = fFallbackHBFont.get();
302         // If not, try to find a fallback typeface
303         } else {
304             fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
305                 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
306             fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
307             fCurrentTypeface = fFallbackTypeface.get();
308             fCurrentHBFont = fFallbackHBFont.get();
309         }
310 
311         while (fCurrent < fEnd) {
312             const char* prev = fCurrent;
313             u = utf8_next(&fCurrent, fEnd);
314 
315             // If not using initial typeface and initial typeface has this character, stop fallback.
316             if (fCurrentTypeface != fTypeface.get() &&
317                 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
318             {
319                 fCurrent = prev;
320                 return;
321             }
322             // If the current typeface cannot handle this character, stop using it.
323             if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
324                 fCurrent = prev;
325                 return;
326             }
327         }
328     }
endOfCurrentRun() const329     const char* endOfCurrentRun() const override {
330         return fCurrent;
331     }
atEnd() const332     bool atEnd() const override {
333         return fCurrent == fEnd;
334     }
335 
currentTypeface() const336     SkTypeface* currentTypeface() const {
337         return fCurrentTypeface;
338     }
currentHBFont() const339     hb_font_t* currentHBFont() const {
340         return fCurrentHBFont;
341     }
342 private:
343     const char* fCurrent;
344     const char* fEnd;
345     sk_sp<SkFontMgr> fFallbackMgr;
346     hb_font_t* fHBFont;
347     sk_sp<SkTypeface> fTypeface;
348     HBFont fFallbackHBFont;
349     sk_sp<SkTypeface> fFallbackTypeface;
350     hb_font_t* fCurrentHBFont;
351     SkTypeface* fCurrentTypeface;
352 };
353 
354 class RunIteratorQueue {
355 public:
insert(RunIterator * runIterator)356     void insert(RunIterator* runIterator) {
357         fRunIterators.insert(runIterator);
358     }
359 
advanceRuns()360     bool advanceRuns() {
361         const RunIterator* leastRun = fRunIterators.peek();
362         if (leastRun->atEnd()) {
363             SkASSERT(this->allRunsAreAtEnd());
364             return false;
365         }
366         const char* leastEnd = leastRun->endOfCurrentRun();
367         RunIterator* currentRun = nullptr;
368         SkDEBUGCODE(const char* previousEndOfCurrentRun);
369         while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
370             fRunIterators.pop();
371             SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
372             currentRun->consume();
373             SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
374             fRunIterators.insert(currentRun);
375         }
376         return true;
377     }
378 
endOfCurrentRun() const379     const char* endOfCurrentRun() const {
380         return fRunIterators.peek()->endOfCurrentRun();
381     }
382 
383 private:
allRunsAreAtEnd() const384     bool allRunsAreAtEnd() const {
385         for (int i = 0; i < fRunIterators.count(); ++i) {
386             if (!fRunIterators.at(i)->atEnd()) {
387                 return false;
388             }
389         }
390         return true;
391     }
392 
CompareRunIterator(RunIterator * const & a,RunIterator * const & b)393     static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
394         return *a < *b;
395     }
396     SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
397 };
398 
399 struct ShapedGlyph {
400     SkGlyphID fID;
401     uint32_t fCluster;
402     SkPoint fOffset;
403     SkVector fAdvance;
404     bool fMayLineBreakBefore;
405     bool fMustLineBreakBefore;
406     bool fHasVisual;
407 };
408 struct ShapedRun {
ShapedRun__anon7b0263360111::ShapedRun409     ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkFont& font,
410               UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
411         : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fFont(font)
412         , fLevel(level), fGlyphs(std::move(glyphs))
413     {}
414 
415     const char* fUtf8Start;
416     const char* fUtf8End;
417     int fNumGlyphs;
418     SkFont fFont;
419     UBiDiLevel fLevel;
420     std::unique_ptr<ShapedGlyph[]> fGlyphs;
421     SkVector fAdvance = { 0, 0 };
422 };
423 
is_LTR(UBiDiLevel level)424 static constexpr bool is_LTR(UBiDiLevel level) {
425     return (level & 1) == 0;
426 }
427 
append(SkShaper::RunHandler * handler,const SkShaper::RunHandler::RunInfo & runInfo,const ShapedRun & run,int start,int end,SkPoint * p)428 static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
429                    const ShapedRun& run, int start, int end,
430                    SkPoint* p) {
431     unsigned len = end - start;
432 
433     const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8End - run.fUtf8Start);
434     SkASSERT(buffer.glyphs);
435     SkASSERT(buffer.positions);
436 
437     if (buffer.utf8text) {
438         memcpy(buffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
439     }
440 
441     for (unsigned i = 0; i < len; i++) {
442         // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
443         const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
444         buffer.glyphs[i] = glyph.fID;
445         buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
446         if (buffer.clusters) {
447             buffer.clusters[i] = glyph.fCluster;
448         }
449         p->fX += glyph.fAdvance.fX;
450         p->fY += glyph.fAdvance.fY;
451     }
452 }
453 
454 struct ShapedRunGlyphIterator {
ShapedRunGlyphIterator__anon7b0263360111::ShapedRunGlyphIterator455     ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
456         : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
457     { }
458 
459     ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
460     ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
operator ==__anon7b0263360111::ShapedRunGlyphIterator461     bool operator==(const ShapedRunGlyphIterator& that) const {
462         return fRuns == that.fRuns &&
463                fRunIndex == that.fRunIndex &&
464                fGlyphIndex == that.fGlyphIndex;
465     }
operator !=__anon7b0263360111::ShapedRunGlyphIterator466     bool operator!=(const ShapedRunGlyphIterator& that) const {
467         return fRuns != that.fRuns ||
468                fRunIndex != that.fRunIndex ||
469                fGlyphIndex != that.fGlyphIndex;
470     }
471 
next__anon7b0263360111::ShapedRunGlyphIterator472     ShapedGlyph* next() {
473         const SkTArray<ShapedRun>& runs = *fRuns;
474         SkASSERT(fRunIndex < runs.count());
475         SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
476 
477         ++fGlyphIndex;
478         if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
479             fGlyphIndex = 0;
480             ++fRunIndex;
481             if (fRunIndex >= runs.count()) {
482                 return nullptr;
483             }
484         }
485         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
486     }
487 
current__anon7b0263360111::ShapedRunGlyphIterator488     ShapedGlyph* current() {
489         const SkTArray<ShapedRun>& runs = *fRuns;
490         if (fRunIndex >= runs.count()) {
491             return nullptr;
492         }
493         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
494     }
495 
496     const SkTArray<ShapedRun>* fRuns;
497     int fRunIndex;
498     int fGlyphIndex;
499 };
500 
501 }  // namespace
502 
503 struct SkShaper::Impl {
504     HBFont fHarfBuzzFont;
505     HBBuffer fBuffer;
506     sk_sp<SkTypeface> fTypeface;
507     ICUBrk fBreakIterator;
508 };
509 
SkShaper(sk_sp<SkTypeface> tf)510 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
511     SkOnce once;
512     once([] { SkLoadICU(); });
513 
514     fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
515     fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
516     if (!fImpl->fHarfBuzzFont) {
517         SkDebugf("create_hb_font failed!\n");
518     }
519     fImpl->fBuffer.reset(hb_buffer_create());
520     SkASSERT(fImpl->fBuffer);
521 
522     UErrorCode status = U_ZERO_ERROR;
523     fImpl->fBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
524     if (U_FAILURE(status)) {
525         SkDebugf("Could not create break iterator: %s", u_errorName(status));
526         SK_ABORT("");
527     }
528 }
529 
~SkShaper()530 SkShaper::~SkShaper() {}
531 
good() const532 bool SkShaper::good() const {
533     return fImpl->fHarfBuzzFont &&
534            fImpl->fBuffer &&
535            fImpl->fTypeface &&
536            fImpl->fBreakIterator;
537 }
538 
shape(RunHandler * handler,const SkFont & srcFont,const char * utf8,size_t utf8Bytes,bool leftToRight,SkPoint point,SkScalar width) const539 SkPoint SkShaper::shape(RunHandler* handler,
540                         const SkFont& srcFont,
541                         const char* utf8,
542                         size_t utf8Bytes,
543                         bool leftToRight,
544                         SkPoint point,
545                         SkScalar width) const {
546     sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
547     SkASSERT(handler);
548     UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
549     //hb_script_t script = ...
550 
551     SkTArray<ShapedRun> runs;
552 {
553     RunIteratorQueue runSegmenter;
554 
555     SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
556     BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
557     if (!bidi) {
558         return point;
559     }
560     runSegmenter.insert(bidi);
561 
562     hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
563     SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
564     ScriptRunIterator* script = maybeScript.getMaybeNull();
565     if (!script) {
566         return point;
567     }
568     runSegmenter.insert(script);
569 
570     SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
571                                                              fImpl->fTypeface,
572                                                              fImpl->fHarfBuzzFont.get(),
573                                                              std::move(fontMgr)));
574     FontRunIterator* font = maybeFont.getMaybeNull();
575     if (!font) {
576         return point;
577     }
578     runSegmenter.insert(font);
579 
580     UBreakIterator& breakIterator = *fImpl->fBreakIterator;
581     {
582         UErrorCode status = U_ZERO_ERROR;
583         UText utf8UText = UTEXT_INITIALIZER;
584         utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
585         std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
586         if (U_FAILURE(status)) {
587             SkDebugf("Could not create utf8UText: %s", u_errorName(status));
588             return point;
589         }
590         ubrk_setUText(&breakIterator, &utf8UText, &status);
591         //utext_close(&utf8UText);
592         if (U_FAILURE(status)) {
593             SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
594             return point;
595         }
596     }
597 
598     const char* utf8Start = nullptr;
599     const char* utf8End = utf8;
600     while (runSegmenter.advanceRuns()) {
601         utf8Start = utf8End;
602         utf8End = runSegmenter.endOfCurrentRun();
603 
604         hb_buffer_t* buffer = fImpl->fBuffer.get();
605         SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
606         hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
607         hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
608 
609         // Add precontext.
610         hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
611 
612         // Populate the hb_buffer directly with utf8 cluster indexes.
613         const char* utf8Current = utf8Start;
614         while (utf8Current < utf8End) {
615             unsigned int cluster = utf8Current - utf8Start;
616             hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
617             hb_buffer_add(buffer, u, cluster);
618         }
619 
620         // Add postcontext.
621         hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
622 
623         size_t utf8runLength = utf8End - utf8Start;
624         if (!SkTFitsIn<int>(utf8runLength)) {
625             SkDebugf("Shaping error: utf8 too long");
626             return point;
627         }
628         hb_buffer_set_script(buffer, script->currentScript());
629         hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
630         hb_buffer_set_direction(buffer, direction);
631         // TODO: language
632         hb_buffer_guess_segment_properties(buffer);
633         // TODO: features
634         if (!font->currentHBFont()) {
635             continue;
636         }
637         hb_shape(font->currentHBFont(), buffer, nullptr, 0);
638         unsigned len = hb_buffer_get_length(buffer);
639         if (len == 0) {
640             continue;
641         }
642 
643         if (direction == HB_DIRECTION_RTL) {
644             // Put the clusters back in logical order.
645             // Note that the advances remain ltr.
646             hb_buffer_reverse(buffer);
647         }
648         hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
649         hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
650 
651         if (!SkTFitsIn<int>(len)) {
652             SkDebugf("Shaping error: too many glyphs");
653             return point;
654         }
655 
656         SkFont runFont(srcFont);
657         runFont.setTypeface(sk_ref_sp(font->currentTypeface()));
658         ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, runFont, bidi->currentLevel(),
659                                            std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
660         int scaleX, scaleY;
661         hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
662         double textSizeY = run.fFont.getSize() / scaleY;
663         double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
664         SkVector runAdvance = { 0, 0 };
665         for (unsigned i = 0; i < len; i++) {
666             ShapedGlyph& glyph = run.fGlyphs[i];
667             glyph.fID = info[i].codepoint;
668             glyph.fCluster = info[i].cluster;
669             glyph.fOffset.fX = pos[i].x_offset * textSizeX;
670             glyph.fOffset.fY = pos[i].y_offset * textSizeY;
671             glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
672             glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
673             glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
674             //info->mask safe_to_break;
675             glyph.fMustLineBreakBefore = false;
676 
677             runAdvance += glyph.fAdvance;
678         }
679         run.fAdvance = runAdvance;
680 
681         int32_t clusterOffset = utf8Start - utf8;
682         uint32_t previousCluster = 0xFFFFFFFF;
683         for (unsigned i = 0; i < len; ++i) {
684             ShapedGlyph& glyph = run.fGlyphs[i];
685             int32_t glyphCluster = glyph.fCluster + clusterOffset;
686             int32_t breakIteratorCurrent = ubrk_current(&breakIterator);
687             while (breakIteratorCurrent != UBRK_DONE &&
688                    breakIteratorCurrent < glyphCluster)
689             {
690                 breakIteratorCurrent = ubrk_next(&breakIterator);
691             }
692             glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
693                                         breakIteratorCurrent == glyphCluster;
694             previousCluster = glyph.fCluster;
695         }
696     }
697 }
698 
699 // Iterate over the glyphs in logical order to mark line endings.
700 {
701     SkScalar widthSoFar = 0;
702     bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
703     bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
704     ShapedRunGlyphIterator previousBreak(runs);
705     ShapedRunGlyphIterator glyphIterator(runs);
706     while (ShapedGlyph* glyph = glyphIterator.current()) {
707         if (canAddBreakNow && glyph->fMayLineBreakBefore) {
708             previousBreakValid = true;
709             previousBreak = glyphIterator;
710         }
711         SkScalar glyphWidth = glyph->fAdvance.fX;
712         // TODO: if the glyph is non-visible it can be added.
713         if (widthSoFar + glyphWidth < width) {
714             widthSoFar += glyphWidth;
715             glyphIterator.next();
716             canAddBreakNow = true;
717             continue;
718         }
719 
720         // TODO: for both of these emergency break cases
721         // don't break grapheme clusters and pull in any zero width or non-visible
722         if (widthSoFar == 0) {
723             // Adding just this glyph is too much, just break with this glyph
724             glyphIterator.next();
725             previousBreak = glyphIterator;
726         } else if (!previousBreakValid) {
727             // No break opportunity found yet, just break without this glyph
728             previousBreak = glyphIterator;
729         }
730         glyphIterator = previousBreak;
731         glyph = glyphIterator.current();
732         if (glyph) {
733             glyph->fMustLineBreakBefore = true;
734         }
735         widthSoFar = 0;
736         previousBreakValid = false;
737         canAddBreakNow = false;
738     }
739 }
740 
741 // Reorder the runs and glyphs per line and write them out.
742     SkPoint currentPoint = point;
743 {
744     ShapedRunGlyphIterator previousBreak(runs);
745     ShapedRunGlyphIterator glyphIterator(runs);
746     SkScalar maxAscent = 0;
747     SkScalar maxDescent = 0;
748     SkScalar maxLeading = 0;
749     int previousRunIndex = -1;
750     size_t lineIndex = 0;
751     while (glyphIterator.current()) {
752         int runIndex = glyphIterator.fRunIndex;
753         int glyphIndex = glyphIterator.fGlyphIndex;
754         ShapedGlyph* nextGlyph = glyphIterator.next();
755 
756         if (previousRunIndex != runIndex) {
757             SkFontMetrics metrics;
758             runs[runIndex].fFont.getMetrics(&metrics);
759             maxAscent = SkTMin(maxAscent, metrics.fAscent);
760             maxDescent = SkTMax(maxDescent, metrics.fDescent);
761             maxLeading = SkTMax(maxLeading, metrics.fLeading);
762             previousRunIndex = runIndex;
763         }
764 
765         // Nothing can be written until the baseline is known.
766         if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
767             continue;
768         }
769 
770         currentPoint.fY -= maxAscent;
771 
772         int numRuns = runIndex - previousBreak.fRunIndex + 1;
773         SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
774         for (int i = 0; i < numRuns; ++i) {
775             runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
776         }
777         SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
778         ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
779 
780         for (int i = 0; i < numRuns; ++i) {
781             int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
782 
783             int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
784                                 ? previousBreak.fGlyphIndex
785                                 : 0;
786             int endGlyphIndex = (logicalIndex == runIndex)
787                               ? glyphIndex + 1
788                               : runs[logicalIndex].fNumGlyphs;
789 
790             const auto& run = runs[logicalIndex];
791             const RunHandler::RunInfo info = {
792                 lineIndex,
793                 run.fAdvance,
794                 maxAscent,
795                 maxDescent,
796                 maxLeading,
797             };
798             append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
799         }
800 
801         currentPoint.fY += maxDescent + maxLeading;
802         currentPoint.fX = point.fX;
803         maxAscent = 0;
804         maxDescent = 0;
805         maxLeading = 0;
806         previousRunIndex = -1;
807         ++lineIndex;
808         previousBreak = glyphIterator;
809     }
810 }
811 
812     return currentPoint;
813 }
814