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