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 "SkBitmaskEnum.h"
9 #include "SkFont.h"
10 #include "SkFontArguments.h"
11 #include "SkFontMetrics.h"
12 #include "SkFontMgr.h"
13 #include "SkMakeUnique.h"
14 #include "SkMalloc.h"
15 #include "SkPoint.h"
16 #include "SkRefCnt.h"
17 #include "SkScalar.h"
18 #include "SkShaper.h"
19 #include "SkSpan.h"
20 #include "SkStream.h"
21 #include "SkString.h"
22 #include "SkTArray.h"
23 #include "SkTDPQueue.h"
24 #include "SkTFitsIn.h"
25 #include "SkTLazy.h"
26 #include "SkTemplates.h"
27 #include "SkTo.h"
28 #include "SkTypeface.h"
29 #include "SkTypes.h"
30 #include "SkUTF.h"
31 
32 #include <hb.h>
33 #include <hb-ot.h>
34 #include <unicode/ubrk.h>
35 #include <unicode/ubidi.h>
36 #include <unicode/ustring.h>
37 #include <unicode/urename.h>
38 #include <unicode/utext.h>
39 #include <unicode/utypes.h>
40 
41 #include <cstring>
42 #include <locale>
43 #include <memory>
44 #include <utility>
45 
46 #if defined(SK_USING_THIRD_PARTY_ICU)
47 #include "SkLoadICU.h"
48 #endif
49 
50 namespace skstd {
51 template <> struct is_bitmask_enum<hb_buffer_flags_t> : std::true_type {};
52 }
53 
54 namespace {
55 template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
56 using HBBlob   = resource<hb_blob_t     , hb_blob_destroy  >;
57 using HBFace   = resource<hb_face_t     , hb_face_destroy  >;
58 using HBFont   = resource<hb_font_t     , hb_font_destroy  >;
59 using HBBuffer = resource<hb_buffer_t   , hb_buffer_destroy>;
60 using ICUBiDi  = resource<UBiDi         , ubidi_close      >;
61 using ICUBrk   = resource<UBreakIterator, ubrk_close       >;
62 
stream_to_blob(std::unique_ptr<SkStreamAsset> asset)63 HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
64     size_t size = asset->getLength();
65     HBBlob blob;
66     if (const void* base = asset->getMemoryBase()) {
67         blob.reset(hb_blob_create((char*)base, SkToUInt(size),
68                                   HB_MEMORY_MODE_READONLY, asset.release(),
69                                   [](void* p) { delete (SkStreamAsset*)p; }));
70     } else {
71         // SkDebugf("Extra SkStreamAsset copy\n");
72         void* ptr = size ? sk_malloc_throw(size) : nullptr;
73         asset->read(ptr, size);
74         blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
75                                   HB_MEMORY_MODE_READONLY, ptr, sk_free));
76     }
77     SkASSERT(blob);
78     hb_blob_make_immutable(blob.get());
79     return blob;
80 }
81 
skhb_position(SkScalar value)82 hb_position_t skhb_position(SkScalar value) {
83     // Treat HarfBuzz hb_position_t as 16.16 fixed-point.
84     constexpr int kHbPosition1 = 1 << 16;
85     return SkScalarRoundToInt(value * kHbPosition1);
86 }
87 
skhb_glyph(hb_font_t * hb_font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t variation_selector,hb_codepoint_t * glyph,void * user_data)88 hb_bool_t skhb_glyph(hb_font_t* hb_font,
89                      void* font_data,
90                      hb_codepoint_t unicode,
91                      hb_codepoint_t variation_selector,
92                      hb_codepoint_t* glyph,
93                      void* user_data) {
94     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
95 
96     *glyph = font.unicharToGlyph(unicode);
97     return *glyph != 0;
98 }
99 
skhb_nominal_glyph(hb_font_t * hb_font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t * glyph,void * user_data)100 hb_bool_t skhb_nominal_glyph(hb_font_t* hb_font,
101                              void* font_data,
102                              hb_codepoint_t unicode,
103                              hb_codepoint_t* glyph,
104                              void* user_data) {
105   return skhb_glyph(hb_font, font_data, unicode, 0, glyph, user_data);
106 }
107 
skhb_nominal_glyphs(hb_font_t * hb_font,void * font_data,unsigned int count,const hb_codepoint_t * unicodes,unsigned int unicode_stride,hb_codepoint_t * glyphs,unsigned int glyph_stride,void * user_data)108 unsigned skhb_nominal_glyphs(hb_font_t *hb_font, void *font_data,
109                              unsigned int count,
110                              const hb_codepoint_t *unicodes,
111                              unsigned int unicode_stride,
112                              hb_codepoint_t *glyphs,
113                              unsigned int glyph_stride,
114                              void *user_data) {
115     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
116 
117     // Batch call textToGlyphs since entry cost is not cheap.
118     // Copy requred because textToGlyphs is dense and hb is strided.
119     SkAutoSTMalloc<256, SkUnichar> unicode(count);
120     for (unsigned i = 0; i < count; i++) {
121         unicode[i] = *unicodes;
122         unicodes = SkTAddOffset<const hb_codepoint_t>(unicodes, unicode_stride);
123     }
124     SkAutoSTMalloc<256, SkGlyphID> glyph(count);
125     font.textToGlyphs(unicode.get(), count * sizeof(SkUnichar), kUTF32_SkTextEncoding,
126                         glyph.get(), count);
127 
128     // Copy the results back to the sparse array.
129     for (unsigned i = 0; i < count; i++) {
130         *glyphs = glyph[i];
131         glyphs = SkTAddOffset<hb_codepoint_t>(glyphs, glyph_stride);
132     }
133     // TODO: supposed to return index of first 0?
134     return count;
135 }
136 
skhb_glyph_h_advance(hb_font_t * hb_font,void * font_data,hb_codepoint_t codepoint,void * user_data)137 hb_position_t skhb_glyph_h_advance(hb_font_t* hb_font,
138                                    void* font_data,
139                                    hb_codepoint_t codepoint,
140                                    void* user_data) {
141     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
142 
143     SkScalar advance;
144     SkGlyphID glyph = SkTo<SkGlyphID>(codepoint);
145 
146     font.getWidths(&glyph, 1, &advance);
147     if (!font.isSubpixel()) {
148         advance = SkScalarRoundToInt(advance);
149     }
150     return skhb_position(advance);
151 }
152 
skhb_glyph_h_advances(hb_font_t * hb_font,void * font_data,unsigned count,const hb_codepoint_t * glyphs,unsigned int glyph_stride,hb_position_t * advances,unsigned int advance_stride,void * user_data)153 void skhb_glyph_h_advances(hb_font_t* hb_font,
154                            void* font_data,
155                            unsigned count,
156                            const hb_codepoint_t* glyphs,
157                            unsigned int glyph_stride,
158                            hb_position_t* advances,
159                            unsigned int advance_stride,
160                            void* user_data) {
161     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
162 
163     // Batch call getWidths since entry cost is not cheap.
164     // Copy requred because getWidths is dense and hb is strided.
165     SkAutoSTMalloc<256, SkGlyphID> glyph(count);
166     for (unsigned i = 0; i < count; i++) {
167         glyph[i] = *glyphs;
168         glyphs = SkTAddOffset<const hb_codepoint_t>(glyphs, glyph_stride);
169     }
170     SkAutoSTMalloc<256, SkScalar> advance(count);
171     font.getWidths(glyph.get(), count, advance.get());
172 
173     if (!font.isSubpixel()) {
174         for (unsigned i = 0; i < count; i++) {
175             advance[i] = SkScalarRoundToInt(advance[i]);
176         }
177     }
178 
179     // Copy the results back to the sparse array.
180     for (unsigned i = 0; i < count; i++) {
181         *advances = skhb_position(advance[i]);
182         advances = SkTAddOffset<hb_position_t>(advances, advance_stride);
183     }
184 }
185 
186 // HarfBuzz callback to retrieve glyph extents, mainly used by HarfBuzz for
187 // fallback mark positioning, i.e. the situation when the font does not have
188 // mark anchors or other mark positioning rules, but instead HarfBuzz is
189 // supposed to heuristically place combining marks around base glyphs. HarfBuzz
190 // does this by measuring "ink boxes" of glyphs, and placing them according to
191 // Unicode mark classes. Above, below, centered or left or right, etc.
skhb_glyph_extents(hb_font_t * hb_font,void * font_data,hb_codepoint_t codepoint,hb_glyph_extents_t * extents,void * user_data)192 hb_bool_t skhb_glyph_extents(hb_font_t* hb_font,
193                              void* font_data,
194                              hb_codepoint_t codepoint,
195                              hb_glyph_extents_t* extents,
196                              void* user_data) {
197     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
198 
199     SkASSERT(codepoint < 0xFFFFu);
200     SkASSERT(extents);
201 
202     SkRect sk_bounds;
203     SkGlyphID glyph = codepoint;
204 
205     font.getWidths(&glyph, 1, nullptr, &sk_bounds);
206     if (!font.isSubpixel()) {
207         sk_bounds.set(sk_bounds.roundOut());
208     }
209 
210     // Skia is y-down but HarfBuzz is y-up.
211     extents->x_bearing = skhb_position(sk_bounds.fLeft);
212     extents->y_bearing = skhb_position(-sk_bounds.fTop);
213     extents->width = skhb_position(sk_bounds.width());
214     extents->height = skhb_position(-sk_bounds.height());
215     return true;
216 }
217 
218 #define SK_HB_VERSION_CHECK(x, y, z) \
219     (HB_VERSION_MAJOR >  (x)) || \
220     (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR >  (y)) || \
221     (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR == (y) && HB_VERSION_MICRO >= (z))
222 
skhb_get_font_funcs()223 hb_font_funcs_t* skhb_get_font_funcs() {
224     static hb_font_funcs_t* const funcs = []{
225         // HarfBuzz will use the default (parent) implementation if they aren't set.
226         hb_font_funcs_t* const funcs = hb_font_funcs_create();
227         hb_font_funcs_set_variation_glyph_func(funcs, skhb_glyph, nullptr, nullptr);
228         hb_font_funcs_set_nominal_glyph_func(funcs, skhb_nominal_glyph, nullptr, nullptr);
229 #if SK_HB_VERSION_CHECK(2, 0, 0)
230         hb_font_funcs_set_nominal_glyphs_func(funcs, skhb_nominal_glyphs, nullptr, nullptr);
231 #else
232         sk_ignore_unused_variable(skhb_nominal_glyphs);
233 #endif
234         hb_font_funcs_set_glyph_h_advance_func(funcs, skhb_glyph_h_advance, nullptr, nullptr);
235 #if SK_HB_VERSION_CHECK(1, 8, 6)
236         hb_font_funcs_set_glyph_h_advances_func(funcs, skhb_glyph_h_advances, nullptr, nullptr);
237 #else
238         sk_ignore_unused_variable(skhb_glyph_h_advances);
239 #endif
240         hb_font_funcs_set_glyph_extents_func(funcs, skhb_glyph_extents, nullptr, nullptr);
241         hb_font_funcs_make_immutable(funcs);
242         return funcs;
243     }();
244     SkASSERT(funcs);
245     return funcs;
246 }
247 
skhb_get_table(hb_face_t * face,hb_tag_t tag,void * user_data)248 hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
249     SkTypeface& typeface = *reinterpret_cast<SkTypeface*>(user_data);
250 
251     const size_t tableSize = typeface.getTableSize(tag);
252     if (!tableSize) {
253         return nullptr;
254     }
255 
256     void* buffer = sk_malloc_throw(tableSize);
257     if (!buffer) {
258         return nullptr;
259     }
260 
261     size_t actualSize = typeface.getTableData(tag, 0, tableSize, buffer);
262     if (tableSize != actualSize) {
263         sk_free(buffer);
264         return nullptr;
265     }
266 
267     return hb_blob_create(reinterpret_cast<char*>(buffer), tableSize,
268                           HB_MEMORY_MODE_WRITABLE, buffer, sk_free);
269 }
270 
create_hb_font(const SkFont & font)271 HBFont create_hb_font(const SkFont& font) {
272     int index;
273     std::unique_ptr<SkStreamAsset> typefaceAsset = font.getTypeface()->openStream(&index);
274     HBFace face;
275     if (!typefaceAsset) {
276         face.reset(hb_face_create_for_tables(
277             skhb_get_table,
278             reinterpret_cast<void *>(font.refTypeface().release()),
279             [](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
280     } else {
281         HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
282         face.reset(hb_face_create(blob.get(), (unsigned)index));
283     }
284     SkASSERT(face);
285     if (!face) {
286         return nullptr;
287     }
288     hb_face_set_index(face.get(), (unsigned)index);
289     hb_face_set_upem(face.get(), font.getTypeface()->getUnitsPerEm());
290 
291     HBFont otFont(hb_font_create(face.get()));
292     SkASSERT(otFont);
293     if (!otFont) {
294         return nullptr;
295     }
296     hb_ot_font_set_funcs(otFont.get());
297     int axis_count = font.getTypeface()->getVariationDesignPosition(nullptr, 0);
298     if (axis_count > 0) {
299         SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
300         if (font.getTypeface()->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
301             hb_font_set_variations(otFont.get(),
302                                    reinterpret_cast<hb_variation_t*>(axis_values.get()),
303                                    axis_count);
304         }
305     }
306 
307     // Creating a sub font means that non-available functions
308     // are found from the parent.
309     HBFont skFont(hb_font_create_sub_font(otFont.get()));
310     hb_font_set_funcs(skFont.get(), skhb_get_font_funcs(),
311                       reinterpret_cast<void *>(new SkFont(font)),
312                       [](void* user_data){ delete reinterpret_cast<SkFont*>(user_data); });
313     int scale = skhb_position(font.getSize());
314     hb_font_set_scale(skFont.get(), scale, scale);
315 
316     return skFont;
317 }
318 
319 /** this version replaces invalid utf-8 sequences with code point U+FFFD. */
utf8_next(const char ** ptr,const char * end)320 static inline SkUnichar utf8_next(const char** ptr, const char* end) {
321     SkUnichar val = SkUTF::NextUTF8(ptr, end);
322     if (val < 0) {
323         return 0xFFFD;  // REPLACEMENT CHARACTER
324     }
325     return val;
326 }
327 
328 class RunIterator {
329 public:
~RunIterator()330     virtual ~RunIterator() {}
331     virtual void consume() = 0;
332     // Pointer one past the last (utf8) element in the current run.
333     virtual const char* endOfCurrentRun() const = 0;
334     virtual bool atEnd() const = 0;
operator <(const RunIterator & that) const335     bool operator<(const RunIterator& that) const {
336         return this->endOfCurrentRun() < that.endOfCurrentRun();
337     }
338 };
339 
340 class BiDiRunIterator : public RunIterator {
341 public:
Make(const char * utf8,size_t utf8Bytes,UBiDiLevel level)342     static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
343         SkTLazy<BiDiRunIterator> ret;
344 
345         // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
346         // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
347         if (!SkTFitsIn<int32_t>(utf8Bytes)) {
348             SkDebugf("Bidi error: text too long");
349             return ret;
350         }
351 
352         UErrorCode status = U_ZERO_ERROR;
353 
354         // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
355         int32_t utf16Units;
356         u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
357         status = U_ZERO_ERROR;
358         std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
359         u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
360         if (U_FAILURE(status)) {
361             SkDebugf("Invalid utf8 input: %s", u_errorName(status));
362             return ret;
363         }
364 
365         ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
366         if (U_FAILURE(status)) {
367             SkDebugf("Bidi error: %s", u_errorName(status));
368             return ret;
369         }
370         SkASSERT(bidi);
371 
372         // The required lifetime of utf16 isn't well documented.
373         // It appears it isn't used after ubidi_setPara except through ubidi_getText.
374         ubidi_setPara(bidi.get(), utf16.get(), utf16Units, level, nullptr, &status);
375         if (U_FAILURE(status)) {
376             SkDebugf("Bidi error: %s", u_errorName(status));
377             return ret;
378         }
379 
380         ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
381         return ret;
382     }
BiDiRunIterator(const char * utf8,const char * end,ICUBiDi bidi)383     BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
384         : fBidi(std::move(bidi))
385         , fEndOfCurrentRun(utf8)
386         , fEndOfAllRuns(end)
387         , fUTF16LogicalPosition(0)
388         , fLevel(UBIDI_DEFAULT_LTR)
389     {}
consume()390     void consume() override {
391         SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
392         int32_t endPosition = ubidi_getLength(fBidi.get());
393         fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
394         SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
395         fUTF16LogicalPosition += SkUTF::ToUTF16(u);
396         UBiDiLevel level;
397         while (fUTF16LogicalPosition < endPosition) {
398             level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
399             if (level != fLevel) {
400                 break;
401             }
402             u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
403             fUTF16LogicalPosition += SkUTF::ToUTF16(u);
404         }
405     }
endOfCurrentRun() const406     const char* endOfCurrentRun() const override {
407         return fEndOfCurrentRun;
408     }
atEnd() const409     bool atEnd() const override {
410         return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
411     }
412 
currentLevel() const413     UBiDiLevel currentLevel() const {
414         return fLevel;
415     }
416 private:
417     ICUBiDi fBidi;
418     const char* fEndOfCurrentRun;
419     const char* fEndOfAllRuns;
420     int32_t fUTF16LogicalPosition;
421     UBiDiLevel fLevel;
422 };
423 
424 class ScriptRunIterator : public RunIterator {
425 public:
Make(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)426     static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
427                                            hb_unicode_funcs_t* hbUnicode)
428     {
429         SkTLazy<ScriptRunIterator> ret;
430         ret.init(utf8, utf8Bytes, hbUnicode);
431         return ret;
432     }
ScriptRunIterator(const char * utf8,size_t utf8Bytes,hb_unicode_funcs_t * hbUnicode)433     ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
434         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
435         , fHBUnicode(hbUnicode)
436         , fCurrentScript(HB_SCRIPT_UNKNOWN)
437     {}
consume()438     void consume() override {
439         SkASSERT(fCurrent < fEnd);
440         SkUnichar u = utf8_next(&fCurrent, fEnd);
441         fCurrentScript = hb_unicode_script(fHBUnicode, u);
442         while (fCurrent < fEnd) {
443             const char* prev = fCurrent;
444             u = utf8_next(&fCurrent, fEnd);
445             const hb_script_t script = hb_unicode_script(fHBUnicode, u);
446             if (script != fCurrentScript) {
447                 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
448                     fCurrentScript = script;
449                 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
450                     continue;
451                 } else {
452                     fCurrent = prev;
453                     break;
454                 }
455             }
456         }
457         if (fCurrentScript == HB_SCRIPT_INHERITED) {
458             fCurrentScript = HB_SCRIPT_COMMON;
459         }
460     }
endOfCurrentRun() const461     const char* endOfCurrentRun() const override {
462         return fCurrent;
463     }
atEnd() const464     bool atEnd() const override {
465         return fCurrent == fEnd;
466     }
467 
currentScript() const468     hb_script_t currentScript() const {
469         return fCurrentScript;
470     }
471 private:
472     const char* fCurrent;
473     const char* fEnd;
474     hb_unicode_funcs_t* fHBUnicode;
475     hb_script_t fCurrentScript;
476 };
477 
478 class FontRunIterator : public RunIterator {
479 public:
Make(const char * utf8,size_t utf8Bytes,SkFont font,sk_sp<SkFontMgr> fallbackMgr)480     static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
481                                          SkFont font,
482                                          sk_sp<SkFontMgr> fallbackMgr)
483     {
484         SkTLazy<FontRunIterator> ret;
485         font.setTypeface(font.refTypefaceOrDefault());
486         HBFont hbFont = create_hb_font(font);
487         if (!hbFont) {
488             SkDebugf("create_hb_font failed!\n");
489             return ret;
490         }
491         ret.init(utf8, utf8Bytes, std::move(font), std::move(hbFont), std::move(fallbackMgr));
492         return ret;
493     }
FontRunIterator(const char * utf8,size_t utf8Bytes,SkFont font,HBFont hbFont,sk_sp<SkFontMgr> fallbackMgr)494     FontRunIterator(const char* utf8, size_t utf8Bytes, SkFont font,
495                     HBFont hbFont, sk_sp<SkFontMgr> fallbackMgr)
496         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
497         , fFallbackMgr(std::move(fallbackMgr))
498         , fHBFont(std::move(hbFont)), fFont(std::move(font))
499         , fFallbackHBFont(nullptr), fFallbackFont(fFont)
500         , fCurrentHBFont(fHBFont.get()), fCurrentFont(&fFont)
501     {
502         fFallbackFont.setTypeface(nullptr);
503     }
consume()504     void consume() override {
505         SkASSERT(fCurrent < fEnd);
506         SkUnichar u = utf8_next(&fCurrent, fEnd);
507         // If the starting typeface can handle this character, use it.
508         if (fFont.unicharToGlyph(u)) {
509             fCurrentFont = &fFont;
510             fCurrentHBFont = fHBFont.get();
511         // If the current fallback can handle this character, use it.
512         } else if (fFallbackFont.getTypeface() && fFallbackFont.unicharToGlyph(u)) {
513             fCurrentFont = &fFallbackFont;
514             fCurrentHBFont = fFallbackHBFont.get();
515         // If not, try to find a fallback typeface
516         } else {
517             sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
518                 nullptr, fFont.getTypeface()->fontStyle(), nullptr, 0, u));
519             if (candidate) {
520                 fFallbackFont.setTypeface(std::move(candidate));
521                 fFallbackHBFont = create_hb_font(fFallbackFont);
522                 fCurrentFont = &fFallbackFont;
523                 fCurrentHBFont = fFallbackHBFont.get();
524             } else {
525                 fCurrentFont = &fFont;
526                 fCurrentHBFont = fHBFont.get();
527             }
528         }
529 
530         while (fCurrent < fEnd) {
531             const char* prev = fCurrent;
532             u = utf8_next(&fCurrent, fEnd);
533 
534             // End run if not using initial typeface and initial typeface has this character.
535             if (fCurrentFont->getTypeface() != fFont.getTypeface() && fFont.unicharToGlyph(u)) {
536                 fCurrent = prev;
537                 return;
538             }
539 
540             // End run if current typeface does not have this character and some other font does.
541             if (!fCurrentFont->unicharToGlyph(u)) {
542                 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
543                     nullptr, fFont.getTypeface()->fontStyle(), nullptr, 0, u));
544                 if (candidate) {
545                     fCurrent = prev;
546                     return;
547                 }
548             }
549         }
550     }
endOfCurrentRun() const551     const char* endOfCurrentRun() const override {
552         return fCurrent;
553     }
atEnd() const554     bool atEnd() const override {
555         return fCurrent == fEnd;
556     }
557 
currentFont() const558     SkFont* currentFont() const {
559         return fCurrentFont;
560     }
currentHBFont() const561     hb_font_t* currentHBFont() const {
562         return fCurrentHBFont;
563     }
564 private:
565     const char* fCurrent;
566     const char* fEnd;
567     sk_sp<SkFontMgr> fFallbackMgr;
568     HBFont fHBFont;
569     SkFont fFont;
570     HBFont fFallbackHBFont;
571     SkFont fFallbackFont;
572     hb_font_t* fCurrentHBFont;
573     SkFont* fCurrentFont;
574 };
575 
576 class LanguageRunIterator : public RunIterator {
577 public:
Make(const char * utf8,size_t utf8Bytes)578     static SkTLazy<LanguageRunIterator> Make(const char* utf8, size_t utf8Bytes) {
579         SkTLazy<LanguageRunIterator> ret;
580         ret.init(utf8, utf8Bytes);
581         return ret;
582     }
LanguageRunIterator(const char * utf8,size_t utf8Bytes)583     LanguageRunIterator(const char* utf8, size_t utf8Bytes)
584         : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
585     , fLanguage(hb_language_from_string(std::locale().name().c_str(), -1))
586     { }
consume()587     void consume() override {
588         // Ideally something like cld2/3 could be used, or user signals.
589         SkASSERT(fCurrent < fEnd);
590         fCurrent = fEnd;
591     }
endOfCurrentRun() const592     const char* endOfCurrentRun() const override {
593         return fCurrent;
594     }
atEnd() const595     bool atEnd() const override {
596         return fCurrent == fEnd;
597     }
598 
currentLanguage() const599     hb_language_t currentLanguage() const {
600         return fLanguage;
601     }
602 private:
603     const char* fCurrent;
604     const char* fEnd;
605     hb_language_t fLanguage;
606 };
607 
608 class RunIteratorQueue {
609 public:
insert(RunIterator * runIterator)610     void insert(RunIterator* runIterator) {
611         fRunIterators.insert(runIterator);
612     }
613 
advanceRuns()614     bool advanceRuns() {
615         const RunIterator* leastRun = fRunIterators.peek();
616         if (leastRun->atEnd()) {
617             SkASSERT(this->allRunsAreAtEnd());
618             return false;
619         }
620         const char* leastEnd = leastRun->endOfCurrentRun();
621         RunIterator* currentRun = nullptr;
622         SkDEBUGCODE(const char* previousEndOfCurrentRun);
623         while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
624             fRunIterators.pop();
625             SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
626             currentRun->consume();
627             SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
628             fRunIterators.insert(currentRun);
629         }
630         return true;
631     }
632 
endOfCurrentRun() const633     const char* endOfCurrentRun() const {
634         return fRunIterators.peek()->endOfCurrentRun();
635     }
636 
637 private:
allRunsAreAtEnd() const638     bool allRunsAreAtEnd() const {
639         for (int i = 0; i < fRunIterators.count(); ++i) {
640             if (!fRunIterators.at(i)->atEnd()) {
641                 return false;
642             }
643         }
644         return true;
645     }
646 
CompareRunIterator(RunIterator * const & a,RunIterator * const & b)647     static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
648         return *a < *b;
649     }
650     SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
651 };
652 
653 struct ShapedGlyph {
654     SkGlyphID fID;
655     uint32_t fCluster;
656     SkPoint fOffset;
657     SkVector fAdvance;
658     bool fMayLineBreakBefore;
659     bool fMustLineBreakBefore;
660     bool fHasVisual;
661     bool fGraphemeBreakBefore;
662     bool fUnsafeToBreak;
663 };
664 struct ShapedRun {
ShapedRun__anona3885cf40111::ShapedRun665     ShapedRun(SkSpan<const char> utf8, const SkFont& font, UBiDiLevel level,
666               std::unique_ptr<ShapedGlyph[]> glyphs, int numGlyphs)
667         : fUtf8(utf8), fFont(font), fLevel(level)
668         , fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs)
669     {}
670 
671     SkSpan<const char> fUtf8;
672     SkFont fFont;
673     UBiDiLevel fLevel;
674     std::unique_ptr<ShapedGlyph[]> fGlyphs;
675     int fNumGlyphs;
676     SkVector fAdvance = { 0, 0 };
677 };
678 struct ShapedLine {
679     SkTArray<ShapedRun> runs;
680     SkVector fAdvance = { 0, 0 };
681 };
682 
is_LTR(UBiDiLevel level)683 static constexpr bool is_LTR(UBiDiLevel level) {
684     return (level & 1) == 0;
685 }
686 
append(SkShaper::RunHandler * handler,const SkShaper::RunHandler::RunInfo & runInfo,const ShapedRun & run,int start,int end,SkPoint * p)687 static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
688                    const ShapedRun& run, int start, int end,
689                    SkPoint* p) {
690     const unsigned len = end - start;
691 
692     const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8);
693     SkASSERT(buffer.glyphs);
694     SkASSERT(buffer.positions);
695 
696     for (unsigned i = 0; i < len; i++) {
697         // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
698         const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
699         buffer.glyphs[i] = glyph.fID;
700         buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
701         if (buffer.clusters) {
702             buffer.clusters[i] = glyph.fCluster;
703         }
704         p->fX += glyph.fAdvance.fX;
705         p->fY += glyph.fAdvance.fY;
706     }
707     handler->commitRun();
708 }
709 
emit(const ShapedLine & line,SkShaper::RunHandler * handler,SkPoint point,SkPoint & currentPoint)710 static void emit(const ShapedLine& line, SkShaper::RunHandler* handler,
711                  SkPoint point, SkPoint& currentPoint)
712 {
713     // Reorder the runs and glyphs per line and write them out.
714     SkScalar maxAscent = 0;
715     SkScalar maxDescent = 0;
716     SkScalar maxLeading = 0;
717     for (const ShapedRun& run : line.runs) {
718         SkFontMetrics metrics;
719         run.fFont.getMetrics(&metrics);
720         maxAscent = SkTMin(maxAscent, metrics.fAscent);
721         maxDescent = SkTMax(maxDescent, metrics.fDescent);
722         maxLeading = SkTMax(maxLeading, metrics.fLeading);
723     }
724 
725     int numRuns = line.runs.size();
726     SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
727     for (int i = 0; i < numRuns; ++i) {
728         runLevels[i] = line.runs[i].fLevel;
729     }
730     SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
731     ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
732 
733     currentPoint.fY -= maxAscent;
734 
735     for (int i = 0; i < numRuns; ++i) {
736         int logicalIndex = logicalFromVisual[i];
737 
738         const auto& run = line.runs[logicalIndex];
739         const SkShaper::RunHandler::RunInfo info = {
740             run.fAdvance,
741             maxAscent,
742             maxDescent,
743             maxLeading,
744         };
745         append(handler, info, run, 0, run.fNumGlyphs, &currentPoint);
746     }
747 
748     currentPoint.fY += maxDescent + maxLeading;
749     currentPoint.fX = point.fX;
750 
751     handler->commitLine();
752 }
753 
754 struct ShapedRunGlyphIterator {
ShapedRunGlyphIterator__anona3885cf40111::ShapedRunGlyphIterator755     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;
operator ==__anona3885cf40111::ShapedRunGlyphIterator761     bool operator==(const ShapedRunGlyphIterator& that) const {
762         return fRuns == that.fRuns &&
763                fRunIndex == that.fRunIndex &&
764                fGlyphIndex == that.fGlyphIndex;
765     }
operator !=__anona3885cf40111::ShapedRunGlyphIterator766     bool operator!=(const ShapedRunGlyphIterator& that) const {
767         return fRuns != that.fRuns ||
768                fRunIndex != that.fRunIndex ||
769                fGlyphIndex != that.fGlyphIndex;
770     }
771 
next__anona3885cf40111::ShapedRunGlyphIterator772     ShapedGlyph* next() {
773         const SkTArray<ShapedRun>& runs = *fRuns;
774         SkASSERT(fRunIndex < runs.count());
775         SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
776 
777         ++fGlyphIndex;
778         if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
779             fGlyphIndex = 0;
780             ++fRunIndex;
781             if (fRunIndex >= runs.count()) {
782                 return nullptr;
783             }
784         }
785         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
786     }
787 
current__anona3885cf40111::ShapedRunGlyphIterator788     ShapedGlyph* current() {
789         const SkTArray<ShapedRun>& runs = *fRuns;
790         if (fRunIndex >= runs.count()) {
791             return nullptr;
792         }
793         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
794     }
795 
796     const SkTArray<ShapedRun>* fRuns;
797     int fRunIndex;
798     int fGlyphIndex;
799 };
800 
801 }  // namespace
802 
803 class SkShaperHarfBuzz : public SkShaper {
804 public:
805     SkShaperHarfBuzz();
806     bool good() const;
807 private:
808     HBBuffer fBuffer;
809     ICUBrk fLineBreakIterator;
810     ICUBrk fGraphemeBreakIterator;
811 
812     SkPoint shape(SkShaper::RunHandler* handler,
813                   const SkFont& srcFont,
814                   const char* utf8text,
815                   size_t textBytes,
816                   bool leftToRight,
817                   SkPoint point,
818                   SkScalar width) const override;
819 
820     SkPoint shapeCorrect(SkShaper::RunHandler* handler,
821                          const char* utf8,
822                          size_t utf8Bytes,
823                          SkPoint point,
824                          SkScalar width,
825                          RunIteratorQueue& runSegmenter,
826                          const BiDiRunIterator* bidi,
827                          const LanguageRunIterator* language,
828                          const ScriptRunIterator* script,
829                          const FontRunIterator* font) const;
830 
831     SkPoint shapeOk(SkShaper::RunHandler* handler,
832                     const char* utf8,
833                     size_t utf8Bytes,
834                     SkPoint point,
835                     SkScalar width,
836                     RunIteratorQueue& runSegmenter,
837                     const BiDiRunIterator* bidi,
838                     const LanguageRunIterator* language,
839                     const ScriptRunIterator* script,
840                     const FontRunIterator* font) const;
841 
842     ShapedRun shape(const char* utf8,
843                     size_t utf8Bytes,
844                     const char* utf8Start,
845                     const char* utf8End,
846                     const BiDiRunIterator* bidi,
847                     const LanguageRunIterator* language,
848                     const ScriptRunIterator* script,
849                     const FontRunIterator* font) const;
850 };
851 
MakeHarfBuzz()852 std::unique_ptr<SkShaper> SkShaper::MakeHarfBuzz() {
853     auto hb = skstd::make_unique<SkShaperHarfBuzz>();
854     return hb->good() ? std::move(hb) : nullptr;
855 }
856 
SkShaperHarfBuzz()857 SkShaperHarfBuzz::SkShaperHarfBuzz() {
858 #if defined(SK_USING_THIRD_PARTY_ICU)
859     if (!SkLoadICU()) {
860         SkDebugf("SkLoadICU() failed!\n");
861         return;
862     }
863 #endif
864     fBuffer.reset(hb_buffer_create());
865     SkASSERT(fBuffer);
866 
867     UErrorCode status = U_ZERO_ERROR;
868     fLineBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
869     if (U_FAILURE(status)) {
870         SkDebugf("Could not create line break iterator: %s", u_errorName(status));
871         SK_ABORT("");
872     }
873 
874     fGraphemeBreakIterator.reset(ubrk_open(UBRK_CHARACTER, "th", nullptr, 0, &status));
875     if (U_FAILURE(status)) {
876         SkDebugf("Could not create grapheme break iterator: %s", u_errorName(status));
877         SK_ABORT("");
878     }
879 
880 }
881 
good() const882 bool SkShaperHarfBuzz::good() const {
883     return fBuffer &&
884            fLineBreakIterator &&
885            fGraphemeBreakIterator;
886 }
887 
shape(SkShaper::RunHandler * handler,const SkFont & srcFont,const char * utf8,size_t utf8Bytes,bool leftToRight,SkPoint point,SkScalar width) const888 SkPoint SkShaperHarfBuzz::shape(SkShaper::RunHandler* handler,
889                                 const SkFont& srcFont,
890                                 const char* utf8,
891                                 size_t utf8Bytes,
892                                 bool leftToRight,
893                                 SkPoint point,
894                                 SkScalar width) const
895 {
896     SkASSERT(handler);
897     sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
898     UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
899 
900     RunIteratorQueue runSegmenter;
901 
902     SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
903     BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
904     if (!bidi) {
905         return point;
906     }
907     runSegmenter.insert(bidi);
908 
909     SkTLazy<LanguageRunIterator> maybeLanguage(LanguageRunIterator::Make(utf8, utf8Bytes));
910     LanguageRunIterator* language = maybeLanguage.getMaybeNull();
911     if (!language) {
912         return point;
913     }
914     runSegmenter.insert(language);
915 
916     hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fBuffer.get());
917     SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
918     ScriptRunIterator* script = maybeScript.getMaybeNull();
919     if (!script) {
920         return point;
921     }
922     runSegmenter.insert(script);
923 
924     SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
925                                                              srcFont, std::move(fontMgr)));
926     FontRunIterator* font = maybeFont.getMaybeNull();
927     if (!font) {
928         return point;
929     }
930     runSegmenter.insert(font);
931 
932     if (true) {
933         return shapeCorrect(handler, utf8, utf8Bytes, point, width,
934                                    runSegmenter, bidi, language, script, font);
935     } else {
936         return shapeOk(handler, utf8, utf8Bytes, point, width,
937                               runSegmenter, bidi, language, script, font);
938     }
939 }
940 
shapeCorrect(RunHandler * handler,const char * utf8,size_t utf8Bytes,SkPoint point,SkScalar width,RunIteratorQueue & runSegmenter,const BiDiRunIterator * bidi,const LanguageRunIterator * language,const ScriptRunIterator * script,const FontRunIterator * font) const941 SkPoint SkShaperHarfBuzz::shapeCorrect(RunHandler* handler,
942                                        const char* utf8,
943                                        size_t utf8Bytes,
944                                        SkPoint point,
945                                        SkScalar width,
946                                        RunIteratorQueue& runSegmenter,
947                                        const BiDiRunIterator* bidi,
948                                        const LanguageRunIterator* language,
949                                        const ScriptRunIterator* script,
950                                        const FontRunIterator* font) const
951 {
952     ShapedLine line;
953     SkPoint currentPoint = point;
954 
955     const char* utf8Start = nullptr;
956     const char* utf8End = utf8;
957     while (runSegmenter.advanceRuns()) {  // For each item
958         utf8Start = utf8End;
959         utf8End = runSegmenter.endOfCurrentRun();
960 
961         ShapedRun model(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
962         bool modelNeedsRegenerated = true;
963         int modelOffset = 0;
964 
965         struct TextProps {
966             int glyphLen = 0;
967             SkVector advance = {0, 0};
968         };
969         // map from character position to [safe to break, glyph position, advance]
970         std::unique_ptr<TextProps[]> modelText;
971         int modelTextOffset = 0;
972         SkVector modelTextAdvanceOffset = {0, 0};
973 
974         while (utf8Start < utf8End) {  // While there are still code points left in this item
975             size_t utf8runLength = utf8End - utf8Start;
976             if (modelNeedsRegenerated) {
977                 model = shape(utf8, utf8Bytes,
978                               utf8Start, utf8End,
979                               bidi, language, script, font);
980                 modelOffset = 0;
981 
982                 SkVector advance = {0, 0};
983                 modelText.reset(new TextProps[utf8runLength + 1]());
984                 size_t modelStartCluster = utf8Start - utf8;
985                 for (int i = 0; i < model.fNumGlyphs; ++i) {
986                     SkASSERT(modelStartCluster <= model.fGlyphs[i].fCluster);
987                     SkASSERT(                     model.fGlyphs[i].fCluster < (size_t)(utf8End - utf8));
988                     if (!model.fGlyphs[i].fUnsafeToBreak) {
989                         modelText[model.fGlyphs[i].fCluster - modelStartCluster].glyphLen = i;
990                         modelText[model.fGlyphs[i].fCluster - modelStartCluster].advance = advance;
991                     }
992                     advance += model.fGlyphs[i].fAdvance;
993                 }
994                 // Assume it is always safe to break after the end of an item
995                 modelText[utf8runLength].glyphLen = model.fNumGlyphs;
996                 modelText[utf8runLength].advance = model.fAdvance;
997                 modelTextOffset = 0;
998                 modelTextAdvanceOffset = {0, 0};
999                 modelNeedsRegenerated = false;
1000             }
1001 
1002             // TODO: break iterator per item, but just reset position if needed?
1003             // Maybe break iterator with model?
1004             UBreakIterator& breakIterator = *fLineBreakIterator;
1005             {
1006                 UErrorCode status = U_ZERO_ERROR;
1007                 UText utf8UText = UTEXT_INITIALIZER;
1008                 utext_openUTF8(&utf8UText, utf8Start, utf8runLength, &status);
1009                 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
1010                 if (U_FAILURE(status)) {
1011                     SkDebugf("Could not create utf8UText: %s", u_errorName(status));
1012                     return point;
1013                 }
1014                 ubrk_setUText(&breakIterator, &utf8UText, &status);
1015                 if (U_FAILURE(status)) {
1016                     SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
1017                     return point;
1018                 }
1019             }
1020 
1021             ShapedRun best(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
1022             best.fAdvance = { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity };
1023             SkScalar widthLeft = width - line.fAdvance.fX;
1024 
1025             for (int32_t breakIteratorCurrent = ubrk_next(&breakIterator);
1026                  breakIteratorCurrent != UBRK_DONE;
1027                  breakIteratorCurrent = ubrk_next(&breakIterator))
1028             {
1029                 // TODO: if past a safe to break, future safe to break will be at least as long
1030 
1031                 // TODO: adjust breakIteratorCurrent by ignorable whitespace
1032                 ShapedRun candidate = modelText[breakIteratorCurrent + modelTextOffset].glyphLen
1033                                     ? ShapedRun(SkSpan<const char>(utf8Start, breakIteratorCurrent),
1034                                                 *font->currentFont(), bidi->currentLevel(),
1035                                                 std::unique_ptr<ShapedGlyph[]>(),
1036                                                 modelText[breakIteratorCurrent + modelTextOffset].glyphLen - modelOffset)
1037                                     : shape(utf8, utf8Bytes,
1038                                             utf8Start, utf8Start + breakIteratorCurrent,
1039                                             bidi, language, script, font);
1040                 if (!candidate.fUtf8.data()) {
1041                     //report error
1042                     return point;
1043                 }
1044                 if (!candidate.fGlyphs) {
1045                     candidate.fAdvance = modelText[breakIteratorCurrent + modelTextOffset].advance - modelTextAdvanceOffset;
1046                 }
1047                 auto score = [widthLeft](const ShapedRun& run) -> SkScalar {
1048                     if (run.fAdvance.fX < widthLeft) {
1049                         if (run.fUtf8.data() == nullptr) {
1050                             return SK_ScalarNegativeInfinity;
1051                         } else {
1052                             return run.fUtf8.size();
1053                         }
1054                     } else {
1055                         return widthLeft - run.fAdvance.fX;
1056                     }
1057                 };
1058                 if (score(best) < score(candidate)) {
1059                     best = std::move(candidate);
1060                 }
1061             }
1062 
1063             // If nothing fit (best score is negative) and the line is not empty
1064             if (width < line.fAdvance.fX + best.fAdvance.fX && !line.runs.empty()) {
1065                 emit(line, handler, point, currentPoint);
1066                 line.runs.reset();
1067                 line.fAdvance = {0, 0};
1068             } else {
1069                 if (!best.fGlyphs) {
1070                     best.fGlyphs.reset(new ShapedGlyph[best.fNumGlyphs]);
1071                     memcpy(best.fGlyphs.get(), model.fGlyphs.get() + modelOffset,
1072                            best.fNumGlyphs * sizeof(ShapedGlyph));
1073                     modelOffset += best.fNumGlyphs;
1074                     modelTextOffset += best.fUtf8.size();
1075                     modelTextAdvanceOffset += best.fAdvance;
1076                 } else {
1077                     modelNeedsRegenerated = true;
1078                 }
1079                 utf8Start = best.fUtf8.end();
1080                 line.fAdvance += best.fAdvance;
1081                 line.runs.emplace_back(std::move(best));
1082 
1083                 // If item broken, emit line (prevent remainder from accidentally fitting)
1084                 if (utf8Start != utf8End) {
1085                     emit(line, handler, point, currentPoint);
1086                     line.runs.reset();
1087                     line.fAdvance = {0, 0};
1088                 }
1089             }
1090         }
1091     }
1092     emit(line, handler, point, currentPoint);
1093     return currentPoint;
1094 }
1095 
shapeOk(RunHandler * handler,const char * utf8,size_t utf8Bytes,SkPoint point,SkScalar width,RunIteratorQueue & runSegmenter,const BiDiRunIterator * bidi,const LanguageRunIterator * language,const ScriptRunIterator * script,const FontRunIterator * font) const1096 SkPoint SkShaperHarfBuzz::shapeOk(RunHandler* handler,
1097                                    const char* utf8,
1098                                    size_t utf8Bytes,
1099                                    SkPoint point,
1100                                    SkScalar width,
1101                                    RunIteratorQueue& runSegmenter,
1102                                    const BiDiRunIterator* bidi,
1103                                    const LanguageRunIterator* language,
1104                                    const ScriptRunIterator* script,
1105                                    const FontRunIterator* font) const
1106 {
1107     SkTArray<ShapedRun> runs;
1108 {
1109     UBreakIterator& lineBreakIterator = *fLineBreakIterator;
1110     UBreakIterator& graphemeBreakIterator = *fGraphemeBreakIterator;
1111     {
1112         UErrorCode status = U_ZERO_ERROR;
1113         UText utf8UText = UTEXT_INITIALIZER;
1114         utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
1115         std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
1116         if (U_FAILURE(status)) {
1117             SkDebugf("Could not create utf8UText: %s", u_errorName(status));
1118             return point;
1119         }
1120 
1121         ubrk_setUText(&lineBreakIterator, &utf8UText, &status);
1122         if (U_FAILURE(status)) {
1123             SkDebugf("Could not setText on line break iterator: %s", u_errorName(status));
1124             return point;
1125         }
1126         ubrk_setUText(&graphemeBreakIterator, &utf8UText, &status);
1127         if (U_FAILURE(status)) {
1128             SkDebugf("Could not setText on grapheme break iterator: %s", u_errorName(status));
1129             return point;
1130         }
1131     }
1132 
1133     const char* utf8Start = nullptr;
1134     const char* utf8End = utf8;
1135     while (runSegmenter.advanceRuns()) {
1136         utf8Start = utf8End;
1137         utf8End = runSegmenter.endOfCurrentRun();
1138 
1139         runs.emplace_back(shape(utf8, utf8Bytes,
1140                                 utf8Start, utf8End,
1141                                 bidi, language, script, font));
1142         ShapedRun& run = runs.back();
1143 
1144         uint32_t previousCluster = 0xFFFFFFFF;
1145         for (int i = 0; i < run.fNumGlyphs; ++i) {
1146             ShapedGlyph& glyph = run.fGlyphs[i];
1147             int32_t glyphCluster = glyph.fCluster;
1148 
1149             int32_t lineBreakIteratorCurrent = ubrk_current(&lineBreakIterator);
1150             while (lineBreakIteratorCurrent != UBRK_DONE &&
1151                    lineBreakIteratorCurrent < glyphCluster)
1152             {
1153                 lineBreakIteratorCurrent = ubrk_next(&lineBreakIterator);
1154             }
1155             glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
1156                                         lineBreakIteratorCurrent == glyphCluster;
1157 
1158             int32_t graphemeBreakIteratorCurrent = ubrk_current(&graphemeBreakIterator);
1159             while (graphemeBreakIteratorCurrent != UBRK_DONE &&
1160                    graphemeBreakIteratorCurrent < glyphCluster)
1161             {
1162                 graphemeBreakIteratorCurrent = ubrk_next(&graphemeBreakIterator);
1163             }
1164             glyph.fGraphemeBreakBefore = glyph.fCluster != previousCluster &&
1165                                          graphemeBreakIteratorCurrent == glyphCluster;
1166 
1167             previousCluster = glyph.fCluster;
1168         }
1169     }
1170 }
1171 
1172 // Iterate over the glyphs in logical order to find potential line lengths.
1173 {
1174     /** The position of the beginning of the line. */
1175     ShapedRunGlyphIterator beginning(runs);
1176 
1177     /** The position of the candidate line break. */
1178     ShapedRunGlyphIterator candidateLineBreak(runs);
1179     SkScalar candidateLineBreakWidth = 0;
1180 
1181     /** The position of the candidate grapheme break. */
1182     ShapedRunGlyphIterator candidateGraphemeBreak(runs);
1183     SkScalar candidateGraphemeBreakWidth = 0;
1184 
1185     /** The position of the current location. */
1186     ShapedRunGlyphIterator current(runs);
1187     SkScalar currentWidth = 0;
1188     while (ShapedGlyph* glyph = current.current()) {
1189         // 'Break' at graphemes until a line boundary, then only at line boundaries.
1190         // Only break at graphemes if no line boundary is valid.
1191         if (current != beginning) {
1192             if (glyph->fGraphemeBreakBefore || glyph->fMayLineBreakBefore) {
1193                 // TODO: preserve line breaks <= grapheme breaks
1194                 // and prevent line breaks inside graphemes
1195                 candidateGraphemeBreak = current;
1196                 candidateGraphemeBreakWidth = currentWidth;
1197                 if (glyph->fMayLineBreakBefore) {
1198                     candidateLineBreak = current;
1199                     candidateLineBreakWidth = currentWidth;
1200                 }
1201             }
1202         }
1203 
1204         SkScalar glyphWidth = glyph->fAdvance.fX;
1205         // Break when overwidth, the glyph has a visual representation, and some space is used.
1206         if (width < currentWidth + glyphWidth && glyph->fHasVisual && candidateGraphemeBreakWidth > 0){
1207             if (candidateLineBreak != beginning) {
1208                 beginning = candidateLineBreak;
1209                 currentWidth -= candidateLineBreakWidth;
1210                 candidateGraphemeBreakWidth -= candidateLineBreakWidth;
1211                 candidateLineBreakWidth = 0;
1212             } else if (candidateGraphemeBreak != beginning) {
1213                 beginning = candidateGraphemeBreak;
1214                 candidateLineBreak = beginning;
1215                 currentWidth -= candidateGraphemeBreakWidth;
1216                 candidateGraphemeBreakWidth = 0;
1217                 candidateLineBreakWidth = 0;
1218             } else {
1219                 SK_ABORT("");
1220             }
1221 
1222             if (width < currentWidth) {
1223                 if (width < candidateGraphemeBreakWidth) {
1224                     candidateGraphemeBreak = candidateLineBreak;
1225                     candidateGraphemeBreakWidth = candidateLineBreakWidth;
1226                 }
1227                 current = candidateGraphemeBreak;
1228                 currentWidth = candidateGraphemeBreakWidth;
1229             }
1230 
1231             glyph = beginning.current();
1232             if (glyph) {
1233                 glyph->fMustLineBreakBefore = true;
1234             }
1235 
1236         } else {
1237             current.next();
1238             currentWidth += glyphWidth;
1239         }
1240     }
1241 }
1242 
1243 // Reorder the runs and glyphs per line and write them out.
1244     SkPoint currentPoint = point;
1245 {
1246     ShapedRunGlyphIterator previousBreak(runs);
1247     ShapedRunGlyphIterator glyphIterator(runs);
1248     SkScalar maxAscent = 0;
1249     SkScalar maxDescent = 0;
1250     SkScalar maxLeading = 0;
1251     int previousRunIndex = -1;
1252     while (glyphIterator.current()) {
1253         int runIndex = glyphIterator.fRunIndex;
1254         int glyphIndex = glyphIterator.fGlyphIndex;
1255         ShapedGlyph* nextGlyph = glyphIterator.next();
1256 
1257         if (previousRunIndex != runIndex) {
1258             SkFontMetrics metrics;
1259             runs[runIndex].fFont.getMetrics(&metrics);
1260             maxAscent = SkTMin(maxAscent, metrics.fAscent);
1261             maxDescent = SkTMax(maxDescent, metrics.fDescent);
1262             maxLeading = SkTMax(maxLeading, metrics.fLeading);
1263             previousRunIndex = runIndex;
1264         }
1265 
1266         // Nothing can be written until the baseline is known.
1267         if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
1268             continue;
1269         }
1270 
1271         currentPoint.fY -= maxAscent;
1272 
1273         int numRuns = runIndex - previousBreak.fRunIndex + 1;
1274         SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
1275         for (int i = 0; i < numRuns; ++i) {
1276             runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
1277         }
1278         SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
1279         ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
1280 
1281         // step through the runs in reverse visual order and the glyphs in reverse logical order
1282         // until a visible glyph is found and force them to the end of the visual line.
1283 
1284         for (int i = 0; i < numRuns; ++i) {
1285             int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
1286 
1287             int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
1288                                 ? previousBreak.fGlyphIndex
1289                                 : 0;
1290             int endGlyphIndex = (logicalIndex == runIndex)
1291                               ? glyphIndex + 1
1292                               : runs[logicalIndex].fNumGlyphs;
1293 
1294             const auto& run = runs[logicalIndex];
1295             const RunHandler::RunInfo info = {
1296                 run.fAdvance,
1297                 maxAscent,
1298                 maxDescent,
1299                 maxLeading,
1300             };
1301             append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
1302         }
1303 
1304         handler->commitLine();
1305 
1306         currentPoint.fY += maxDescent + maxLeading;
1307         currentPoint.fX = point.fX;
1308         maxAscent = 0;
1309         maxDescent = 0;
1310         maxLeading = 0;
1311         previousRunIndex = -1;
1312         previousBreak = glyphIterator;
1313     }
1314 }
1315 
1316     return currentPoint;
1317 }
1318 
1319 
shape(const char * utf8,const size_t utf8Bytes,const char * utf8Start,const char * utf8End,const BiDiRunIterator * bidi,const LanguageRunIterator * language,const ScriptRunIterator * script,const FontRunIterator * font) const1320 ShapedRun SkShaperHarfBuzz::shape(const char* utf8,
1321                                    const size_t utf8Bytes,
1322                                    const char* utf8Start,
1323                                    const char* utf8End,
1324                                    const BiDiRunIterator* bidi,
1325                                    const LanguageRunIterator* language,
1326                                    const ScriptRunIterator* script,
1327                                    const FontRunIterator* font) const
1328 {
1329     ShapedRun run(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
1330 
1331     hb_buffer_t* buffer = fBuffer.get();
1332     SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
1333     hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1334     hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
1335 
1336     // See 763e5466c0a03a7c27020e1e2598e488612529a7 for documentation.
1337     hb_buffer_set_flags(buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
1338 
1339     // Add precontext.
1340     hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
1341 
1342     // Populate the hb_buffer directly with utf8 cluster indexes.
1343     const char* utf8Current = utf8Start;
1344     while (utf8Current < utf8End) {
1345         unsigned int cluster = utf8Current - utf8;
1346         hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
1347         hb_buffer_add(buffer, u, cluster);
1348     }
1349 
1350     // Add postcontext.
1351     hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
1352 
1353     size_t utf8runLength = utf8End - utf8Start;
1354     if (!SkTFitsIn<int>(utf8runLength)) {
1355         SkDebugf("Shaping error: utf8 too long");
1356         return run;
1357     }
1358     hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
1359     hb_buffer_set_direction(buffer, direction);
1360     hb_buffer_set_script(buffer, script->currentScript());
1361     hb_buffer_set_language(buffer, language->currentLanguage());
1362     hb_buffer_guess_segment_properties(buffer);
1363     // TODO: features
1364     if (!font->currentHBFont()) {
1365         return run;
1366     }
1367     hb_shape(font->currentHBFont(), buffer, nullptr, 0);
1368     unsigned len = hb_buffer_get_length(buffer);
1369     if (len == 0) {
1370         // TODO: this isn't an error, make it look different
1371         return run;
1372     }
1373 
1374     if (direction == HB_DIRECTION_RTL) {
1375         // Put the clusters back in logical order.
1376         // Note that the advances remain ltr.
1377         hb_buffer_reverse(buffer);
1378     }
1379     hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
1380     hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
1381 
1382     if (!SkTFitsIn<int>(len)) {
1383         SkDebugf("Shaping error: too many glyphs");
1384         return run;
1385     }
1386 
1387     run = ShapedRun(SkSpan<const char>(utf8Start, utf8runLength),
1388                     *font->currentFont(), bidi->currentLevel(),
1389                     std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]), len);
1390     int scaleX, scaleY;
1391     hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
1392     double textSizeY = run.fFont.getSize() / scaleY;
1393     double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
1394     SkVector runAdvance = { 0, 0 };
1395     for (unsigned i = 0; i < len; i++) {
1396         ShapedGlyph& glyph = run.fGlyphs[i];
1397         glyph.fID = info[i].codepoint;
1398         glyph.fCluster = info[i].cluster;
1399         glyph.fOffset.fX = pos[i].x_offset * textSizeX;
1400         glyph.fOffset.fY = pos[i].y_offset * textSizeY;
1401         glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
1402         glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
1403 
1404         SkRect bounds;
1405         SkScalar advance;
1406         SkPaint p;
1407         run.fFont.getWidthsBounds(&glyph.fID, 1, &advance, &bounds, &p);
1408         glyph.fHasVisual = !bounds.isEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1409 #if SK_HB_VERSION_CHECK(1, 5, 0)
1410         glyph.fUnsafeToBreak = info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
1411 #else
1412         glyph.fUnsafeToBreak = false;
1413 #endif
1414         glyph.fMustLineBreakBefore = false;
1415 
1416         runAdvance += glyph.fAdvance;
1417     }
1418     run.fAdvance = runAdvance;
1419 
1420     return run;
1421 }
1422