blob: 2077dedadcb52ee4b27acfbb3fe6c7ccaef991fa [file] [log] [blame]
Ben Wagnera25fbef2017-08-30 13:56:19 -04001/*
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>
Ben Wagner8d45a382017-11-16 10:08:28 -05009#include <unicode/brkiter.h>
10#include <unicode/locid.h>
Ben Wagnera25fbef2017-08-30 13:56:19 -040011#include <unicode/stringpiece.h>
12#include <unicode/ubidi.h>
Ben Wagner8d45a382017-11-16 10:08:28 -050013#include <unicode/uchriter.h>
Ben Wagnera25fbef2017-08-30 13:56:19 -040014#include <unicode/unistr.h>
Ben Wagner8d45a382017-11-16 10:08:28 -050015#include <unicode/uscript.h>
Ben Wagnera25fbef2017-08-30 13:56:19 -040016
Ben Wagner67e3a302017-09-05 14:46:19 -040017#include "SkFontMgr.h"
Hal Canary0e07ad72018-02-08 13:06:56 -050018#include "SkLoadICU.h"
19#include "SkOnce.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040020#include "SkShaper.h"
21#include "SkStream.h"
Ben Wagner8d45a382017-11-16 10:08:28 -050022#include "SkTDPQueue.h"
23#include "SkTLazy.h"
Ben Wagnere0001732017-08-31 16:26:26 -040024#include "SkTemplates.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040025#include "SkTextBlob.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040026#include "SkTo.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040027#include "SkTypeface.h"
28#include "SkUtils.h"
29
Ben Wagnera25fbef2017-08-30 13:56:19 -040030namespace {
31template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
32using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
33using HBFace = resource<hb_face_t , hb_face_destroy >;
34using HBFont = resource<hb_font_t , hb_font_destroy >;
35using HBBuffer = resource<hb_buffer_t, hb_buffer_destroy>;
36using ICUBiDi = resource<UBiDi , ubidi_close >;
37
38HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
39 size_t size = asset->getLength();
40 HBBlob blob;
41 if (const void* base = asset->getMemoryBase()) {
42 blob.reset(hb_blob_create((char*)base, SkToUInt(size),
43 HB_MEMORY_MODE_READONLY, asset.release(),
44 [](void* p) { delete (SkStreamAsset*)p; }));
45 } else {
46 // SkDebugf("Extra SkStreamAsset copy\n");
47 void* ptr = size ? sk_malloc_throw(size) : nullptr;
48 asset->read(ptr, size);
49 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
50 HB_MEMORY_MODE_READONLY, ptr, sk_free));
51 }
52 SkASSERT(blob);
53 hb_blob_make_immutable(blob.get());
54 return blob;
55}
Ben Wagnera25fbef2017-08-30 13:56:19 -040056
Ben Wagner8d45a382017-11-16 10:08:28 -050057HBFont create_hb_font(SkTypeface* tf) {
Ben Wagnera25fbef2017-08-30 13:56:19 -040058 int index;
Ben Wagnere0001732017-08-31 16:26:26 -040059 HBBlob blob(stream_to_blob(std::unique_ptr<SkStreamAsset>(tf->openStream(&index))));
Ben Wagnera25fbef2017-08-30 13:56:19 -040060 HBFace face(hb_face_create(blob.get(), (unsigned)index));
61 SkASSERT(face);
62 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040063 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040064 }
65 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -040066 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -040067
Ben Wagnere0001732017-08-31 16:26:26 -040068 HBFont font(hb_font_create(face.get()));
69 SkASSERT(font);
70 if (!font) {
71 return nullptr;
72 }
Ben Wagnere0001732017-08-31 16:26:26 -040073 hb_ot_font_set_funcs(font.get());
74 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
75 if (axis_count > 0) {
76 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
77 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
78 hb_font_set_variations(font.get(),
79 reinterpret_cast<hb_variation_t*>(axis_values.get()),
80 axis_count);
81 }
82 }
83 return font;
84}
85
Ben Wagner8d45a382017-11-16 10:08:28 -050086class RunIterator {
87public:
88 virtual ~RunIterator() {}
89 virtual void consume() = 0;
90 // Pointer one past the last (utf8) element in the current run.
91 virtual const char* endOfCurrentRun() const = 0;
92 virtual bool atEnd() const = 0;
93 bool operator<(const RunIterator& that) const {
94 return this->endOfCurrentRun() < that.endOfCurrentRun();
95 }
96};
97
98class BiDiRunIterator : public RunIterator {
99public:
100 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
101 SkTLazy<BiDiRunIterator> ret;
102
103 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
104 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
105 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
106 SkDebugf("Bidi error: text too long");
107 return ret;
108 }
109 icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, utf8Bytes));
110
111 UErrorCode status = U_ZERO_ERROR;
112 ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
113 if (U_FAILURE(status)) {
114 SkDebugf("Bidi error: %s", u_errorName(status));
115 return ret;
116 }
117 SkASSERT(bidi);
118
119 // The required lifetime of utf16 isn't well documented.
120 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
121 ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), level, nullptr, &status);
122 if (U_FAILURE(status)) {
123 SkDebugf("Bidi error: %s", u_errorName(status));
124 return ret;
125 }
126
Hal Canary4014ba62018-07-24 11:33:21 -0400127 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500128 return ret;
129 }
Hal Canary4014ba62018-07-24 11:33:21 -0400130 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500131 : fBidi(std::move(bidi))
132 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400133 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500134 , fUTF16LogicalPosition(0)
135 , fLevel(UBIDI_DEFAULT_LTR)
136 {}
137 void consume() override {
138 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
139 int32_t endPosition = ubidi_getLength(fBidi.get());
140 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canary4014ba62018-07-24 11:33:21 -0400141 SkUnichar u = SkUTF8_NextUnichar(&fEndOfCurrentRun, fEndOfAllRuns);
Ben Wagner5a907a72018-01-25 16:03:22 -0500142 fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500143 UBiDiLevel level;
144 while (fUTF16LogicalPosition < endPosition) {
145 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
146 if (level != fLevel) {
147 break;
148 }
Hal Canary4014ba62018-07-24 11:33:21 -0400149 u = SkUTF8_NextUnichar(&fEndOfCurrentRun, fEndOfAllRuns);
Ben Wagner5a907a72018-01-25 16:03:22 -0500150 fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500151 }
152 }
153 const char* endOfCurrentRun() const override {
154 return fEndOfCurrentRun;
155 }
156 bool atEnd() const override {
157 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
158 }
159
160 UBiDiLevel currentLevel() const {
161 return fLevel;
162 }
163private:
164 ICUBiDi fBidi;
165 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400166 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500167 int32_t fUTF16LogicalPosition;
168 UBiDiLevel fLevel;
169};
170
171class ScriptRunIterator : public RunIterator {
172public:
173 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
174 hb_unicode_funcs_t* hbUnicode)
175 {
176 SkTLazy<ScriptRunIterator> ret;
177 ret.init(utf8, utf8Bytes, hbUnicode);
178 return ret;
179 }
180 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
181 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
182 , fHBUnicode(hbUnicode)
183 , fCurrentScript(HB_SCRIPT_UNKNOWN)
184 {}
185 void consume() override {
186 SkASSERT(fCurrent < fEnd);
Hal Canary4014ba62018-07-24 11:33:21 -0400187 SkUnichar u = SkUTF8_NextUnichar(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500188 fCurrentScript = hb_unicode_script(fHBUnicode, u);
189 while (fCurrent < fEnd) {
190 const char* prev = fCurrent;
Hal Canary4014ba62018-07-24 11:33:21 -0400191 u = SkUTF8_NextUnichar(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500192 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
193 if (script != fCurrentScript) {
194 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
195 fCurrentScript = script;
196 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
197 continue;
198 } else {
199 fCurrent = prev;
200 break;
201 }
202 }
203 }
204 if (fCurrentScript == HB_SCRIPT_INHERITED) {
205 fCurrentScript = HB_SCRIPT_COMMON;
206 }
207 }
208 const char* endOfCurrentRun() const override {
209 return fCurrent;
210 }
211 bool atEnd() const override {
212 return fCurrent == fEnd;
213 }
214
215 hb_script_t currentScript() const {
216 return fCurrentScript;
217 }
218private:
219 const char* fCurrent;
220 const char* fEnd;
221 hb_unicode_funcs_t* fHBUnicode;
222 hb_script_t fCurrentScript;
223};
224
225class FontRunIterator : public RunIterator {
226public:
227 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
228 sk_sp<SkTypeface> typeface,
229 hb_font_t* hbFace,
230 sk_sp<SkFontMgr> fallbackMgr)
231 {
232 SkTLazy<FontRunIterator> ret;
233 ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
234 return ret;
235 }
236 FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
237 hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
238 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
239 , fFallbackMgr(std::move(fallbackMgr))
240 , fHBFont(hbFace), fTypeface(std::move(typeface))
241 , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
242 , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
243 {}
244 void consume() override {
245 SkASSERT(fCurrent < fEnd);
Hal Canary4014ba62018-07-24 11:33:21 -0400246 SkUnichar u = SkUTF8_NextUnichar(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500247 // If the starting typeface can handle this character, use it.
248 if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
249 fFallbackTypeface.reset();
250 // If not, try to find a fallback typeface
251 } else {
252 fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
253 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
254 }
255
256 if (fFallbackTypeface) {
257 fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
258 fCurrentTypeface = fFallbackTypeface.get();
259 fCurrentHBFont = fFallbackHBFont.get();
260 } else {
261 fFallbackHBFont.reset();
262 fCurrentTypeface = fTypeface.get();
263 fCurrentHBFont = fHBFont;
264 }
265
266 while (fCurrent < fEnd) {
267 const char* prev = fCurrent;
Hal Canary4014ba62018-07-24 11:33:21 -0400268 u = SkUTF8_NextUnichar(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500269
270 // If using a fallback and the initial typeface has this character, stop fallback.
271 if (fFallbackTypeface &&
272 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
273 {
274 fCurrent = prev;
275 return;
276 }
277 // If the current typeface cannot handle this character, stop using it.
278 if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
279 fCurrent = prev;
280 return;
281 }
282 }
283 }
284 const char* endOfCurrentRun() const override {
285 return fCurrent;
286 }
287 bool atEnd() const override {
288 return fCurrent == fEnd;
289 }
290
291 SkTypeface* currentTypeface() const {
292 return fCurrentTypeface;
293 }
294 hb_font_t* currentHBFont() const {
295 return fCurrentHBFont;
296 }
297private:
298 const char* fCurrent;
299 const char* fEnd;
300 sk_sp<SkFontMgr> fFallbackMgr;
301 hb_font_t* fHBFont;
302 sk_sp<SkTypeface> fTypeface;
303 HBFont fFallbackHBFont;
304 sk_sp<SkTypeface> fFallbackTypeface;
305 hb_font_t* fCurrentHBFont;
306 SkTypeface* fCurrentTypeface;
307};
308
309class RunIteratorQueue {
310public:
311 void insert(RunIterator* runIterator) {
312 fRunIterators.insert(runIterator);
313 }
314
315 bool advanceRuns() {
316 const RunIterator* leastRun = fRunIterators.peek();
317 if (leastRun->atEnd()) {
318 SkASSERT(this->allRunsAreAtEnd());
319 return false;
320 }
321 const char* leastEnd = leastRun->endOfCurrentRun();
322 RunIterator* currentRun = nullptr;
323 SkDEBUGCODE(const char* previousEndOfCurrentRun);
324 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
325 fRunIterators.pop();
326 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
327 currentRun->consume();
328 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
329 fRunIterators.insert(currentRun);
330 }
331 return true;
332 }
333
334 const char* endOfCurrentRun() const {
335 return fRunIterators.peek()->endOfCurrentRun();
336 }
337
338private:
339 bool allRunsAreAtEnd() const {
340 for (int i = 0; i < fRunIterators.count(); ++i) {
341 if (!fRunIterators.at(i)->atEnd()) {
342 return false;
343 }
344 }
345 return true;
346 }
347
348 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
349 return *a < *b;
350 }
351 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
352};
353
354struct ShapedGlyph {
355 SkGlyphID fID;
356 uint32_t fCluster;
357 SkPoint fOffset;
358 SkVector fAdvance;
359 bool fMayLineBreakBefore;
360 bool fMustLineBreakBefore;
361 bool fHasVisual;
362};
363struct ShapedRun {
364 ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkPaint& paint,
365 UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
366 : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fPaint(paint)
367 , fLevel(level), fGlyphs(std::move(glyphs))
368 {}
369
370 const char* fUtf8Start;
371 const char* fUtf8End;
372 int fNumGlyphs;
373 SkPaint fPaint;
374 UBiDiLevel fLevel;
375 std::unique_ptr<ShapedGlyph[]> fGlyphs;
376};
377
378static constexpr bool is_LTR(UBiDiLevel level) {
379 return (level & 1) == 0;
380}
381
382static void append(SkTextBlobBuilder* b, const ShapedRun& run, int start, int end, SkPoint* p) {
383 unsigned len = end - start;
384 auto runBuffer = b->allocRunTextPos(run.fPaint, len, run.fUtf8End - run.fUtf8Start, SkString());
385 memcpy(runBuffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
386
387 for (unsigned i = 0; i < len; i++) {
388 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
389 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
390 runBuffer.glyphs[i] = glyph.fID;
391 runBuffer.clusters[i] = glyph.fCluster;
392 reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
393 SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
394 p->fX += glyph.fAdvance.fX;
395 p->fY += glyph.fAdvance.fY;
396 }
397}
398
399struct ShapedRunGlyphIterator {
400 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
401 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
402 { }
403
404 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
405 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
406 bool operator==(const ShapedRunGlyphIterator& that) const {
407 return fRuns == that.fRuns &&
408 fRunIndex == that.fRunIndex &&
409 fGlyphIndex == that.fGlyphIndex;
410 }
411 bool operator!=(const ShapedRunGlyphIterator& that) const {
412 return fRuns != that.fRuns ||
413 fRunIndex != that.fRunIndex ||
414 fGlyphIndex != that.fGlyphIndex;
415 }
416
417 ShapedGlyph* next() {
418 const SkTArray<ShapedRun>& runs = *fRuns;
419 SkASSERT(fRunIndex < runs.count());
420 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
421
422 ++fGlyphIndex;
423 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
424 fGlyphIndex = 0;
425 ++fRunIndex;
426 if (fRunIndex >= runs.count()) {
427 return nullptr;
428 }
429 }
430 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
431 }
432
433 ShapedGlyph* current() {
434 const SkTArray<ShapedRun>& runs = *fRuns;
435 if (fRunIndex >= runs.count()) {
436 return nullptr;
437 }
438 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
439 }
440
441 const SkTArray<ShapedRun>* fRuns;
442 int fRunIndex;
443 int fGlyphIndex;
444};
445
446} // namespace
447
448struct SkShaper::Impl {
449 HBFont fHarfBuzzFont;
450 HBBuffer fBuffer;
451 sk_sp<SkTypeface> fTypeface;
452 std::unique_ptr<icu::BreakIterator> fBreakIterator;
453};
454
Ben Wagnere0001732017-08-31 16:26:26 -0400455SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary0e07ad72018-02-08 13:06:56 -0500456 SkOnce once;
457 once([] { SkLoadICU(); });
458
Ben Wagnere0001732017-08-31 16:26:26 -0400459 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
460 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Ben Wagnera25fbef2017-08-30 13:56:19 -0400461 SkASSERT(fImpl->fHarfBuzzFont);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400462 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500463 SkASSERT(fImpl->fBuffer);
464
465 icu::Locale thai("th");
466 UErrorCode status = U_ZERO_ERROR;
467 fImpl->fBreakIterator.reset(icu::BreakIterator::createLineInstance(thai, status));
468 if (U_FAILURE(status)) {
469 SkDebugf("Could not create break iterator: %s", u_errorName(status));
470 SK_ABORT("");
471 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400472}
473
474SkShaper::~SkShaper() {}
475
Ben Wagner8d45a382017-11-16 10:08:28 -0500476bool SkShaper::good() const {
477 return fImpl->fHarfBuzzFont &&
478 fImpl->fBuffer &&
479 fImpl->fTypeface &&
480 fImpl->fBreakIterator;
481}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400482
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500483SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
484 const SkPaint& srcPaint,
485 const char* utf8,
486 size_t utf8Bytes,
487 bool leftToRight,
488 SkPoint point,
489 SkScalar width) const {
Ben Wagner67e3a302017-09-05 14:46:19 -0400490 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
Ben Wagnera25fbef2017-08-30 13:56:19 -0400491 SkASSERT(builder);
Ben Wagner8d45a382017-11-16 10:08:28 -0500492 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400493 //hb_script_t script = ...
Ben Wagnera25fbef2017-08-30 13:56:19 -0400494
Ben Wagner8d45a382017-11-16 10:08:28 -0500495 SkTArray<ShapedRun> runs;
496{
497 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400498
Ben Wagner8d45a382017-11-16 10:08:28 -0500499 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
500 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
501 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500502 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400503 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500504 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400505
Ben Wagner8d45a382017-11-16 10:08:28 -0500506 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
507 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
508 ScriptRunIterator* script = maybeScript.getMaybeNull();
509 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500510 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400511 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500512 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400513
Ben Wagner8d45a382017-11-16 10:08:28 -0500514 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
515 fImpl->fTypeface,
516 fImpl->fHarfBuzzFont.get(),
517 std::move(fontMgr)));
518 FontRunIterator* font = maybeFont.getMaybeNull();
519 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500520 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400521 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500522 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400523
Ben Wagner8d45a382017-11-16 10:08:28 -0500524 icu::BreakIterator& breakIterator = *fImpl->fBreakIterator;
525 {
526 UErrorCode status = U_ZERO_ERROR;
527 UText utf8UText = UTEXT_INITIALIZER;
528 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
529 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
530 if (U_FAILURE(status)) {
531 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500532 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500533 }
534 breakIterator.setText(&utf8UText, status);
535 //utext_close(&utf8UText);
536 if (U_FAILURE(status)) {
537 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500538 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500539 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400540 }
541
Ben Wagner8d45a382017-11-16 10:08:28 -0500542 const char* utf8Start = nullptr;
543 const char* utf8End = utf8;
544 while (runSegmenter.advanceRuns()) {
545 utf8Start = utf8End;
546 utf8End = runSegmenter.endOfCurrentRun();
547
548 hb_buffer_t* buffer = fImpl->fBuffer.get();
549 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
550 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
551 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
552
553 // Populate the hb_buffer directly with utf8 cluster indexes.
554 const char* utf8Current = utf8Start;
555 while (utf8Current < utf8End) {
556 unsigned int cluster = utf8Current - utf8Start;
Hal Canary4014ba62018-07-24 11:33:21 -0400557 hb_codepoint_t u = SkUTF8_NextUnichar(&utf8Current, utf8End);
Ben Wagner8d45a382017-11-16 10:08:28 -0500558 hb_buffer_add(buffer, u, cluster);
559 }
560
561 size_t utf8runLength = utf8End - utf8Start;
562 if (!SkTFitsIn<int>(utf8runLength)) {
563 SkDebugf("Shaping error: utf8 too long");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500564 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500565 }
566 hb_buffer_set_script(buffer, script->currentScript());
567 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
568 hb_buffer_set_direction(buffer, direction);
569 // TODO: language
570 hb_buffer_guess_segment_properties(buffer);
571 // TODO: features
572 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
573 unsigned len = hb_buffer_get_length(buffer);
574 if (len == 0) {
575 continue;
576 }
577
578 if (direction == HB_DIRECTION_RTL) {
579 // Put the clusters back in logical order.
580 // Note that the advances remain ltr.
581 hb_buffer_reverse(buffer);
582 }
583 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
584 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
585
586 if (!SkTFitsIn<int>(len)) {
587 SkDebugf("Shaping error: too many glyphs");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500588 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500589 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400590
591 SkPaint paint(srcPaint);
592 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Ben Wagner8d45a382017-11-16 10:08:28 -0500593 paint.setTypeface(sk_ref_sp(font->currentTypeface()));
594 ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, paint, bidi->currentLevel(),
595 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
596 int scaleX, scaleY;
597 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
598 double textSizeY = run.fPaint.getTextSize() / scaleY;
599 double textSizeX = run.fPaint.getTextSize() / scaleX * run.fPaint.getTextScaleX();
600 for (unsigned i = 0; i < len; i++) {
601 ShapedGlyph& glyph = run.fGlyphs[i];
602 glyph.fID = info[i].codepoint;
603 glyph.fCluster = info[i].cluster;
604 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
605 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
606 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
607 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
608 glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
609 //info->mask safe_to_break;
610 glyph.fMustLineBreakBefore = false;
611 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400612
Ben Wagner8d45a382017-11-16 10:08:28 -0500613 int32_t clusterOffset = utf8Start - utf8;
614 uint32_t previousCluster = 0xFFFFFFFF;
615 for (unsigned i = 0; i < len; ++i) {
616 ShapedGlyph& glyph = run.fGlyphs[i];
617 int32_t glyphCluster = glyph.fCluster + clusterOffset;
618 int32_t breakIteratorCurrent = breakIterator.current();
619 while (breakIteratorCurrent != icu::BreakIterator::DONE &&
620 breakIteratorCurrent < glyphCluster)
621 {
622 breakIteratorCurrent = breakIterator.next();
Ben Wagner2868b782017-08-31 14:12:27 -0400623 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500624 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
625 breakIteratorCurrent == glyphCluster;
626 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400627 }
628 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500629}
630
631// Iterate over the glyphs in logical order to mark line endings.
632{
633 SkScalar widthSoFar = 0;
634 bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
635 bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
636 ShapedRunGlyphIterator previousBreak(runs);
637 ShapedRunGlyphIterator glyphIterator(runs);
638 while (ShapedGlyph* glyph = glyphIterator.current()) {
639 if (canAddBreakNow && glyph->fMayLineBreakBefore) {
640 previousBreakValid = true;
641 previousBreak = glyphIterator;
642 }
643 SkScalar glyphWidth = glyph->fAdvance.fX;
644 if (widthSoFar + glyphWidth < width) {
645 widthSoFar += glyphWidth;
646 glyphIterator.next();
647 canAddBreakNow = true;
648 continue;
649 }
650
651 if (widthSoFar == 0) {
652 // Adding just this glyph is too much, just break with this glyph
653 glyphIterator.next();
654 previousBreak = glyphIterator;
655 } else if (!previousBreakValid) {
656 // No break opprotunity found yet, just break without this glyph
657 previousBreak = glyphIterator;
658 }
659 glyphIterator = previousBreak;
660 glyph = glyphIterator.current();
661 if (glyph) {
662 glyph->fMustLineBreakBefore = true;
663 }
664 widthSoFar = 0;
665 previousBreakValid = false;
666 canAddBreakNow = false;
667 }
668}
669
670// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500671 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500672{
673 ShapedRunGlyphIterator previousBreak(runs);
674 ShapedRunGlyphIterator glyphIterator(runs);
675 SkScalar maxAscent = 0;
676 SkScalar maxDescent = 0;
677 SkScalar maxLeading = 0;
678 int previousRunIndex = -1;
679 while (glyphIterator.current()) {
680 int runIndex = glyphIterator.fRunIndex;
681 int glyphIndex = glyphIterator.fGlyphIndex;
682 ShapedGlyph* nextGlyph = glyphIterator.next();
683
684 if (previousRunIndex != runIndex) {
685 SkPaint::FontMetrics metrics;
686 runs[runIndex].fPaint.getFontMetrics(&metrics);
687 maxAscent = SkTMin(maxAscent, metrics.fAscent);
688 maxDescent = SkTMax(maxDescent, metrics.fDescent);
689 maxLeading = SkTMax(maxLeading, metrics.fLeading);
690 previousRunIndex = runIndex;
691 }
692
693 // Nothing can be written until the baseline is known.
694 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
695 continue;
696 }
697
698 currentPoint.fY -= maxAscent;
699
700 int numRuns = runIndex - previousBreak.fRunIndex + 1;
701 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
702 for (int i = 0; i < numRuns; ++i) {
703 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
704 }
705 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
706 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
707
708 for (int i = 0; i < numRuns; ++i) {
709 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
710
711 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
712 ? previousBreak.fGlyphIndex
713 : 0;
714 int endGlyphIndex = (logicalIndex == runIndex)
715 ? glyphIndex + 1
716 : runs[logicalIndex].fNumGlyphs;
717 append(builder, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
718 }
719
720 currentPoint.fY += maxDescent + maxLeading;
721 currentPoint.fX = point.fX;
722 maxAscent = 0;
723 maxDescent = 0;
724 maxLeading = 0;
725 previousRunIndex = -1;
726 previousBreak = glyphIterator;
727 }
728}
729
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500730 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400731}