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