• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkFont.h"
9 #include "include/core/SkFontArguments.h"
10 #include "include/core/SkFontMetrics.h"
11 #include "include/core/SkFontMgr.h"
12 #include "include/core/SkFontTypes.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/core/SkScalar.h"
18 #include "include/core/SkSpan.h"
19 #include "include/core/SkStream.h"
20 #include "include/core/SkTypeface.h"
21 #include "include/core/SkTypes.h"
22 #include "include/private/SkBitmaskEnum.h"
23 #include "include/private/SkMalloc.h"
24 #include "include/private/SkMutex.h"
25 #include "include/private/SkTArray.h"
26 #include "include/private/SkTFitsIn.h"
27 #include "include/private/SkTemplates.h"
28 #include "include/private/SkTo.h"
29 #include "modules/skshaper/include/SkShaper.h"
30 #include "modules/skshaper/src/SkUnicode.h"
31 #include "src/core/SkLRUCache.h"
32 #include "src/core/SkTDPQueue.h"
33 #include "src/utils/SkUTF.h"
34 
35 #include <hb.h>
36 #include <hb-icu.h>
37 #include <hb-ot.h>
38 #include <unicode/uscript.h>
39 #include <cstring>
40 #include <memory>
41 #include <type_traits>
42 #include <utility>
43 
44 // HB_FEATURE_GLOBAL_START and HB_FEATURE_GLOBAL_END were not added until HarfBuzz 2.0
45 // They would have always worked, they just hadn't been named yet.
46 #if !defined(HB_FEATURE_GLOBAL_START)
47 #  define HB_FEATURE_GLOBAL_START 0
48 #endif
49 #if !defined(HB_FEATURE_GLOBAL_END)
50 # define HB_FEATURE_GLOBAL_END ((unsigned int) -1)
51 #endif
52 
53 namespace sknonstd {
54 template <> struct is_bitmask_enum<hb_buffer_flags_t> : std::true_type {};
55 }  // namespace sknonstd
56 
57 namespace {
58 template <typename T,typename P,P* p> using resource = std::unique_ptr<T, SkFunctionWrapper<P, p>>;
59 using HBBlob   = resource<hb_blob_t     , decltype(hb_blob_destroy)  , hb_blob_destroy  >;
60 using HBFace   = resource<hb_face_t     , decltype(hb_face_destroy)  , hb_face_destroy  >;
61 using HBFont   = resource<hb_font_t     , decltype(hb_font_destroy)  , hb_font_destroy  >;
62 using HBBuffer = resource<hb_buffer_t   , decltype(hb_buffer_destroy), hb_buffer_destroy>;
63 
64 using SkUnicodeBidi = std::unique_ptr<SkBidiIterator>;
65 using SkUnicodeBreak = std::unique_ptr<SkBreakIterator>;
66 using SkUnicodeScript = std::unique_ptr<SkScriptIterator>;
67 
skhb_position(SkScalar value)68 hb_position_t skhb_position(SkScalar value) {
69     // Treat HarfBuzz hb_position_t as 16.16 fixed-point.
70     constexpr int kHbPosition1 = 1 << 16;
71     return SkScalarRoundToInt(value * kHbPosition1);
72 }
73 
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)74 hb_bool_t skhb_glyph(hb_font_t* hb_font,
75                      void* font_data,
76                      hb_codepoint_t unicode,
77                      hb_codepoint_t variation_selector,
78                      hb_codepoint_t* glyph,
79                      void* user_data) {
80     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
81 
82     *glyph = font.unicharToGlyph(unicode);
83     return *glyph != 0;
84 }
85 
skhb_nominal_glyph(hb_font_t * hb_font,void * font_data,hb_codepoint_t unicode,hb_codepoint_t * glyph,void * user_data)86 hb_bool_t skhb_nominal_glyph(hb_font_t* hb_font,
87                              void* font_data,
88                              hb_codepoint_t unicode,
89                              hb_codepoint_t* glyph,
90                              void* user_data) {
91   return skhb_glyph(hb_font, font_data, unicode, 0, glyph, user_data);
92 }
93 
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)94 unsigned skhb_nominal_glyphs(hb_font_t *hb_font, void *font_data,
95                              unsigned int count,
96                              const hb_codepoint_t *unicodes,
97                              unsigned int unicode_stride,
98                              hb_codepoint_t *glyphs,
99                              unsigned int glyph_stride,
100                              void *user_data) {
101     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
102 
103     // Batch call textToGlyphs since entry cost is not cheap.
104     // Copy requred because textToGlyphs is dense and hb is strided.
105     SkAutoSTMalloc<256, SkUnichar> unicode(count);
106     for (unsigned i = 0; i < count; i++) {
107         unicode[i] = *unicodes;
108         unicodes = SkTAddOffset<const hb_codepoint_t>(unicodes, unicode_stride);
109     }
110     SkAutoSTMalloc<256, SkGlyphID> glyph(count);
111     font.textToGlyphs(unicode.get(), count * sizeof(SkUnichar), SkTextEncoding::kUTF32,
112                         glyph.get(), count);
113 
114     // Copy the results back to the sparse array.
115     unsigned int done;
116     for (done = 0; done < count && glyph[done] != 0; done++) {
117         *glyphs = glyph[done];
118         glyphs = SkTAddOffset<hb_codepoint_t>(glyphs, glyph_stride);
119     }
120     // return 'done' to allow HarfBuzz to synthesize with NFC and spaces, return 'count' to avoid
121     return done;
122 }
123 
skhb_glyph_h_advance(hb_font_t * hb_font,void * font_data,hb_codepoint_t hbGlyph,void * user_data)124 hb_position_t skhb_glyph_h_advance(hb_font_t* hb_font,
125                                    void* font_data,
126                                    hb_codepoint_t hbGlyph,
127                                    void* user_data) {
128     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
129 
130     SkScalar advance;
131     SkGlyphID skGlyph = SkTo<SkGlyphID>(hbGlyph);
132 
133     font.getWidths(&skGlyph, 1, &advance);
134     if (!font.isSubpixel()) {
135         advance = SkScalarRoundToInt(advance);
136     }
137     return skhb_position(advance);
138 }
139 
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)140 void skhb_glyph_h_advances(hb_font_t* hb_font,
141                            void* font_data,
142                            unsigned count,
143                            const hb_codepoint_t* glyphs,
144                            unsigned int glyph_stride,
145                            hb_position_t* advances,
146                            unsigned int advance_stride,
147                            void* user_data) {
148     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
149 
150     // Batch call getWidths since entry cost is not cheap.
151     // Copy requred because getWidths is dense and hb is strided.
152     SkAutoSTMalloc<256, SkGlyphID> glyph(count);
153     for (unsigned i = 0; i < count; i++) {
154         glyph[i] = *glyphs;
155         glyphs = SkTAddOffset<const hb_codepoint_t>(glyphs, glyph_stride);
156     }
157     SkAutoSTMalloc<256, SkScalar> advance(count);
158     font.getWidths(glyph.get(), count, advance.get());
159 
160     if (!font.isSubpixel()) {
161         for (unsigned i = 0; i < count; i++) {
162             advance[i] = SkScalarRoundToInt(advance[i]);
163         }
164     }
165 
166     // Copy the results back to the sparse array.
167     for (unsigned i = 0; i < count; i++) {
168         *advances = skhb_position(advance[i]);
169         advances = SkTAddOffset<hb_position_t>(advances, advance_stride);
170     }
171 }
172 
173 // HarfBuzz callback to retrieve glyph extents, mainly used by HarfBuzz for
174 // fallback mark positioning, i.e. the situation when the font does not have
175 // mark anchors or other mark positioning rules, but instead HarfBuzz is
176 // supposed to heuristically place combining marks around base glyphs. HarfBuzz
177 // does this by measuring "ink boxes" of glyphs, and placing them according to
178 // 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 hbGlyph,hb_glyph_extents_t * extents,void * user_data)179 hb_bool_t skhb_glyph_extents(hb_font_t* hb_font,
180                              void* font_data,
181                              hb_codepoint_t hbGlyph,
182                              hb_glyph_extents_t* extents,
183                              void* user_data) {
184     SkFont& font = *reinterpret_cast<SkFont*>(font_data);
185     SkASSERT(extents);
186 
187     SkRect sk_bounds;
188     SkGlyphID skGlyph = SkTo<SkGlyphID>(hbGlyph);
189 
190     font.getWidths(&skGlyph, 1, nullptr, &sk_bounds);
191     if (!font.isSubpixel()) {
192         sk_bounds.set(sk_bounds.roundOut());
193     }
194 
195     // Skia is y-down but HarfBuzz is y-up.
196     extents->x_bearing = skhb_position(sk_bounds.fLeft);
197     extents->y_bearing = skhb_position(-sk_bounds.fTop);
198     extents->width = skhb_position(sk_bounds.width());
199     extents->height = skhb_position(-sk_bounds.height());
200     return true;
201 }
202 
203 #define SK_HB_VERSION_CHECK(x, y, z) \
204     (HB_VERSION_MAJOR >  (x)) || \
205     (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR >  (y)) || \
206     (HB_VERSION_MAJOR == (x) && HB_VERSION_MINOR == (y) && HB_VERSION_MICRO >= (z))
207 
skhb_get_font_funcs()208 hb_font_funcs_t* skhb_get_font_funcs() {
209     static hb_font_funcs_t* const funcs = []{
210         // HarfBuzz will use the default (parent) implementation if they aren't set.
211         hb_font_funcs_t* const funcs = hb_font_funcs_create();
212         hb_font_funcs_set_variation_glyph_func(funcs, skhb_glyph, nullptr, nullptr);
213         hb_font_funcs_set_nominal_glyph_func(funcs, skhb_nominal_glyph, nullptr, nullptr);
214 #if SK_HB_VERSION_CHECK(2, 0, 0)
215         hb_font_funcs_set_nominal_glyphs_func(funcs, skhb_nominal_glyphs, nullptr, nullptr);
216 #else
217         sk_ignore_unused_variable(skhb_nominal_glyphs);
218 #endif
219         hb_font_funcs_set_glyph_h_advance_func(funcs, skhb_glyph_h_advance, nullptr, nullptr);
220 #if SK_HB_VERSION_CHECK(1, 8, 6)
221         hb_font_funcs_set_glyph_h_advances_func(funcs, skhb_glyph_h_advances, nullptr, nullptr);
222 #else
223         sk_ignore_unused_variable(skhb_glyph_h_advances);
224 #endif
225         hb_font_funcs_set_glyph_extents_func(funcs, skhb_glyph_extents, nullptr, nullptr);
226         hb_font_funcs_make_immutable(funcs);
227         return funcs;
228     }();
229     SkASSERT(funcs);
230     return funcs;
231 }
232 
skhb_get_table(hb_face_t * face,hb_tag_t tag,void * user_data)233 hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
234     SkTypeface& typeface = *reinterpret_cast<SkTypeface*>(user_data);
235 
236     auto data = typeface.copyTableData(tag);
237     if (!data) {
238         return nullptr;
239     }
240     SkData* rawData = data.release();
241     return hb_blob_create(reinterpret_cast<char*>(rawData->writable_data()), rawData->size(),
242                           HB_MEMORY_MODE_READONLY, rawData, [](void* ctx) {
243                               SkSafeUnref(((SkData*)ctx));
244                           });
245 }
246 
stream_to_blob(std::unique_ptr<SkStreamAsset> asset)247 HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
248     size_t size = asset->getLength();
249     HBBlob blob;
250     if (const void* base = asset->getMemoryBase()) {
251         blob.reset(hb_blob_create((char*)base, SkToUInt(size),
252                                   HB_MEMORY_MODE_READONLY, asset.release(),
253                                   [](void* p) { delete (SkStreamAsset*)p; }));
254     } else {
255         // SkDebugf("Extra SkStreamAsset copy\n");
256         void* ptr = size ? sk_malloc_throw(size) : nullptr;
257         asset->read(ptr, size);
258         blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
259                                   HB_MEMORY_MODE_READONLY, ptr, sk_free));
260     }
261     SkASSERT(blob);
262     hb_blob_make_immutable(blob.get());
263     return blob;
264 }
265 
SkDEBUGCODE(static hb_user_data_key_t gDataIdKey;)266 SkDEBUGCODE(static hb_user_data_key_t gDataIdKey;)
267 
268 HBFace create_hb_face(const SkTypeface& typeface) {
269     int index;
270     std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openStream(&index);
271     HBFace face;
272     if (typefaceAsset && typefaceAsset->getMemoryBase()) {
273         HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
274         face.reset(hb_face_create(blob.get(), (unsigned)index));
275     } else {
276         face.reset(hb_face_create_for_tables(
277             skhb_get_table,
278             const_cast<SkTypeface*>(SkRef(&typeface)),
__anonea9152db0502(void* user_data)279             [](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
280     }
281     SkASSERT(face);
282     if (!face) {
283         return nullptr;
284     }
285     hb_face_set_index(face.get(), (unsigned)index);
286     hb_face_set_upem(face.get(), typeface.getUnitsPerEm());
287 
288     SkDEBUGCODE(
289         hb_face_set_user_data(face.get(), &gDataIdKey, const_cast<SkTypeface*>(&typeface),
290                               nullptr, false);
291     )
292 
293     return face;
294 }
295 
create_hb_font(const SkFont & font,const HBFace & face)296 HBFont create_hb_font(const SkFont& font, const HBFace& face) {
297     SkDEBUGCODE(
298         void* dataId = hb_face_get_user_data(face.get(), &gDataIdKey);
299         SkASSERT(dataId == font.getTypeface());
300     )
301 
302     HBFont otFont(hb_font_create(face.get()));
303     SkASSERT(otFont);
304     if (!otFont) {
305         return nullptr;
306     }
307     hb_ot_font_set_funcs(otFont.get());
308     int axis_count = font.getTypeface()->getVariationDesignPosition(nullptr, 0);
309     if (axis_count > 0) {
310         SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
311         if (font.getTypeface()->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
312             hb_font_set_variations(otFont.get(),
313                                    reinterpret_cast<hb_variation_t*>(axis_values.get()),
314                                    axis_count);
315         }
316     }
317 
318     // Creating a sub font means that non-available functions
319     // are found from the parent.
320     HBFont skFont(hb_font_create_sub_font(otFont.get()));
321     hb_font_set_funcs(skFont.get(), skhb_get_font_funcs(),
322                       reinterpret_cast<void *>(new SkFont(font)),
323                       [](void* user_data){ delete reinterpret_cast<SkFont*>(user_data); });
324     int scale = skhb_position(font.getSize());
325     hb_font_set_scale(skFont.get(), scale, scale);
326 
327     return skFont;
328 }
329 
330 /** Replaces invalid utf-8 sequences with REPLACEMENT CHARACTER U+FFFD. */
utf8_next(const char ** ptr,const char * end)331 static inline SkUnichar utf8_next(const char** ptr, const char* end) {
332     SkUnichar val = SkUTF::NextUTF8(ptr, end);
333     return val < 0 ? 0xFFFD : val;
334 }
335 
336 class SkUnicodeBidiRunIterator final : public SkShaper::BiDiRunIterator {
337 public:
SkUnicodeBidiRunIterator(const char * utf8,const char * end,SkUnicodeBidi bidi)338     SkUnicodeBidiRunIterator(const char* utf8, const char* end, SkUnicodeBidi bidi)
339         : fBidi(std::move(bidi))
340         , fEndOfCurrentRun(utf8)
341         , fBegin(utf8)
342         , fEnd(end)
343         , fUTF16LogicalPosition(0)
344         , fLevel(SkBidiIterator::kLTR)
345     {}
346 
consume()347     void consume() override {
348         SkASSERT(fUTF16LogicalPosition < fBidi->getLength());
349         int32_t endPosition = fBidi->getLength();
350         fLevel = fBidi->getLevelAt(fUTF16LogicalPosition);
351         SkUnichar u = utf8_next(&fEndOfCurrentRun, fEnd);
352         fUTF16LogicalPosition += SkUTF::ToUTF16(u);
353         SkBidiIterator::Level level;
354         while (fUTF16LogicalPosition < endPosition) {
355             level = fBidi->getLevelAt(fUTF16LogicalPosition);
356             if (level != fLevel) {
357                 break;
358             }
359             u = utf8_next(&fEndOfCurrentRun, fEnd);
360 
361             fUTF16LogicalPosition += SkUTF::ToUTF16(u);
362         }
363     }
endOfCurrentRun() const364     size_t endOfCurrentRun() const override {
365         return fEndOfCurrentRun - fBegin;
366     }
atEnd() const367     bool atEnd() const override {
368         return fUTF16LogicalPosition == fBidi->getLength();
369     }
currentLevel() const370     SkBidiIterator::Level currentLevel() const override {
371         return fLevel;
372     }
373 private:
374     SkUnicodeBidi fBidi;
375     char const * fEndOfCurrentRun;
376     char const * const fBegin;
377     char const * const fEnd;
378     int32_t fUTF16LogicalPosition;
379     SkBidiIterator::Level fLevel;
380 };
381 
382 class SkUnicodeHbScriptRunIterator final: public SkShaper::ScriptRunIterator {
383 public:
SkUnicodeHbScriptRunIterator(SkUnicodeScript script,const char * utf8,size_t utf8Bytes)384     SkUnicodeHbScriptRunIterator(SkUnicodeScript script, const char* utf8, size_t utf8Bytes)
385         : fScript(std::move(script))
386         , fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
387         , fCurrentScript(HB_SCRIPT_UNKNOWN)
388     {}
hb_script_from_icu(SkUnichar u)389     hb_script_t hb_script_from_icu(SkUnichar u) {
390         SkScriptIterator::ScriptID scriptId;
391         if (!fScript->getScript(u, &scriptId)) {
392             return HB_SCRIPT_UNKNOWN;
393         }
394         return hb_icu_script_to_script((UScriptCode)scriptId);
395     }
consume()396     void consume() override {
397         SkASSERT(fCurrent < fEnd);
398         SkUnichar u = utf8_next(&fCurrent, fEnd);
399         fCurrentScript = hb_script_from_icu(u);
400         while (fCurrent < fEnd) {
401             const char* prev = fCurrent;
402             u = utf8_next(&fCurrent, fEnd);
403             const hb_script_t script = hb_script_from_icu(u);
404             if (script != fCurrentScript) {
405                 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
406                     fCurrentScript = script;
407                 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
408                     continue;
409                 } else {
410                     fCurrent = prev;
411                     break;
412                 }
413             }
414         }
415         if (fCurrentScript == HB_SCRIPT_INHERITED) {
416             fCurrentScript = HB_SCRIPT_COMMON;
417         }
418     }
endOfCurrentRun() const419     size_t endOfCurrentRun() const override {
420         return fCurrent - fBegin;
421     }
atEnd() const422     bool atEnd() const override {
423         return fCurrent == fEnd;
424     }
425 
currentScript() const426     SkFourByteTag currentScript() const override {
427         return SkSetFourByteTag(HB_UNTAG(fCurrentScript));
428     }
429 private:
430     SkUnicodeScript fScript;
431     char const * fCurrent;
432     char const * const fBegin;
433     char const * const fEnd;
434     hb_script_t fCurrentScript;
435 };
436 
437 class RunIteratorQueue {
438 public:
insert(SkShaper::RunIterator * runIterator,int priority)439     void insert(SkShaper::RunIterator* runIterator, int priority) {
440         fEntries.insert({runIterator, priority});
441     }
442 
advanceRuns()443     bool advanceRuns() {
444         const SkShaper::RunIterator* leastRun = fEntries.peek().runIterator;
445         if (leastRun->atEnd()) {
446             SkASSERT(this->allRunsAreAtEnd());
447             return false;
448         }
449         const size_t leastEnd = leastRun->endOfCurrentRun();
450         SkShaper::RunIterator* currentRun = nullptr;
451         SkDEBUGCODE(size_t previousEndOfCurrentRun);
452         while ((currentRun = fEntries.peek().runIterator)->endOfCurrentRun() <= leastEnd) {
453             int priority = fEntries.peek().priority;
454             fEntries.pop();
455             SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
456             currentRun->consume();
457             SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
458             fEntries.insert({currentRun, priority});
459         }
460         return true;
461     }
462 
endOfCurrentRun() const463     size_t endOfCurrentRun() const {
464         return fEntries.peek().runIterator->endOfCurrentRun();
465     }
466 
467 private:
allRunsAreAtEnd() const468     bool allRunsAreAtEnd() const {
469         for (int i = 0; i < fEntries.count(); ++i) {
470             if (!fEntries.at(i).runIterator->atEnd()) {
471                 return false;
472             }
473         }
474         return true;
475     }
476 
477     struct Entry {
478         SkShaper::RunIterator* runIterator;
479         int priority;
480     };
CompareEntry(Entry const & a,Entry const & b)481     static bool CompareEntry(Entry const& a, Entry const& b) {
482         size_t aEnd = a.runIterator->endOfCurrentRun();
483         size_t bEnd = b.runIterator->endOfCurrentRun();
484         return aEnd  < bEnd || (aEnd == bEnd && a.priority < b.priority);
485     }
486     SkTDPQueue<Entry, CompareEntry> fEntries;
487 };
488 
489 struct ShapedGlyph {
490     SkGlyphID fID;
491     uint32_t fCluster;
492     SkPoint fOffset;
493     SkVector fAdvance;
494     bool fMayLineBreakBefore;
495     bool fMustLineBreakBefore;
496     bool fHasVisual;
497     bool fGraphemeBreakBefore;
498     bool fUnsafeToBreak;
499 };
500 struct ShapedRun {
ShapedRun__anonea9152db0111::ShapedRun501     ShapedRun(SkShaper::RunHandler::Range utf8Range, const SkFont& font, SkBidiIterator::Level level,
502               std::unique_ptr<ShapedGlyph[]> glyphs, size_t numGlyphs, SkVector advance = {0, 0})
503         : fUtf8Range(utf8Range), fFont(font), fLevel(level)
504         , fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs), fAdvance(advance)
505     {}
506 
507     SkShaper::RunHandler::Range fUtf8Range;
508     SkFont fFont;
509     SkBidiIterator::Level fLevel;
510     std::unique_ptr<ShapedGlyph[]> fGlyphs;
511     size_t fNumGlyphs;
512     SkVector fAdvance;
513 };
514 struct ShapedLine {
515     SkTArray<ShapedRun> runs;
516     SkVector fAdvance = { 0, 0 };
517 };
518 
is_LTR(SkBidiIterator::Level level)519 constexpr bool is_LTR(SkBidiIterator::Level level) {
520     return (level & 1) == 0;
521 }
522 
append(SkShaper::RunHandler * handler,const SkShaper::RunHandler::RunInfo & runInfo,const ShapedRun & run,size_t startGlyphIndex,size_t endGlyphIndex)523 void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
524                    const ShapedRun& run, size_t startGlyphIndex, size_t endGlyphIndex) {
525     SkASSERT(startGlyphIndex <= endGlyphIndex);
526     const size_t glyphLen = endGlyphIndex - startGlyphIndex;
527 
528     const auto buffer = handler->runBuffer(runInfo);
529     SkASSERT(buffer.glyphs);
530     SkASSERT(buffer.positions);
531 
532     SkVector advance = {0,0};
533     for (size_t i = 0; i < glyphLen; i++) {
534         // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
535         const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? startGlyphIndex + i
536                                                                   : endGlyphIndex - 1 - i];
537         buffer.glyphs[i] = glyph.fID;
538         if (buffer.offsets) {
539             buffer.positions[i] = advance + buffer.point;
540             buffer.offsets[i] = glyph.fOffset;
541         } else {
542             buffer.positions[i] = advance + buffer.point + glyph.fOffset;
543         }
544         if (buffer.clusters) {
545             buffer.clusters[i] = glyph.fCluster;
546         }
547         advance += glyph.fAdvance;
548     }
549     handler->commitRunBuffer(runInfo);
550 }
551 
emit(const ShapedLine & line,SkShaper::RunHandler * handler)552 void emit(const ShapedLine& line, SkShaper::RunHandler* handler) {
553     // Reorder the runs and glyphs per line and write them out.
554     handler->beginLine();
555 
556     int numRuns = line.runs.size();
557     SkAutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
558     for (int i = 0; i < numRuns; ++i) {
559         runLevels[i] = line.runs[i].fLevel;
560     }
561     SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
562     SkBidiIterator::ReorderVisual(runLevels, numRuns, logicalFromVisual);
563 
564     for (int i = 0; i < numRuns; ++i) {
565         int logicalIndex = logicalFromVisual[i];
566 
567         const auto& run = line.runs[logicalIndex];
568         const SkShaper::RunHandler::RunInfo info = {
569             run.fFont,
570             run.fLevel,
571             run.fAdvance,
572             run.fNumGlyphs,
573             run.fUtf8Range
574         };
575         handler->runInfo(info);
576     }
577     handler->commitRunInfo();
578     for (int i = 0; i < numRuns; ++i) {
579         int logicalIndex = logicalFromVisual[i];
580 
581         const auto& run = line.runs[logicalIndex];
582         const SkShaper::RunHandler::RunInfo info = {
583             run.fFont,
584             run.fLevel,
585             run.fAdvance,
586             run.fNumGlyphs,
587             run.fUtf8Range
588         };
589         append(handler, info, run, 0, run.fNumGlyphs);
590     }
591 
592     handler->commitLine();
593 }
594 
595 struct ShapedRunGlyphIterator {
ShapedRunGlyphIterator__anonea9152db0111::ShapedRunGlyphIterator596     ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
597         : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
598     { }
599 
600     ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
601     ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
operator ==__anonea9152db0111::ShapedRunGlyphIterator602     bool operator==(const ShapedRunGlyphIterator& that) const {
603         return fRuns == that.fRuns &&
604                fRunIndex == that.fRunIndex &&
605                fGlyphIndex == that.fGlyphIndex;
606     }
operator !=__anonea9152db0111::ShapedRunGlyphIterator607     bool operator!=(const ShapedRunGlyphIterator& that) const {
608         return fRuns != that.fRuns ||
609                fRunIndex != that.fRunIndex ||
610                fGlyphIndex != that.fGlyphIndex;
611     }
612 
next__anonea9152db0111::ShapedRunGlyphIterator613     ShapedGlyph* next() {
614         const SkTArray<ShapedRun>& runs = *fRuns;
615         SkASSERT(fRunIndex < runs.count());
616         SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
617 
618         ++fGlyphIndex;
619         if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
620             fGlyphIndex = 0;
621             ++fRunIndex;
622             if (fRunIndex >= runs.count()) {
623                 return nullptr;
624             }
625         }
626         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
627     }
628 
current__anonea9152db0111::ShapedRunGlyphIterator629     ShapedGlyph* current() {
630         const SkTArray<ShapedRun>& runs = *fRuns;
631         if (fRunIndex >= runs.count()) {
632             return nullptr;
633         }
634         return &runs[fRunIndex].fGlyphs[fGlyphIndex];
635     }
636 
637     const SkTArray<ShapedRun>* fRuns;
638     int fRunIndex;
639     size_t fGlyphIndex;
640 };
641 
642 class ShaperHarfBuzz : public SkShaper {
643 public:
644     ShaperHarfBuzz(std::unique_ptr<SkUnicode>,
645                    SkUnicodeBreak line,
646                    SkUnicodeBreak grapheme,
647                    HBBuffer,
648                    sk_sp<SkFontMgr>);
649 
650 protected:
651     std::unique_ptr<SkUnicode> fUnicode;
652     SkUnicodeBreak fLineBreakIterator;
653     SkUnicodeBreak fGraphemeBreakIterator;
654 
655     ShapedRun shape(const char* utf8, size_t utf8Bytes,
656                     const char* utf8Start,
657                     const char* utf8End,
658                     const BiDiRunIterator&,
659                     const LanguageRunIterator&,
660                     const ScriptRunIterator&,
661                     const FontRunIterator&,
662                     const Feature*, size_t featuresSize) const;
663 private:
664     const sk_sp<SkFontMgr> fFontMgr;
665     HBBuffer               fBuffer;
666     hb_language_t          fUndefinedLanguage;
667 
668     void shape(const char* utf8, size_t utf8Bytes,
669                const SkFont&,
670                bool leftToRight,
671                SkScalar width,
672                RunHandler*) const override;
673 
674     void shape(const char* utf8Text, size_t textBytes,
675                FontRunIterator&,
676                BiDiRunIterator&,
677                ScriptRunIterator&,
678                LanguageRunIterator&,
679                SkScalar width,
680                RunHandler*) const override;
681 
682     void shape(const char* utf8Text, size_t textBytes,
683                FontRunIterator&,
684                BiDiRunIterator&,
685                ScriptRunIterator&,
686                LanguageRunIterator&,
687                const Feature*, size_t featuresSize,
688                SkScalar width,
689                RunHandler*) const override;
690 
691     virtual void wrap(char const * const utf8, size_t utf8Bytes,
692                       const BiDiRunIterator&,
693                       const LanguageRunIterator&,
694                       const ScriptRunIterator&,
695                       const FontRunIterator&,
696                       RunIteratorQueue& runSegmenter,
697                       const Feature*, size_t featuresSize,
698                       SkScalar width,
699                       RunHandler*) const = 0;
700 };
701 
702 class ShaperDrivenWrapper : public ShaperHarfBuzz {
703 public:
704     using ShaperHarfBuzz::ShaperHarfBuzz;
705 private:
706     void wrap(char const * const utf8, size_t utf8Bytes,
707               const BiDiRunIterator&,
708               const LanguageRunIterator&,
709               const ScriptRunIterator&,
710               const FontRunIterator&,
711               RunIteratorQueue& runSegmenter,
712               const Feature*, size_t featuresSize,
713               SkScalar width,
714               RunHandler*) const override;
715 };
716 
717 class ShapeThenWrap : public ShaperHarfBuzz {
718 public:
719     using ShaperHarfBuzz::ShaperHarfBuzz;
720 private:
721     void wrap(char const * const utf8, size_t utf8Bytes,
722               const BiDiRunIterator&,
723               const LanguageRunIterator&,
724               const ScriptRunIterator&,
725               const FontRunIterator&,
726               RunIteratorQueue& runSegmenter,
727               const Feature*, size_t featuresSize,
728               SkScalar width,
729               RunHandler*) const override;
730 };
731 
732 class ShapeDontWrapOrReorder : public ShaperHarfBuzz {
733 public:
734     using ShaperHarfBuzz::ShaperHarfBuzz;
735 private:
736     void wrap(char const * const utf8, size_t utf8Bytes,
737               const BiDiRunIterator&,
738               const LanguageRunIterator&,
739               const ScriptRunIterator&,
740               const FontRunIterator&,
741               RunIteratorQueue& runSegmenter,
742               const Feature*, size_t featuresSize,
743               SkScalar width,
744               RunHandler*) const override;
745 };
746 
MakeHarfBuzz(sk_sp<SkFontMgr> fontmgr,bool correct)747 static std::unique_ptr<SkShaper> MakeHarfBuzz(sk_sp<SkFontMgr> fontmgr, bool correct) {
748     HBBuffer buffer(hb_buffer_create());
749     if (!buffer) {
750         SkDEBUGF("Could not create hb_buffer");
751         return nullptr;
752     }
753 
754     auto unicode = SkUnicode::Make();
755     if (!unicode) {
756         return nullptr;
757     }
758     auto lineIter = unicode->makeBreakIterator("th", SkUnicode::BreakType::kLines);
759     if (!lineIter) {
760         return nullptr;
761     }
762     auto graphIter = unicode->makeBreakIterator("th", SkUnicode::BreakType::kGraphemes);
763     if (!graphIter) {
764         return nullptr;
765     }
766 
767     if (correct) {
768         return std::make_unique<ShaperDrivenWrapper>(std::move(unicode),
769             std::move(lineIter), std::move(graphIter), std::move(buffer), std::move(fontmgr));
770     } else {
771         return std::make_unique<ShapeThenWrap>(std::move(unicode),
772             std::move(lineIter), std::move(graphIter), std::move(buffer), std::move(fontmgr));
773     }
774 }
775 
ShaperHarfBuzz(std::unique_ptr<SkUnicode> unicode,SkUnicodeBreak lineIter,SkUnicodeBreak graphIter,HBBuffer buffer,sk_sp<SkFontMgr> fontmgr)776 ShaperHarfBuzz::ShaperHarfBuzz(std::unique_ptr<SkUnicode> unicode,
777     SkUnicodeBreak lineIter, SkUnicodeBreak graphIter, HBBuffer buffer, sk_sp<SkFontMgr> fontmgr)
778     : fUnicode(std::move(unicode))
779     , fLineBreakIterator(std::move(lineIter))
780     , fGraphemeBreakIterator(std::move(graphIter))
781     , fFontMgr(std::move(fontmgr))
782     , fBuffer(std::move(buffer))
783     , fUndefinedLanguage(hb_language_from_string("und", -1))
784 { }
785 
shape(const char * utf8,size_t utf8Bytes,const SkFont & srcFont,bool leftToRight,SkScalar width,RunHandler * handler) const786 void ShaperHarfBuzz::shape(const char* utf8, size_t utf8Bytes,
787                            const SkFont& srcFont,
788                            bool leftToRight,
789                            SkScalar width,
790                            RunHandler* handler) const
791 {
792     SkBidiIterator::Level defaultLevel = leftToRight ? SkBidiIterator::kLTR : SkBidiIterator::kRTL;
793     std::unique_ptr<BiDiRunIterator> bidi(MakeSkUnicodeBidiRunIterator(fUnicode.get(),
794                                                                        utf8,
795                                                                        utf8Bytes,
796                                                                        defaultLevel));
797 
798     if (!bidi) {
799         return;
800     }
801 
802     std::unique_ptr<LanguageRunIterator> language(MakeStdLanguageRunIterator(utf8, utf8Bytes));
803     if (!language) {
804         return;
805     }
806 
807     std::unique_ptr<ScriptRunIterator> script(MakeSkUnicodeHbScriptRunIterator(fUnicode.get(),
808                                                                                        utf8,
809                                                                                        utf8Bytes));
810     if (!script) {
811         return;
812     }
813 
814     std::unique_ptr<FontRunIterator> font(
815                 MakeFontMgrRunIterator(utf8, utf8Bytes, srcFont,
816                                        fFontMgr ? fFontMgr : SkFontMgr::RefDefault()));
817     if (!font) {
818         return;
819     }
820 
821     this->shape(utf8, utf8Bytes, *font, *bidi, *script, *language, width, handler);
822 }
823 
shape(const char * utf8,size_t utf8Bytes,FontRunIterator & font,BiDiRunIterator & bidi,ScriptRunIterator & script,LanguageRunIterator & language,SkScalar width,RunHandler * handler) const824 void ShaperHarfBuzz::shape(const char* utf8, size_t utf8Bytes,
825                            FontRunIterator& font,
826                            BiDiRunIterator& bidi,
827                            ScriptRunIterator& script,
828                            LanguageRunIterator& language,
829                            SkScalar width,
830                            RunHandler* handler) const
831 {
832     this->shape(utf8, utf8Bytes, font, bidi, script, language, nullptr, 0, width, handler);
833 }
834 
shape(const char * utf8,size_t utf8Bytes,FontRunIterator & font,BiDiRunIterator & bidi,ScriptRunIterator & script,LanguageRunIterator & language,const Feature * features,size_t featuresSize,SkScalar width,RunHandler * handler) const835 void ShaperHarfBuzz::shape(const char* utf8, size_t utf8Bytes,
836                            FontRunIterator& font,
837                            BiDiRunIterator& bidi,
838                            ScriptRunIterator& script,
839                            LanguageRunIterator& language,
840                            const Feature* features, size_t featuresSize,
841                            SkScalar width,
842                            RunHandler* handler) const
843 {
844     SkASSERT(handler);
845     RunIteratorQueue runSegmenter;
846     runSegmenter.insert(&font,     3); // The font iterator is always run last in case of tie.
847     runSegmenter.insert(&bidi,     2);
848     runSegmenter.insert(&script,   1);
849     runSegmenter.insert(&language, 0);
850 
851     this->wrap(utf8, utf8Bytes, bidi, language, script, font, runSegmenter,
852                features, featuresSize, width, handler);
853 }
854 
wrap(char const * const utf8,size_t utf8Bytes,const BiDiRunIterator & bidi,const LanguageRunIterator & language,const ScriptRunIterator & script,const FontRunIterator & font,RunIteratorQueue & runSegmenter,const Feature * features,size_t featuresSize,SkScalar width,RunHandler * handler) const855 void ShaperDrivenWrapper::wrap(char const * const utf8, size_t utf8Bytes,
856                                const BiDiRunIterator& bidi,
857                                const LanguageRunIterator& language,
858                                const ScriptRunIterator& script,
859                                const FontRunIterator& font,
860                                RunIteratorQueue& runSegmenter,
861                                const Feature* features, size_t featuresSize,
862                                SkScalar width,
863                                RunHandler* handler) const
864 {
865     ShapedLine line;
866 
867     const char* utf8Start = nullptr;
868     const char* utf8End = utf8;
869     while (runSegmenter.advanceRuns()) {  // For each item
870         utf8Start = utf8End;
871         utf8End = utf8 + runSegmenter.endOfCurrentRun();
872 
873         ShapedRun model(RunHandler::Range(), SkFont(), 0, nullptr, 0);
874         bool modelNeedsRegenerated = true;
875         int modelGlyphOffset = 0;
876 
877         struct TextProps {
878             int glyphLen = 0;
879             SkVector advance = {0, 0};
880         };
881         // map from character position to [safe to break, glyph position, advance]
882         std::unique_ptr<TextProps[]> modelText;
883         int modelTextOffset = 0;
884         SkVector modelAdvanceOffset = {0, 0};
885 
886         while (utf8Start < utf8End) {  // While there are still code points left in this item
887             size_t utf8runLength = utf8End - utf8Start;
888             if (modelNeedsRegenerated) {
889                 model = shape(utf8, utf8Bytes,
890                               utf8Start, utf8End,
891                               bidi, language, script, font,
892                               features, featuresSize);
893                 modelGlyphOffset = 0;
894 
895                 SkVector advance = {0, 0};
896                 modelText = std::make_unique<TextProps[]>(utf8runLength + 1);
897                 size_t modelStartCluster = utf8Start - utf8;
898                 for (size_t i = 0; i < model.fNumGlyphs; ++i) {
899                     SkASSERT(modelStartCluster <= model.fGlyphs[i].fCluster);
900                     SkASSERT(                     model.fGlyphs[i].fCluster < (size_t)(utf8End - utf8));
901                     if (!model.fGlyphs[i].fUnsafeToBreak) {
902                         modelText[model.fGlyphs[i].fCluster - modelStartCluster].glyphLen = i;
903                         modelText[model.fGlyphs[i].fCluster - modelStartCluster].advance = advance;
904                     }
905                     advance += model.fGlyphs[i].fAdvance;
906                 }
907                 // Assume it is always safe to break after the end of an item
908                 modelText[utf8runLength].glyphLen = model.fNumGlyphs;
909                 modelText[utf8runLength].advance = model.fAdvance;
910                 modelTextOffset = 0;
911                 modelAdvanceOffset = {0, 0};
912                 modelNeedsRegenerated = false;
913             }
914 
915             // TODO: break iterator per item, but just reset position if needed?
916             // Maybe break iterator with model?
917             if (!fLineBreakIterator->setText(utf8Start, utf8runLength)) {
918                 return;
919             }
920             SkBreakIterator& breakIterator = *fLineBreakIterator;
921 
922             ShapedRun best(RunHandler::Range(), SkFont(), 0, nullptr, 0,
923                            { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity });
924             bool bestIsInvalid = true;
925             bool bestUsesModelForGlyphs = false;
926             SkScalar widthLeft = width - line.fAdvance.fX;
927 
928             for (int32_t breakIteratorCurrent = breakIterator.next();
929                  !breakIterator.isDone();
930                  breakIteratorCurrent = breakIterator.next())
931             {
932                 // TODO: if past a safe to break, future safe to break will be at least as long
933 
934                 // TODO: adjust breakIteratorCurrent by ignorable whitespace
935                 bool candidateUsesModelForGlyphs = false;
936                 ShapedRun candidate = [&](const TextProps& props){
937                     if (props.glyphLen) {
938                         candidateUsesModelForGlyphs = true;
939                         return ShapedRun(RunHandler::Range(utf8Start - utf8, breakIteratorCurrent),
940                                          font.currentFont(), bidi.currentLevel(),
941                                          std::unique_ptr<ShapedGlyph[]>(),
942                                          props.glyphLen - modelGlyphOffset,
943                                          props.advance - modelAdvanceOffset);
944                     } else {
945                         return shape(utf8, utf8Bytes,
946                                      utf8Start, utf8Start + breakIteratorCurrent,
947                                      bidi, language, script, font,
948                                      features, featuresSize);
949                     }
950                 }(modelText[breakIteratorCurrent + modelTextOffset]);
951                 auto score = [widthLeft](const ShapedRun& run) -> SkScalar {
952                     if (run.fAdvance.fX < widthLeft) {
953                         return run.fUtf8Range.size();
954                     } else {
955                         return widthLeft - run.fAdvance.fX;
956                     }
957                 };
958                 if (bestIsInvalid || score(best) < score(candidate)) {
959                     best = std::move(candidate);
960                     bestIsInvalid = false;
961                     bestUsesModelForGlyphs = candidateUsesModelForGlyphs;
962                 }
963             }
964 
965             // If nothing fit (best score is negative) and the line is not empty
966             if (width < line.fAdvance.fX + best.fAdvance.fX && !line.runs.empty()) {
967                 emit(line, handler);
968                 line.runs.reset();
969                 line.fAdvance = {0, 0};
970             } else {
971                 if (bestUsesModelForGlyphs) {
972                     best.fGlyphs = std::make_unique<ShapedGlyph[]>(best.fNumGlyphs);
973                     memcpy(best.fGlyphs.get(), model.fGlyphs.get() + modelGlyphOffset,
974                            best.fNumGlyphs * sizeof(ShapedGlyph));
975                     modelGlyphOffset += best.fNumGlyphs;
976                     modelTextOffset += best.fUtf8Range.size();
977                     modelAdvanceOffset += best.fAdvance;
978                 } else {
979                     modelNeedsRegenerated = true;
980                 }
981                 utf8Start += best.fUtf8Range.size();
982                 line.fAdvance += best.fAdvance;
983                 line.runs.emplace_back(std::move(best));
984 
985                 // If item broken, emit line (prevent remainder from accidentally fitting)
986                 if (utf8Start != utf8End) {
987                     emit(line, handler);
988                     line.runs.reset();
989                     line.fAdvance = {0, 0};
990                 }
991             }
992         }
993     }
994     emit(line, handler);
995 }
996 
wrap(char const * const utf8,size_t utf8Bytes,const BiDiRunIterator & bidi,const LanguageRunIterator & language,const ScriptRunIterator & script,const FontRunIterator & font,RunIteratorQueue & runSegmenter,const Feature * features,size_t featuresSize,SkScalar width,RunHandler * handler) const997 void ShapeThenWrap::wrap(char const * const utf8, size_t utf8Bytes,
998                          const BiDiRunIterator& bidi,
999                          const LanguageRunIterator& language,
1000                          const ScriptRunIterator& script,
1001                          const FontRunIterator& font,
1002                          RunIteratorQueue& runSegmenter,
1003                          const Feature* features, size_t featuresSize,
1004                          SkScalar width,
1005                          RunHandler* handler) const
1006 {
1007     SkTArray<ShapedRun> runs;
1008 {
1009     if (!fLineBreakIterator->setText(utf8, utf8Bytes)) {
1010         return;
1011     }
1012     if (!fGraphemeBreakIterator->setText(utf8, utf8Bytes)) {
1013         return;
1014     }
1015 
1016     SkBreakIterator& lineBreakIterator = *fLineBreakIterator;
1017     SkBreakIterator& graphemeBreakIterator = *fGraphemeBreakIterator;
1018     const char* utf8Start = nullptr;
1019     const char* utf8End = utf8;
1020     while (runSegmenter.advanceRuns()) {
1021         utf8Start = utf8End;
1022         utf8End = utf8 + runSegmenter.endOfCurrentRun();
1023 
1024         runs.emplace_back(shape(utf8, utf8Bytes,
1025                                 utf8Start, utf8End,
1026                                 bidi, language, script, font,
1027                                 features, featuresSize));
1028         ShapedRun& run = runs.back();
1029 
1030         uint32_t previousCluster = 0xFFFFFFFF;
1031         for (size_t i = 0; i < run.fNumGlyphs; ++i) {
1032             ShapedGlyph& glyph = run.fGlyphs[i];
1033             int32_t glyphCluster = glyph.fCluster;
1034 
1035             int32_t lineBreakIteratorCurrent = lineBreakIterator.current();
1036             while (!lineBreakIterator.isDone() && lineBreakIteratorCurrent < glyphCluster)
1037             {
1038                 lineBreakIteratorCurrent = lineBreakIterator.next();
1039             }
1040             glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
1041                                         lineBreakIteratorCurrent == glyphCluster;
1042 
1043             int32_t graphemeBreakIteratorCurrent = graphemeBreakIterator.current();
1044             while (!graphemeBreakIterator.isDone() && graphemeBreakIteratorCurrent < glyphCluster)
1045             {
1046                 graphemeBreakIteratorCurrent = graphemeBreakIterator.next();
1047             }
1048             glyph.fGraphemeBreakBefore = glyph.fCluster != previousCluster &&
1049                                          graphemeBreakIteratorCurrent == glyphCluster;
1050 
1051             previousCluster = glyph.fCluster;
1052         }
1053     }
1054 }
1055 
1056 // Iterate over the glyphs in logical order to find potential line lengths.
1057 {
1058     /** The position of the beginning of the line. */
1059     ShapedRunGlyphIterator beginning(runs);
1060 
1061     /** The position of the candidate line break. */
1062     ShapedRunGlyphIterator candidateLineBreak(runs);
1063     SkScalar candidateLineBreakWidth = 0;
1064 
1065     /** The position of the candidate grapheme break. */
1066     ShapedRunGlyphIterator candidateGraphemeBreak(runs);
1067     SkScalar candidateGraphemeBreakWidth = 0;
1068 
1069     /** The position of the current location. */
1070     ShapedRunGlyphIterator current(runs);
1071     SkScalar currentWidth = 0;
1072     while (ShapedGlyph* glyph = current.current()) {
1073         // 'Break' at graphemes until a line boundary, then only at line boundaries.
1074         // Only break at graphemes if no line boundary is valid.
1075         if (current != beginning) {
1076             if (glyph->fGraphemeBreakBefore || glyph->fMayLineBreakBefore) {
1077                 // TODO: preserve line breaks <= grapheme breaks
1078                 // and prevent line breaks inside graphemes
1079                 candidateGraphemeBreak = current;
1080                 candidateGraphemeBreakWidth = currentWidth;
1081                 if (glyph->fMayLineBreakBefore) {
1082                     candidateLineBreak = current;
1083                     candidateLineBreakWidth = currentWidth;
1084                 }
1085             }
1086         }
1087 
1088         SkScalar glyphWidth = glyph->fAdvance.fX;
1089         // Break when overwidth, the glyph has a visual representation, and some space is used.
1090         if (width < currentWidth + glyphWidth && glyph->fHasVisual && candidateGraphemeBreakWidth > 0){
1091             if (candidateLineBreak != beginning) {
1092                 beginning = candidateLineBreak;
1093                 currentWidth -= candidateLineBreakWidth;
1094                 candidateGraphemeBreakWidth -= candidateLineBreakWidth;
1095                 candidateLineBreakWidth = 0;
1096             } else if (candidateGraphemeBreak != beginning) {
1097                 beginning = candidateGraphemeBreak;
1098                 candidateLineBreak = beginning;
1099                 currentWidth -= candidateGraphemeBreakWidth;
1100                 candidateGraphemeBreakWidth = 0;
1101                 candidateLineBreakWidth = 0;
1102             } else {
1103                 SK_ABORT("");
1104             }
1105 
1106             if (width < currentWidth) {
1107                 if (width < candidateGraphemeBreakWidth) {
1108                     candidateGraphemeBreak = candidateLineBreak;
1109                     candidateGraphemeBreakWidth = candidateLineBreakWidth;
1110                 }
1111                 current = candidateGraphemeBreak;
1112                 currentWidth = candidateGraphemeBreakWidth;
1113             }
1114 
1115             glyph = beginning.current();
1116             if (glyph) {
1117                 glyph->fMustLineBreakBefore = true;
1118             }
1119 
1120         } else {
1121             current.next();
1122             currentWidth += glyphWidth;
1123         }
1124     }
1125 }
1126 
1127 // Reorder the runs and glyphs per line and write them out.
1128 {
1129     ShapedRunGlyphIterator previousBreak(runs);
1130     ShapedRunGlyphIterator glyphIterator(runs);
1131     int previousRunIndex = -1;
1132     while (glyphIterator.current()) {
1133         const ShapedRunGlyphIterator current = glyphIterator;
1134         ShapedGlyph* nextGlyph = glyphIterator.next();
1135 
1136         if (previousRunIndex != current.fRunIndex) {
1137             SkFontMetrics metrics;
1138             runs[current.fRunIndex].fFont.getMetrics(&metrics);
1139             previousRunIndex = current.fRunIndex;
1140         }
1141 
1142         // Nothing can be written until the baseline is known.
1143         if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
1144             continue;
1145         }
1146 
1147         int numRuns = current.fRunIndex - previousBreak.fRunIndex + 1;
1148         SkAutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
1149         for (int i = 0; i < numRuns; ++i) {
1150             runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
1151         }
1152         SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
1153         SkBidiIterator::ReorderVisual(runLevels, numRuns, logicalFromVisual);
1154 
1155         // step through the runs in reverse visual order and the glyphs in reverse logical order
1156         // until a visible glyph is found and force them to the end of the visual line.
1157 
1158         handler->beginLine();
1159 
1160         struct SubRun { const ShapedRun& run; size_t startGlyphIndex; size_t endGlyphIndex; };
1161         auto makeSubRun = [&runs, &previousBreak, &current, &logicalFromVisual](size_t visualIndex){
1162             int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[visualIndex];
1163             const auto& run = runs[logicalIndex];
1164             size_t startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
1165                                    ? previousBreak.fGlyphIndex
1166                                    : 0;
1167             size_t endGlyphIndex = (logicalIndex == current.fRunIndex)
1168                                  ? current.fGlyphIndex + 1
1169                                  : run.fNumGlyphs;
1170             return SubRun{ run, startGlyphIndex, endGlyphIndex };
1171         };
1172         auto makeRunInfo = [](const SubRun& sub) {
1173             uint32_t startUtf8 = sub.run.fGlyphs[sub.startGlyphIndex].fCluster;
1174             uint32_t endUtf8 = (sub.endGlyphIndex < sub.run.fNumGlyphs)
1175                              ? sub.run.fGlyphs[sub.endGlyphIndex].fCluster
1176                              : sub.run.fUtf8Range.end();
1177 
1178             SkVector advance = SkVector::Make(0, 0);
1179             for (size_t i = sub.startGlyphIndex; i < sub.endGlyphIndex; ++i) {
1180                 advance += sub.run.fGlyphs[i].fAdvance;
1181             }
1182 
1183             return RunHandler::RunInfo{
1184                 sub.run.fFont,
1185                 sub.run.fLevel,
1186                 advance,
1187                 sub.endGlyphIndex - sub.startGlyphIndex,
1188                 RunHandler::Range(startUtf8, endUtf8 - startUtf8)
1189             };
1190         };
1191 
1192         for (int i = 0; i < numRuns; ++i) {
1193             handler->runInfo(makeRunInfo(makeSubRun(i)));
1194         }
1195         handler->commitRunInfo();
1196         for (int i = 0; i < numRuns; ++i) {
1197             SubRun sub = makeSubRun(i);
1198             append(handler, makeRunInfo(sub), sub.run, sub.startGlyphIndex, sub.endGlyphIndex);
1199         }
1200 
1201         handler->commitLine();
1202 
1203         previousRunIndex = -1;
1204         previousBreak = glyphIterator;
1205     }
1206 }
1207 }
1208 
wrap(char const * const utf8,size_t utf8Bytes,const BiDiRunIterator & bidi,const LanguageRunIterator & language,const ScriptRunIterator & script,const FontRunIterator & font,RunIteratorQueue & runSegmenter,const Feature * features,size_t featuresSize,SkScalar width,RunHandler * handler) const1209 void ShapeDontWrapOrReorder::wrap(char const * const utf8, size_t utf8Bytes,
1210                                   const BiDiRunIterator& bidi,
1211                                   const LanguageRunIterator& language,
1212                                   const ScriptRunIterator& script,
1213                                   const FontRunIterator& font,
1214                                   RunIteratorQueue& runSegmenter,
1215                                   const Feature* features, size_t featuresSize,
1216                                   SkScalar width,
1217                                   RunHandler* handler) const
1218 {
1219     sk_ignore_unused_variable(width);
1220     SkTArray<ShapedRun> runs;
1221 
1222     const char* utf8Start = nullptr;
1223     const char* utf8End = utf8;
1224     while (runSegmenter.advanceRuns()) {
1225         utf8Start = utf8End;
1226         utf8End = utf8 + runSegmenter.endOfCurrentRun();
1227 
1228         runs.emplace_back(shape(utf8, utf8Bytes,
1229                                 utf8Start, utf8End,
1230                                 bidi, language, script, font,
1231                                 features, featuresSize));
1232     }
1233 
1234     handler->beginLine();
1235     for (const auto& run : runs) {
1236         const RunHandler::RunInfo info = {
1237             run.fFont,
1238             run.fLevel,
1239             run.fAdvance,
1240             run.fNumGlyphs,
1241             run.fUtf8Range
1242         };
1243         handler->runInfo(info);
1244     }
1245     handler->commitRunInfo();
1246     for (const auto& run : runs) {
1247         const RunHandler::RunInfo info = {
1248             run.fFont,
1249             run.fLevel,
1250             run.fAdvance,
1251             run.fNumGlyphs,
1252             run.fUtf8Range
1253         };
1254         append(handler, info, run, 0, run.fNumGlyphs);
1255     }
1256     handler->commitLine();
1257 }
1258 
1259 class HBLockedFaceCache {
1260 public:
HBLockedFaceCache(SkLRUCache<SkFontID,HBFace> & lruCache,SkMutex & mutex)1261     HBLockedFaceCache(SkLRUCache<SkFontID, HBFace>& lruCache, SkMutex& mutex)
1262         : fLRUCache(lruCache), fMutex(mutex)
1263     {
1264         fMutex.acquire();
1265     }
1266     HBLockedFaceCache(const HBLockedFaceCache&) = delete;
1267     HBLockedFaceCache& operator=(const HBLockedFaceCache&) = delete;
1268     HBLockedFaceCache(HBLockedFaceCache&&) = delete;
1269     HBLockedFaceCache& operator=(HBLockedFaceCache&&) = delete;
1270 
~HBLockedFaceCache()1271     ~HBLockedFaceCache() {
1272         fMutex.release();
1273     }
1274 
find(SkFontID fontId)1275     HBFace* find(SkFontID fontId) {
1276         return fLRUCache.find(fontId);
1277     }
insert(SkFontID fontId,HBFace hbFace)1278     HBFace* insert(SkFontID fontId, HBFace hbFace) {
1279         return fLRUCache.insert(fontId, std::move(hbFace));
1280     }
reset()1281     void reset() {
1282         fLRUCache.reset();
1283     }
1284 private:
1285     SkLRUCache<SkFontID, HBFace>& fLRUCache;
1286     SkMutex& fMutex;
1287 };
get_hbFace_cache()1288 static HBLockedFaceCache get_hbFace_cache() {
1289     static SkMutex gHBFaceCacheMutex;
1290     static SkLRUCache<SkFontID, HBFace> gHBFaceCache(100);
1291     return HBLockedFaceCache(gHBFaceCache, gHBFaceCacheMutex);
1292 }
1293 
shape(char const * const utf8,size_t const utf8Bytes,char const * const utf8Start,char const * const utf8End,const BiDiRunIterator & bidi,const LanguageRunIterator & language,const ScriptRunIterator & script,const FontRunIterator & font,Feature const * const features,size_t const featuresSize) const1294 ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
1295                                   size_t const utf8Bytes,
1296                                   char const * const utf8Start,
1297                                   char const * const utf8End,
1298                                   const BiDiRunIterator& bidi,
1299                                   const LanguageRunIterator& language,
1300                                   const ScriptRunIterator& script,
1301                                   const FontRunIterator& font,
1302                                   Feature const * const features, size_t const featuresSize) const
1303 {
1304     size_t utf8runLength = utf8End - utf8Start;
1305     ShapedRun run(RunHandler::Range(utf8Start - utf8, utf8runLength),
1306                   font.currentFont(), bidi.currentLevel(), nullptr, 0);
1307 
1308     hb_buffer_t* buffer = fBuffer.get();
1309     SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
1310     hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1311     hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
1312 
1313     // Documentation for HB_BUFFER_FLAG_BOT/EOT at 763e5466c0a03a7c27020e1e2598e488612529a7.
1314     // Currently BOT forces a dotted circle when first codepoint is a mark; EOT has no effect.
1315     // Avoid adding dotted circle, re-evaluate if BOT/EOT change. See https://skbug.com/9618.
1316     // hb_buffer_set_flags(buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
1317 
1318     // Add precontext.
1319     hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
1320 
1321     // Populate the hb_buffer directly with utf8 cluster indexes.
1322     const char* utf8Current = utf8Start;
1323     while (utf8Current < utf8End) {
1324         unsigned int cluster = utf8Current - utf8;
1325         hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
1326         hb_buffer_add(buffer, u, cluster);
1327     }
1328 
1329     // Add postcontext.
1330     hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
1331 
1332     hb_direction_t direction = is_LTR(bidi.currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
1333     hb_buffer_set_direction(buffer, direction);
1334     hb_buffer_set_script(buffer, hb_script_from_iso15924_tag((hb_tag_t)script.currentScript()));
1335     // Buffers with HB_LANGUAGE_INVALID race since hb_language_get_default is not thread safe.
1336     // The user must provide a language, but may provide data hb_language_from_string cannot use.
1337     // Use "und" for the undefined language in this case (RFC5646 4.1 5).
1338     hb_language_t hbLanguage = hb_language_from_string(language.currentLanguage(), -1);
1339     if (hbLanguage == HB_LANGUAGE_INVALID) {
1340         hbLanguage = fUndefinedLanguage;
1341     }
1342     hb_buffer_set_language(buffer, hbLanguage);
1343     hb_buffer_guess_segment_properties(buffer);
1344 
1345     // TODO: better cache HBFace (data) / hbfont (typeface)
1346     // An HBFace is expensive (it sanitizes the bits).
1347     // An HBFont is fairly inexpensive.
1348     // An HBFace is actually tied to the data, not the typeface.
1349     // The size of 100 here is completely arbitrary and used to match libtxt.
1350     HBFont hbFont;
1351     {
1352         HBLockedFaceCache cache = get_hbFace_cache();
1353         SkFontID dataId = font.currentFont().getTypeface()->uniqueID();
1354         HBFace* hbFaceCached = cache.find(dataId);
1355         if (!hbFaceCached) {
1356             HBFace hbFace(create_hb_face(*font.currentFont().getTypeface()));
1357             hbFaceCached = cache.insert(dataId, std::move(hbFace));
1358         }
1359         hbFont = create_hb_font(font.currentFont(), *hbFaceCached);
1360     }
1361     if (!hbFont) {
1362         return run;
1363     }
1364 
1365     SkSTArray<32, hb_feature_t> hbFeatures;
1366     for (const auto& feature : SkMakeSpan(features, featuresSize)) {
1367         if (feature.end < SkTo<size_t>(utf8Start - utf8) ||
1368                           SkTo<size_t>(utf8End   - utf8)  <= feature.start)
1369         {
1370             continue;
1371         }
1372         if (feature.start <= SkTo<size_t>(utf8Start - utf8) &&
1373                              SkTo<size_t>(utf8End   - utf8) <= feature.end)
1374         {
1375             hbFeatures.push_back({ (hb_tag_t)feature.tag, feature.value,
1376                                    HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END});
1377         } else {
1378             hbFeatures.push_back({ (hb_tag_t)feature.tag, feature.value,
1379                                    SkTo<unsigned>(feature.start), SkTo<unsigned>(feature.end)});
1380         }
1381     }
1382 
1383     hb_shape(hbFont.get(), buffer, hbFeatures.data(), hbFeatures.size());
1384     unsigned len = hb_buffer_get_length(buffer);
1385     if (len == 0) {
1386         return run;
1387     }
1388 
1389     if (direction == HB_DIRECTION_RTL) {
1390         // Put the clusters back in logical order.
1391         // Note that the advances remain ltr.
1392         hb_buffer_reverse(buffer);
1393     }
1394     hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
1395     hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
1396 
1397     run = ShapedRun(RunHandler::Range(utf8Start - utf8, utf8runLength),
1398                     font.currentFont(), bidi.currentLevel(),
1399                     std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]), len);
1400 
1401     // Undo skhb_position with (1.0/(1<<16)) and scale as needed.
1402     double SkScalarFromHBPosX = +(1.52587890625e-5) * run.fFont.getScaleX();
1403     double SkScalarFromHBPosY = -(1.52587890625e-5);  // HarfBuzz y-up, Skia y-down
1404     SkVector runAdvance = { 0, 0 };
1405     for (unsigned i = 0; i < len; i++) {
1406         ShapedGlyph& glyph = run.fGlyphs[i];
1407         glyph.fID = info[i].codepoint;
1408         glyph.fCluster = info[i].cluster;
1409         glyph.fOffset.fX = pos[i].x_offset * SkScalarFromHBPosX;
1410         glyph.fOffset.fY = pos[i].y_offset * SkScalarFromHBPosY;
1411         glyph.fAdvance.fX = pos[i].x_advance * SkScalarFromHBPosX;
1412         glyph.fAdvance.fY = pos[i].y_advance * SkScalarFromHBPosY;
1413 
1414         SkRect bounds;
1415         SkScalar advance;
1416         SkPaint p;
1417         run.fFont.getWidthsBounds(&glyph.fID, 1, &advance, &bounds, &p);
1418         glyph.fHasVisual = !bounds.isEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1419 #if SK_HB_VERSION_CHECK(1, 5, 0)
1420         glyph.fUnsafeToBreak = info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
1421 #else
1422         glyph.fUnsafeToBreak = false;
1423 #endif
1424         glyph.fMustLineBreakBefore = false;
1425 
1426         runAdvance += glyph.fAdvance;
1427     }
1428     run.fAdvance = runAdvance;
1429 
1430     return run;
1431 }
1432 
1433 }  // namespace
1434 
1435 std::unique_ptr<SkShaper::BiDiRunIterator>
MakeIcuBiDiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)1436 SkShaper::MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
1437     auto unicode = SkUnicode::Make();
1438     if (!unicode) {
1439         return nullptr;
1440     }
1441     return SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
1442                                                   utf8,
1443                                                   utf8Bytes,
1444                                                   bidiLevel);
1445 }
1446 
1447 std::unique_ptr<SkShaper::BiDiRunIterator>
MakeSkUnicodeBidiRunIterator(SkUnicode * unicode,const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)1448 SkShaper::MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
1449     // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
1450     // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
1451     if (!SkTFitsIn<int32_t>(utf8Bytes)) {
1452         SkDEBUGF("Bidi error: text too long");
1453         return nullptr;
1454     }
1455 
1456     int32_t utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Bytes);
1457     if (utf16Units < 0) {
1458         SkDEBUGF("Invalid utf8 input\n");
1459         return nullptr;
1460     }
1461 
1462     std::unique_ptr<uint16_t[]> utf16(new uint16_t[utf16Units]);
1463     (void)SkUTF::UTF8ToUTF16(utf16.get(), utf16Units, utf8, utf8Bytes);
1464 
1465     auto bidiDir = (bidiLevel % 2 == 0) ? SkBidiIterator::kLTR : SkBidiIterator::kRTL;
1466     SkUnicodeBidi bidi = unicode->makeBidiIterator(utf16.get(), utf16Units, bidiDir);
1467     if (!bidi) {
1468         SkDEBUGF("Bidi error\n");
1469         return nullptr;
1470     }
1471 
1472     return std::make_unique<SkUnicodeBidiRunIterator>(utf8, utf8 + utf8Bytes, std::move(bidi));
1473 }
1474 
1475 std::unique_ptr<SkShaper::ScriptRunIterator>
MakeHbIcuScriptRunIterator(const char * utf8,size_t utf8Bytes)1476 SkShaper::MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes) {
1477     auto unicode = SkUnicode::Make();
1478     if (!unicode) {
1479         return nullptr;
1480     }
1481     return SkShaper::MakeSkUnicodeHbScriptRunIterator(unicode.get(), utf8, utf8Bytes);
1482 }
1483 
1484 std::unique_ptr<SkShaper::ScriptRunIterator>
MakeSkUnicodeHbScriptRunIterator(SkUnicode * unicode,const char * utf8,size_t utf8Bytes)1485 SkShaper::MakeSkUnicodeHbScriptRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes) {
1486     auto script = unicode->makeScriptIterator();
1487     if (!script) {
1488         return nullptr;
1489     }
1490     return std::make_unique<SkUnicodeHbScriptRunIterator>(std::move(script), utf8, utf8Bytes);
1491 }
1492 
MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fontmgr)1493 std::unique_ptr<SkShaper> SkShaper::MakeShaperDrivenWrapper(sk_sp<SkFontMgr> fontmgr) {
1494     return MakeHarfBuzz(std::move(fontmgr), true);
1495 }
MakeShapeThenWrap(sk_sp<SkFontMgr> fontmgr)1496 std::unique_ptr<SkShaper> SkShaper::MakeShapeThenWrap(sk_sp<SkFontMgr> fontmgr) {
1497     return MakeHarfBuzz(std::move(fontmgr), false);
1498 }
MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> fontmgr)1499 std::unique_ptr<SkShaper> SkShaper::MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> fontmgr) {
1500     HBBuffer buffer(hb_buffer_create());
1501     if (!buffer) {
1502         SkDEBUGF("Could not create hb_buffer");
1503         return nullptr;
1504     }
1505 
1506     auto unicode = SkUnicode::Make();
1507     if (!unicode) {
1508         return nullptr;
1509     }
1510 
1511     return std::make_unique<ShapeDontWrapOrReorder>
1512         (std::move(unicode), nullptr, nullptr, std::move(buffer), std::move(fontmgr));
1513 }
1514 
PurgeHarfBuzzCache()1515 void SkShaper::PurgeHarfBuzzCache() {
1516     HBLockedFaceCache cache = get_hbFace_cache();
1517     cache.reset();
1518 }
1519