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 <hb-ot.h>
9 #include <unicode/brkiter.h>
10 #include <unicode/locid.h>
11 #include <unicode/stringpiece.h>
12 #include <unicode/ubidi.h>
13 #include <unicode/uchriter.h>
14 #include <unicode/unistr.h>
15 #include <unicode/uscript.h>
16 
17 #include "SkFontMgr.h"
18 #include "SkShaper.h"
19 #include "SkStream.h"
20 #include "SkTDPQueue.h"
21 #include "SkTLazy.h"
22 #include "SkTemplates.h"
23 #include "SkTextBlob.h"
24 #include "SkTypeface.h"
25 #include "SkUtils.h"
26 
27 namespace {
28 template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
29 using HBBlob   = resource<hb_blob_t  , hb_blob_destroy  >;
30 using HBFace   = resource<hb_face_t  , hb_face_destroy  >;
31 using HBFont   = resource<hb_font_t  , hb_font_destroy  >;
32 using HBBuffer = resource<hb_buffer_t, hb_buffer_destroy>;
33 using ICUBiDi  = resource<UBiDi      , ubidi_close      >;
34 
stream_to_blob(std::unique_ptr<SkStreamAsset> asset)35 HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
36     size_t size = asset->getLength();
37     HBBlob blob;
38     if (const void* base = asset->getMemoryBase()) {
39         blob.reset(hb_blob_create((char*)base, SkToUInt(size),
40                                   HB_MEMORY_MODE_READONLY, asset.release(),
41                                   [](void* p) { delete (SkStreamAsset*)p; }));
42     } else {
43         // SkDebugf("Extra SkStreamAsset copy\n");
44         void* ptr = size ? sk_malloc_throw(size) : nullptr;
45         asset->read(ptr, size);
46         blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
47                                   HB_MEMORY_MODE_READONLY, ptr, sk_free));
48     }
49     SkASSERT(blob);
50     hb_blob_make_immutable(blob.get());
51     return blob;
52 }
53 
create_hb_font(SkTypeface * tf)54 HBFont create_hb_font(SkTypeface* tf) {
55     int index;
56     HBBlob blob(stream_to_blob(std::unique_ptr<SkStreamAsset>(tf->openStream(&index))));
57     HBFace face(hb_face_create(blob.get(), (unsigned)index));
58     SkASSERT(face);
59     if (!face) {
60         return nullptr;
61     }
62     hb_face_set_index(face.get(), (unsigned)index);
63     hb_face_set_upem(face.get(), tf->getUnitsPerEm());
64 
65     HBFont font(hb_font_create(face.get()));
66     SkASSERT(font);
67     if (!font) {
68         return nullptr;
69     }
70     hb_ot_font_set_funcs(font.get());
71     int axis_count = tf->getVariationDesignPosition(nullptr, 0);
72     if (axis_count > 0) {
73         SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
74         if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
75             hb_font_set_variations(font.get(),
76                                    reinterpret_cast<hb_variation_t*>(axis_values.get()),
77                                    axis_count);
78         }
79     }
80     return font;
81 }
82 
83 class RunIterator {
84 public:
~RunIterator()85     virtual ~RunIterator() {}
86     virtual void consume() = 0;
87     // Pointer one past the last (utf8) element in the current run.
88     virtual const char* endOfCurrentRun() const = 0;
89     virtual bool atEnd() const = 0;
operator <(const RunIterator & that) const90     bool operator<(const RunIterator& that) const {
91         return this->endOfCurrentRun() < that.endOfCurrentRun();
92     }
93 };
94 
95 class BiDiRunIterator : public RunIterator {
96 public:
Make(const char * utf8,size_t utf8Bytes,UBiDiLevel level)97     static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
98         SkTLazy<BiDiRunIterator> ret;
99 
100         // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
101         // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
102         if (!SkTFitsIn<int32_t>(utf8Bytes)) {
103             SkDebugf("Bidi error: text too long");
104             return ret;
105         }
106         icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, utf8Bytes));
107 
108         UErrorCode status = U_ZERO_ERROR;
109         ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
110         if (U_FAILURE(status)) {
111             SkDebugf("Bidi error: %s", u_errorName(status));
112             return ret;
113         }
114         SkASSERT(bidi);
115 
116         // The required lifetime of utf16 isn't well documented.
117         // It appears it isn't used after ubidi_setPara except through ubidi_getText.
118         ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), level, nullptr, &status);
119         if (U_FAILURE(status)) {
120             SkDebugf("Bidi error: %s", u_errorName(status));
121             return ret;
122         }
123 
124         ret.init(utf8, std::move(bidi));
125         return ret;
126     }
BiDiRunIterator(const char * utf8,ICUBiDi bidi)127     BiDiRunIterator(const char* utf8, ICUBiDi bidi)
128         : fBidi(std::move(bidi))
129         , fEndOfCurrentRun(utf8)
130         , fUTF16LogicalPosition(0)
131         , fLevel(UBIDI_DEFAULT_LTR)
132     {}
consume()133     void consume() override {
134         SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
135         int32_t endPosition = ubidi_getLength(fBidi.get());
136         fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
137         SkUnichar u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
138         fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
139         UBiDiLevel level;
140         while (fUTF16LogicalPosition < endPosition) {
141             level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
142             if (level != fLevel) {
143                 break;
144             }
145             u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
146             fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
147         }
148     }
endOfCurrentRun() const149     const char* endOfCurrentRun() const override {
150         return fEndOfCurrentRun;
151     }
atEnd() const152     bool atEnd() const override {
153         return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
154     }
155 
currentLevel() const156     UBiDiLevel currentLevel() const {
157         return fLevel;
158     }
159 private:
160     ICUBiDi fBidi;
161     const char* fEndOfCurrentRun;
162     int32_t fUTF16LogicalPosition;
163     UBiDiLevel fLevel;
164 };
165 
166 class ScriptRunIterator : public RunIterator {
167 public:
Make(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)168     static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
169                                            hb_unicode_funcs_t* hbUnicode)
170     {
171         SkTLazy<ScriptRunIterator> ret;
172         ret.init(utf8, utf8Bytes, hbUnicode);
173         return ret;
174     }
ScriptRunIterator(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)175     ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
176         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
177         , fHBUnicode(hbUnicode)
178         , fCurrentScript(HB_SCRIPT_UNKNOWN)
179     {}
consume()180     void consume() override {
181         SkASSERT(fCurrent < fEnd);
182         SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
183         fCurrentScript = hb_unicode_script(fHBUnicode, u);
184         while (fCurrent < fEnd) {
185             const char* prev = fCurrent;
186             u = SkUTF8_NextUnichar(&fCurrent);
187             const hb_script_t script = hb_unicode_script(fHBUnicode, u);
188             if (script != fCurrentScript) {
189                 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
190                     fCurrentScript = script;
191                 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
192                     continue;
193                 } else {
194                     fCurrent = prev;
195                     break;
196                 }
197             }
198         }
199         if (fCurrentScript == HB_SCRIPT_INHERITED) {
200             fCurrentScript = HB_SCRIPT_COMMON;
201         }
202     }
endOfCurrentRun() const203     const char* endOfCurrentRun() const override {
204         return fCurrent;
205     }
atEnd() const206     bool atEnd() const override {
207         return fCurrent == fEnd;
208     }
209 
currentScript() const210     hb_script_t currentScript() const {
211         return fCurrentScript;
212     }
213 private:
214     const char* fCurrent;
215     const char* fEnd;
216     hb_unicode_funcs_t* fHBUnicode;
217     hb_script_t fCurrentScript;
218 };
219 
220 class FontRunIterator : public RunIterator {
221 public:
Make(const char * utf8,size_t utf8Bytes,sk_sp<SkTypeface> typeface,hb_font_t * hbFace,sk_sp<SkFontMgr> fallbackMgr)222     static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
223                                          sk_sp<SkTypeface> typeface,
224                                          hb_font_t* hbFace,
225                                          sk_sp<SkFontMgr> fallbackMgr)
226     {
227         SkTLazy<FontRunIterator> ret;
228         ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
229         return ret;
230     }
FontRunIterator(const char * utf8,size_t utf8Bytes,sk_sp<SkTypeface> typeface,hb_font_t * hbFace,sk_sp<SkFontMgr> fallbackMgr)231     FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
232                     hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
233         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
234         , fFallbackMgr(std::move(fallbackMgr))
235         , fHBFont(hbFace), fTypeface(std::move(typeface))
236         , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
237         , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
238     {}
consume()239     void consume() override {
240         SkASSERT(fCurrent < fEnd);
241         SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
242         // If the starting typeface can handle this character, use it.
243         if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
244             fFallbackTypeface.reset();
245         // If not, try to find a fallback typeface
246         } else {
247             fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
248                 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
249         }
250 
251         if (fFallbackTypeface) {
252             fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
253             fCurrentTypeface = fFallbackTypeface.get();
254             fCurrentHBFont = fFallbackHBFont.get();
255         } else {
256             fFallbackHBFont.reset();
257             fCurrentTypeface = fTypeface.get();
258             fCurrentHBFont = fHBFont;
259         }
260 
261         while (fCurrent < fEnd) {
262             const char* prev = fCurrent;
263             u = SkUTF8_NextUnichar(&fCurrent);
264 
265             // If using a fallback and the initial typeface has this character, stop fallback.
266             if (fFallbackTypeface &&
267                 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
268             {
269                 fCurrent = prev;
270                 return;
271             }
272             // If the current typeface cannot handle this character, stop using it.
273             if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
274                 fCurrent = prev;
275                 return;
276             }
277         }
278     }
endOfCurrentRun() const279     const char* endOfCurrentRun() const override {
280         return fCurrent;
281     }
atEnd() const282     bool atEnd() const override {
283         return fCurrent == fEnd;
284     }
285 
currentTypeface() const286     SkTypeface* currentTypeface() const {
287         return fCurrentTypeface;
288     }
currentHBFont() const289     hb_font_t* currentHBFont() const {
290         return fCurrentHBFont;
291     }
292 private:
293     const char* fCurrent;
294     const char* fEnd;
295     sk_sp<SkFontMgr> fFallbackMgr;
296     hb_font_t* fHBFont;
297     sk_sp<SkTypeface> fTypeface;
298     HBFont fFallbackHBFont;
299     sk_sp<SkTypeface> fFallbackTypeface;
300     hb_font_t* fCurrentHBFont;
301     SkTypeface* fCurrentTypeface;
302 };
303 
304 class RunIteratorQueue {
305 public:
insert(RunIterator * runIterator)306     void insert(RunIterator* runIterator) {
307         fRunIterators.insert(runIterator);
308     }
309 
advanceRuns()310     bool advanceRuns() {
311         const RunIterator* leastRun = fRunIterators.peek();
312         if (leastRun->atEnd()) {
313             SkASSERT(this->allRunsAreAtEnd());
314             return false;
315         }
316         const char* leastEnd = leastRun->endOfCurrentRun();
317         RunIterator* currentRun = nullptr;
318         SkDEBUGCODE(const char* previousEndOfCurrentRun);
319         while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
320             fRunIterators.pop();
321             SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
322             currentRun->consume();
323             SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
324             fRunIterators.insert(currentRun);
325         }
326         return true;
327     }
328 
endOfCurrentRun() const329     const char* endOfCurrentRun() const {
330         return fRunIterators.peek()->endOfCurrentRun();
331     }
332 
333 private:
allRunsAreAtEnd() const334     bool allRunsAreAtEnd() const {
335         for (int i = 0; i < fRunIterators.count(); ++i) {
336             if (!fRunIterators.at(i)->atEnd()) {
337                 return false;
338             }
339         }
340         return true;
341     }
342 
CompareRunIterator(RunIterator * const & a,RunIterator * const & b)343     static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
344         return *a < *b;
345     }
346     SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
347 };
348 
349 struct ShapedGlyph {
350     SkGlyphID fID;
351     uint32_t fCluster;
352     SkPoint fOffset;
353     SkVector fAdvance;
354     bool fMayLineBreakBefore;
355     bool fMustLineBreakBefore;
356     bool fHasVisual;
357 };
358 struct ShapedRun {
ShapedRun__anon14a72d1c0111::ShapedRun359     ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkPaint& paint,
360               UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
361         : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fPaint(paint)
362         , fLevel(level), fGlyphs(std::move(glyphs))
363     {}
364 
365     const char* fUtf8Start;
366     const char* fUtf8End;
367     int fNumGlyphs;
368     SkPaint fPaint;
369     UBiDiLevel fLevel;
370     std::unique_ptr<ShapedGlyph[]> fGlyphs;
371 };
372 
is_LTR(UBiDiLevel level)373 static constexpr bool is_LTR(UBiDiLevel level) {
374     return (level & 1) == 0;
375 }
376 
append(SkTextBlobBuilder * b,const ShapedRun & run,int start,int end,SkPoint * p)377 static void append(SkTextBlobBuilder* b, const ShapedRun& run, int start, int end, SkPoint* p) {
378     unsigned len = end - start;
379     auto runBuffer = b->allocRunTextPos(run.fPaint, len, run.fUtf8End - run.fUtf8Start, SkString());
380     memcpy(runBuffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
381 
382     for (unsigned i = 0; i < len; i++) {
383         // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
384         const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
385         runBuffer.glyphs[i] = glyph.fID;
386         runBuffer.clusters[i] = glyph.fCluster;
387         reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
388                 SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
389         p->fX += glyph.fAdvance.fX;
390         p->fY += glyph.fAdvance.fY;
391     }
392 }
393 
394 struct ShapedRunGlyphIterator {
ShapedRunGlyphIterator__anon14a72d1c0111::ShapedRunGlyphIterator395     ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
396         : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
397     { }
398 
399     ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
400     ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
operator ==__anon14a72d1c0111::ShapedRunGlyphIterator401     bool operator==(const ShapedRunGlyphIterator& that) const {
402         return fRuns == that.fRuns &&
403                fRunIndex == that.fRunIndex &&
404                fGlyphIndex == that.fGlyphIndex;
405     }
operator !=__anon14a72d1c0111::ShapedRunGlyphIterator406     bool operator!=(const ShapedRunGlyphIterator& that) const {
407         return fRuns != that.fRuns ||
408                fRunIndex != that.fRunIndex ||
409                fGlyphIndex != that.fGlyphIndex;
410     }
411 
next__anon14a72d1c0111::ShapedRunGlyphIterator412     ShapedGlyph* next() {
413         const SkTArray<ShapedRun>& runs = *fRuns;
414         SkASSERT(fRunIndex < runs.count());
415         SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
416 
417         ++fGlyphIndex;
418         if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
419             fGlyphIndex = 0;
420             ++fRunIndex;
421             if (fRunIndex >= runs.count()) {
422                 return nullptr;
423             }
424         }
425         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
426     }
427 
current__anon14a72d1c0111::ShapedRunGlyphIterator428     ShapedGlyph* current() {
429         const SkTArray<ShapedRun>& runs = *fRuns;
430         if (fRunIndex >= runs.count()) {
431             return nullptr;
432         }
433         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
434     }
435 
436     const SkTArray<ShapedRun>* fRuns;
437     int fRunIndex;
438     int fGlyphIndex;
439 };
440 
441 }  // namespace
442 
443 struct SkShaper::Impl {
444     HBFont fHarfBuzzFont;
445     HBBuffer fBuffer;
446     sk_sp<SkTypeface> fTypeface;
447     std::unique_ptr<icu::BreakIterator> fBreakIterator;
448 };
449 
SkShaper(sk_sp<SkTypeface> tf)450 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
451     fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
452     fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
453     SkASSERT(fImpl->fHarfBuzzFont);
454     fImpl->fBuffer.reset(hb_buffer_create());
455     SkASSERT(fImpl->fBuffer);
456 
457     icu::Locale thai("th");
458     UErrorCode status = U_ZERO_ERROR;
459     fImpl->fBreakIterator.reset(icu::BreakIterator::createLineInstance(thai, status));
460     if (U_FAILURE(status)) {
461         SkDebugf("Could not create break iterator: %s", u_errorName(status));
462         SK_ABORT("");
463     }
464 }
465 
~SkShaper()466 SkShaper::~SkShaper() {}
467 
good() const468 bool SkShaper::good() const {
469     return fImpl->fHarfBuzzFont &&
470            fImpl->fBuffer &&
471            fImpl->fTypeface &&
472            fImpl->fBreakIterator;
473 }
474 
shape(SkTextBlobBuilder * builder,const SkPaint & srcPaint,const char * utf8,size_t utf8Bytes,bool leftToRight,SkPoint point,SkScalar width) const475 SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
476                         const SkPaint& srcPaint,
477                         const char* utf8,
478                         size_t utf8Bytes,
479                         bool leftToRight,
480                         SkPoint point,
481                         SkScalar width) const {
482     sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
483     SkASSERT(builder);
484     UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
485     //hb_script_t script = ...
486 
487     SkTArray<ShapedRun> runs;
488 {
489     RunIteratorQueue runSegmenter;
490 
491     SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
492     BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
493     if (!bidi) {
494         return point;
495     }
496     runSegmenter.insert(bidi);
497 
498     hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
499     SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
500     ScriptRunIterator* script = maybeScript.getMaybeNull();
501     if (!script) {
502         return point;
503     }
504     runSegmenter.insert(script);
505 
506     SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
507                                                              fImpl->fTypeface,
508                                                              fImpl->fHarfBuzzFont.get(),
509                                                              std::move(fontMgr)));
510     FontRunIterator* font = maybeFont.getMaybeNull();
511     if (!font) {
512         return point;
513     }
514     runSegmenter.insert(font);
515 
516     icu::BreakIterator& breakIterator = *fImpl->fBreakIterator;
517     {
518         UErrorCode status = U_ZERO_ERROR;
519         UText utf8UText = UTEXT_INITIALIZER;
520         utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
521         std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
522         if (U_FAILURE(status)) {
523             SkDebugf("Could not create utf8UText: %s", u_errorName(status));
524             return point;
525         }
526         breakIterator.setText(&utf8UText, status);
527         //utext_close(&utf8UText);
528         if (U_FAILURE(status)) {
529             SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
530             return point;
531         }
532     }
533 
534     const char* utf8Start = nullptr;
535     const char* utf8End = utf8;
536     while (runSegmenter.advanceRuns()) {
537         utf8Start = utf8End;
538         utf8End = runSegmenter.endOfCurrentRun();
539 
540         hb_buffer_t* buffer = fImpl->fBuffer.get();
541         SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
542         hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
543         hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
544 
545         // Populate the hb_buffer directly with utf8 cluster indexes.
546         const char* utf8Current = utf8Start;
547         while (utf8Current < utf8End) {
548             unsigned int cluster = utf8Current - utf8Start;
549             hb_codepoint_t u = SkUTF8_NextUnichar(&utf8Current);
550             hb_buffer_add(buffer, u, cluster);
551         }
552 
553         size_t utf8runLength = utf8End - utf8Start;
554         if (!SkTFitsIn<int>(utf8runLength)) {
555             SkDebugf("Shaping error: utf8 too long");
556             return point;
557         }
558         hb_buffer_set_script(buffer, script->currentScript());
559         hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
560         hb_buffer_set_direction(buffer, direction);
561         // TODO: language
562         hb_buffer_guess_segment_properties(buffer);
563         // TODO: features
564         hb_shape(font->currentHBFont(), buffer, nullptr, 0);
565         unsigned len = hb_buffer_get_length(buffer);
566         if (len == 0) {
567             continue;
568         }
569 
570         if (direction == HB_DIRECTION_RTL) {
571             // Put the clusters back in logical order.
572             // Note that the advances remain ltr.
573             hb_buffer_reverse(buffer);
574         }
575         hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
576         hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
577 
578         if (!SkTFitsIn<int>(len)) {
579             SkDebugf("Shaping error: too many glyphs");
580             return point;
581         }
582 
583         SkPaint paint(srcPaint);
584         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
585         paint.setTypeface(sk_ref_sp(font->currentTypeface()));
586         ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, paint, bidi->currentLevel(),
587                                            std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
588         int scaleX, scaleY;
589         hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
590         double textSizeY = run.fPaint.getTextSize() / scaleY;
591         double textSizeX = run.fPaint.getTextSize() / scaleX * run.fPaint.getTextScaleX();
592         for (unsigned i = 0; i < len; i++) {
593             ShapedGlyph& glyph = run.fGlyphs[i];
594             glyph.fID = info[i].codepoint;
595             glyph.fCluster = info[i].cluster;
596             glyph.fOffset.fX = pos[i].x_offset * textSizeX;
597             glyph.fOffset.fY = pos[i].y_offset * textSizeY;
598             glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
599             glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
600             glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
601             //info->mask safe_to_break;
602             glyph.fMustLineBreakBefore = false;
603         }
604 
605         int32_t clusterOffset = utf8Start - utf8;
606         uint32_t previousCluster = 0xFFFFFFFF;
607         for (unsigned i = 0; i < len; ++i) {
608             ShapedGlyph& glyph = run.fGlyphs[i];
609             int32_t glyphCluster = glyph.fCluster + clusterOffset;
610             int32_t breakIteratorCurrent = breakIterator.current();
611             while (breakIteratorCurrent != icu::BreakIterator::DONE &&
612                    breakIteratorCurrent < glyphCluster)
613             {
614                 breakIteratorCurrent = breakIterator.next();
615             }
616             glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
617                                         breakIteratorCurrent == glyphCluster;
618             previousCluster = glyph.fCluster;
619         }
620     }
621 }
622 
623 // Iterate over the glyphs in logical order to mark line endings.
624 {
625     SkScalar widthSoFar = 0;
626     bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
627     bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
628     ShapedRunGlyphIterator previousBreak(runs);
629     ShapedRunGlyphIterator glyphIterator(runs);
630     while (ShapedGlyph* glyph = glyphIterator.current()) {
631         if (canAddBreakNow && glyph->fMayLineBreakBefore) {
632             previousBreakValid = true;
633             previousBreak = glyphIterator;
634         }
635         SkScalar glyphWidth = glyph->fAdvance.fX;
636         if (widthSoFar + glyphWidth < width) {
637             widthSoFar += glyphWidth;
638             glyphIterator.next();
639             canAddBreakNow = true;
640             continue;
641         }
642 
643         if (widthSoFar == 0) {
644             // Adding just this glyph is too much, just break with this glyph
645             glyphIterator.next();
646             previousBreak = glyphIterator;
647         } else if (!previousBreakValid) {
648             // No break opprotunity found yet, just break without this glyph
649             previousBreak = glyphIterator;
650         }
651         glyphIterator = previousBreak;
652         glyph = glyphIterator.current();
653         if (glyph) {
654             glyph->fMustLineBreakBefore = true;
655         }
656         widthSoFar = 0;
657         previousBreakValid = false;
658         canAddBreakNow = false;
659     }
660 }
661 
662 // Reorder the runs and glyphs per line and write them out.
663     SkPoint currentPoint = point;
664 {
665     ShapedRunGlyphIterator previousBreak(runs);
666     ShapedRunGlyphIterator glyphIterator(runs);
667     SkScalar maxAscent = 0;
668     SkScalar maxDescent = 0;
669     SkScalar maxLeading = 0;
670     int previousRunIndex = -1;
671     while (glyphIterator.current()) {
672         int runIndex = glyphIterator.fRunIndex;
673         int glyphIndex = glyphIterator.fGlyphIndex;
674         ShapedGlyph* nextGlyph = glyphIterator.next();
675 
676         if (previousRunIndex != runIndex) {
677             SkPaint::FontMetrics metrics;
678             runs[runIndex].fPaint.getFontMetrics(&metrics);
679             maxAscent = SkTMin(maxAscent, metrics.fAscent);
680             maxDescent = SkTMax(maxDescent, metrics.fDescent);
681             maxLeading = SkTMax(maxLeading, metrics.fLeading);
682             previousRunIndex = runIndex;
683         }
684 
685         // Nothing can be written until the baseline is known.
686         if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
687             continue;
688         }
689 
690         currentPoint.fY -= maxAscent;
691 
692         int numRuns = runIndex - previousBreak.fRunIndex + 1;
693         SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
694         for (int i = 0; i < numRuns; ++i) {
695             runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
696         }
697         SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
698         ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
699 
700         for (int i = 0; i < numRuns; ++i) {
701             int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
702 
703             int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
704                                 ? previousBreak.fGlyphIndex
705                                 : 0;
706             int endGlyphIndex = (logicalIndex == runIndex)
707                               ? glyphIndex + 1
708                               : runs[logicalIndex].fNumGlyphs;
709             append(builder, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
710         }
711 
712         currentPoint.fY += maxDescent + maxLeading;
713         currentPoint.fX = point.fX;
714         maxAscent = 0;
715         maxDescent = 0;
716         maxLeading = 0;
717         previousRunIndex = -1;
718         previousBreak = glyphIterator;
719     }
720 }
721 
722     return currentPoint;
723 }
724