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