blob: c15395b7eacce030ec2ac9adb2dd941076b85653 [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
Ben Wagner17774242018-08-07 14:31:33 -04008#include "SkFontArguments.h"
Ben Wagner67e3a302017-09-05 14:46:19 -04009#include "SkFontMgr.h"
Hal Canary0e07ad72018-02-08 13:06:56 -050010#include "SkLoadICU.h"
Ben Wagner17774242018-08-07 14:31:33 -040011#include "SkMalloc.h"
Hal Canary0e07ad72018-02-08 13:06:56 -050012#include "SkOnce.h"
Ben Wagner17774242018-08-07 14:31:33 -040013#include "SkPaint.h"
14#include "SkPoint.h"
15#include "SkRefCnt.h"
16#include "SkScalar.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040017#include "SkShaper.h"
18#include "SkStream.h"
Ben Wagner17774242018-08-07 14:31:33 -040019#include "SkString.h"
20#include "SkTArray.h"
Ben Wagner8d45a382017-11-16 10:08:28 -050021#include "SkTDPQueue.h"
Ben Wagner17774242018-08-07 14:31:33 -040022#include "SkTFitsIn.h"
Ben Wagner8d45a382017-11-16 10:08:28 -050023#include "SkTLazy.h"
Ben Wagnere0001732017-08-31 16:26:26 -040024#include "SkTemplates.h"
Cary Clarke12a0902018-08-09 10:07:33 -040025#include "SkTextBlobPriv.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040026#include "SkTo.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040027#include "SkTypeface.h"
Ben Wagner17774242018-08-07 14:31:33 -040028#include "SkTypes.h"
29#include "SkUTF.h"
30
31#include <hb.h>
32#include <hb-ot.h>
33#include <unicode/brkiter.h>
34#include <unicode/locid.h>
35#include <unicode/stringpiece.h>
36#include <unicode/ubidi.h>
37#include <unicode/unistr.h>
38#include <unicode/urename.h>
39#include <unicode/utext.h>
40#include <unicode/utypes.h>
41
42#include <memory>
43#include <utility>
44#include <cstring>
Ben Wagnera25fbef2017-08-30 13:56:19 -040045
Ben Wagnera25fbef2017-08-30 13:56:19 -040046namespace {
47template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
48using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
49using HBFace = resource<hb_face_t , hb_face_destroy >;
50using HBFont = resource<hb_font_t , hb_font_destroy >;
51using HBBuffer = resource<hb_buffer_t, hb_buffer_destroy>;
52using ICUBiDi = resource<UBiDi , ubidi_close >;
53
54HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
55 size_t size = asset->getLength();
56 HBBlob blob;
57 if (const void* base = asset->getMemoryBase()) {
58 blob.reset(hb_blob_create((char*)base, SkToUInt(size),
59 HB_MEMORY_MODE_READONLY, asset.release(),
60 [](void* p) { delete (SkStreamAsset*)p; }));
61 } else {
62 // SkDebugf("Extra SkStreamAsset copy\n");
63 void* ptr = size ? sk_malloc_throw(size) : nullptr;
64 asset->read(ptr, size);
65 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
66 HB_MEMORY_MODE_READONLY, ptr, sk_free));
67 }
68 SkASSERT(blob);
69 hb_blob_make_immutable(blob.get());
70 return blob;
71}
Ben Wagnera25fbef2017-08-30 13:56:19 -040072
Ben Wagner8d45a382017-11-16 10:08:28 -050073HBFont create_hb_font(SkTypeface* tf) {
Ben Wagnera25fbef2017-08-30 13:56:19 -040074 int index;
Ben Wagnere0001732017-08-31 16:26:26 -040075 HBBlob blob(stream_to_blob(std::unique_ptr<SkStreamAsset>(tf->openStream(&index))));
Ben Wagnera25fbef2017-08-30 13:56:19 -040076 HBFace face(hb_face_create(blob.get(), (unsigned)index));
77 SkASSERT(face);
78 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040079 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040080 }
81 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -040082 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -040083
Ben Wagnere0001732017-08-31 16:26:26 -040084 HBFont font(hb_font_create(face.get()));
85 SkASSERT(font);
86 if (!font) {
87 return nullptr;
88 }
Ben Wagnere0001732017-08-31 16:26:26 -040089 hb_ot_font_set_funcs(font.get());
90 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
91 if (axis_count > 0) {
92 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
93 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
94 hb_font_set_variations(font.get(),
95 reinterpret_cast<hb_variation_t*>(axis_values.get()),
96 axis_count);
97 }
98 }
99 return font;
100}
101
Hal Canaryf107a2f2018-07-25 16:52:48 -0400102/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
103static inline SkUnichar utf8_next(const char** ptr, const char* end) {
104 SkUnichar val = SkUTF::NextUTF8(ptr, end);
105 if (val < 0) {
106 return 0xFFFD; // REPLACEMENT CHARACTER
107 }
108 return val;
109}
110
Ben Wagner8d45a382017-11-16 10:08:28 -0500111class RunIterator {
112public:
113 virtual ~RunIterator() {}
114 virtual void consume() = 0;
115 // Pointer one past the last (utf8) element in the current run.
116 virtual const char* endOfCurrentRun() const = 0;
117 virtual bool atEnd() const = 0;
118 bool operator<(const RunIterator& that) const {
119 return this->endOfCurrentRun() < that.endOfCurrentRun();
120 }
121};
122
123class BiDiRunIterator : public RunIterator {
124public:
125 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
126 SkTLazy<BiDiRunIterator> ret;
127
128 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
129 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
130 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
131 SkDebugf("Bidi error: text too long");
132 return ret;
133 }
134 icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, utf8Bytes));
135
136 UErrorCode status = U_ZERO_ERROR;
137 ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
138 if (U_FAILURE(status)) {
139 SkDebugf("Bidi error: %s", u_errorName(status));
140 return ret;
141 }
142 SkASSERT(bidi);
143
144 // The required lifetime of utf16 isn't well documented.
145 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
146 ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), level, nullptr, &status);
147 if (U_FAILURE(status)) {
148 SkDebugf("Bidi error: %s", u_errorName(status));
149 return ret;
150 }
151
Hal Canary4014ba62018-07-24 11:33:21 -0400152 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500153 return ret;
154 }
Hal Canary4014ba62018-07-24 11:33:21 -0400155 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500156 : fBidi(std::move(bidi))
157 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400158 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500159 , fUTF16LogicalPosition(0)
160 , fLevel(UBIDI_DEFAULT_LTR)
161 {}
162 void consume() override {
163 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
164 int32_t endPosition = ubidi_getLength(fBidi.get());
165 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400166 SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
167 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500168 UBiDiLevel level;
169 while (fUTF16LogicalPosition < endPosition) {
170 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
171 if (level != fLevel) {
172 break;
173 }
Hal Canaryf107a2f2018-07-25 16:52:48 -0400174 u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
175 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500176 }
177 }
178 const char* endOfCurrentRun() const override {
179 return fEndOfCurrentRun;
180 }
181 bool atEnd() const override {
182 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
183 }
184
185 UBiDiLevel currentLevel() const {
186 return fLevel;
187 }
188private:
189 ICUBiDi fBidi;
190 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400191 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500192 int32_t fUTF16LogicalPosition;
193 UBiDiLevel fLevel;
194};
195
196class ScriptRunIterator : public RunIterator {
197public:
198 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
199 hb_unicode_funcs_t* hbUnicode)
200 {
201 SkTLazy<ScriptRunIterator> ret;
202 ret.init(utf8, utf8Bytes, hbUnicode);
203 return ret;
204 }
205 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
206 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
207 , fHBUnicode(hbUnicode)
208 , fCurrentScript(HB_SCRIPT_UNKNOWN)
209 {}
210 void consume() override {
211 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400212 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500213 fCurrentScript = hb_unicode_script(fHBUnicode, u);
214 while (fCurrent < fEnd) {
215 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400216 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500217 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
218 if (script != fCurrentScript) {
219 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
220 fCurrentScript = script;
221 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
222 continue;
223 } else {
224 fCurrent = prev;
225 break;
226 }
227 }
228 }
229 if (fCurrentScript == HB_SCRIPT_INHERITED) {
230 fCurrentScript = HB_SCRIPT_COMMON;
231 }
232 }
233 const char* endOfCurrentRun() const override {
234 return fCurrent;
235 }
236 bool atEnd() const override {
237 return fCurrent == fEnd;
238 }
239
240 hb_script_t currentScript() const {
241 return fCurrentScript;
242 }
243private:
244 const char* fCurrent;
245 const char* fEnd;
246 hb_unicode_funcs_t* fHBUnicode;
247 hb_script_t fCurrentScript;
248};
249
250class FontRunIterator : public RunIterator {
251public:
252 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
253 sk_sp<SkTypeface> typeface,
254 hb_font_t* hbFace,
255 sk_sp<SkFontMgr> fallbackMgr)
256 {
257 SkTLazy<FontRunIterator> ret;
258 ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
259 return ret;
260 }
261 FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
262 hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
263 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
264 , fFallbackMgr(std::move(fallbackMgr))
265 , fHBFont(hbFace), fTypeface(std::move(typeface))
266 , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
267 , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
268 {}
269 void consume() override {
270 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400271 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500272 // If the starting typeface can handle this character, use it.
273 if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
274 fFallbackTypeface.reset();
275 // If not, try to find a fallback typeface
276 } else {
277 fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
278 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
279 }
280
281 if (fFallbackTypeface) {
282 fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
283 fCurrentTypeface = fFallbackTypeface.get();
284 fCurrentHBFont = fFallbackHBFont.get();
285 } else {
286 fFallbackHBFont.reset();
287 fCurrentTypeface = fTypeface.get();
288 fCurrentHBFont = fHBFont;
289 }
290
291 while (fCurrent < fEnd) {
292 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400293 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500294
295 // If using a fallback and the initial typeface has this character, stop fallback.
296 if (fFallbackTypeface &&
297 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
298 {
299 fCurrent = prev;
300 return;
301 }
302 // If the current typeface cannot handle this character, stop using it.
303 if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
304 fCurrent = prev;
305 return;
306 }
307 }
308 }
309 const char* endOfCurrentRun() const override {
310 return fCurrent;
311 }
312 bool atEnd() const override {
313 return fCurrent == fEnd;
314 }
315
316 SkTypeface* currentTypeface() const {
317 return fCurrentTypeface;
318 }
319 hb_font_t* currentHBFont() const {
320 return fCurrentHBFont;
321 }
322private:
323 const char* fCurrent;
324 const char* fEnd;
325 sk_sp<SkFontMgr> fFallbackMgr;
326 hb_font_t* fHBFont;
327 sk_sp<SkTypeface> fTypeface;
328 HBFont fFallbackHBFont;
329 sk_sp<SkTypeface> fFallbackTypeface;
330 hb_font_t* fCurrentHBFont;
331 SkTypeface* fCurrentTypeface;
332};
333
334class RunIteratorQueue {
335public:
336 void insert(RunIterator* runIterator) {
337 fRunIterators.insert(runIterator);
338 }
339
340 bool advanceRuns() {
341 const RunIterator* leastRun = fRunIterators.peek();
342 if (leastRun->atEnd()) {
343 SkASSERT(this->allRunsAreAtEnd());
344 return false;
345 }
346 const char* leastEnd = leastRun->endOfCurrentRun();
347 RunIterator* currentRun = nullptr;
348 SkDEBUGCODE(const char* previousEndOfCurrentRun);
349 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
350 fRunIterators.pop();
351 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
352 currentRun->consume();
353 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
354 fRunIterators.insert(currentRun);
355 }
356 return true;
357 }
358
359 const char* endOfCurrentRun() const {
360 return fRunIterators.peek()->endOfCurrentRun();
361 }
362
363private:
364 bool allRunsAreAtEnd() const {
365 for (int i = 0; i < fRunIterators.count(); ++i) {
366 if (!fRunIterators.at(i)->atEnd()) {
367 return false;
368 }
369 }
370 return true;
371 }
372
373 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
374 return *a < *b;
375 }
376 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
377};
378
379struct ShapedGlyph {
380 SkGlyphID fID;
381 uint32_t fCluster;
382 SkPoint fOffset;
383 SkVector fAdvance;
384 bool fMayLineBreakBefore;
385 bool fMustLineBreakBefore;
386 bool fHasVisual;
387};
388struct ShapedRun {
389 ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkPaint& paint,
390 UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
391 : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fPaint(paint)
392 , fLevel(level), fGlyphs(std::move(glyphs))
393 {}
394
395 const char* fUtf8Start;
396 const char* fUtf8End;
397 int fNumGlyphs;
398 SkPaint fPaint;
399 UBiDiLevel fLevel;
400 std::unique_ptr<ShapedGlyph[]> fGlyphs;
401};
402
403static constexpr bool is_LTR(UBiDiLevel level) {
404 return (level & 1) == 0;
405}
406
407static void append(SkTextBlobBuilder* b, const ShapedRun& run, int start, int end, SkPoint* p) {
408 unsigned len = end - start;
Cary Clarke12a0902018-08-09 10:07:33 -0400409 auto runBuffer = SkTextBlobBuilderPriv::AllocRunTextPos(b, run.fPaint, len,
410 run.fUtf8End - run.fUtf8Start, SkString());
Ben Wagner8d45a382017-11-16 10:08:28 -0500411 memcpy(runBuffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
412
413 for (unsigned i = 0; i < len; i++) {
414 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
415 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
416 runBuffer.glyphs[i] = glyph.fID;
417 runBuffer.clusters[i] = glyph.fCluster;
418 reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
419 SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
420 p->fX += glyph.fAdvance.fX;
421 p->fY += glyph.fAdvance.fY;
422 }
423}
424
425struct ShapedRunGlyphIterator {
426 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
427 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
428 { }
429
430 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
431 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
432 bool operator==(const ShapedRunGlyphIterator& that) const {
433 return fRuns == that.fRuns &&
434 fRunIndex == that.fRunIndex &&
435 fGlyphIndex == that.fGlyphIndex;
436 }
437 bool operator!=(const ShapedRunGlyphIterator& that) const {
438 return fRuns != that.fRuns ||
439 fRunIndex != that.fRunIndex ||
440 fGlyphIndex != that.fGlyphIndex;
441 }
442
443 ShapedGlyph* next() {
444 const SkTArray<ShapedRun>& runs = *fRuns;
445 SkASSERT(fRunIndex < runs.count());
446 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
447
448 ++fGlyphIndex;
449 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
450 fGlyphIndex = 0;
451 ++fRunIndex;
452 if (fRunIndex >= runs.count()) {
453 return nullptr;
454 }
455 }
456 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
457 }
458
459 ShapedGlyph* current() {
460 const SkTArray<ShapedRun>& runs = *fRuns;
461 if (fRunIndex >= runs.count()) {
462 return nullptr;
463 }
464 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
465 }
466
467 const SkTArray<ShapedRun>* fRuns;
468 int fRunIndex;
469 int fGlyphIndex;
470};
471
472} // namespace
473
474struct SkShaper::Impl {
475 HBFont fHarfBuzzFont;
476 HBBuffer fBuffer;
477 sk_sp<SkTypeface> fTypeface;
478 std::unique_ptr<icu::BreakIterator> fBreakIterator;
479};
480
Ben Wagnere0001732017-08-31 16:26:26 -0400481SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary0e07ad72018-02-08 13:06:56 -0500482 SkOnce once;
483 once([] { SkLoadICU(); });
484
Ben Wagnere0001732017-08-31 16:26:26 -0400485 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
486 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Ben Wagnera25fbef2017-08-30 13:56:19 -0400487 SkASSERT(fImpl->fHarfBuzzFont);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400488 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500489 SkASSERT(fImpl->fBuffer);
490
491 icu::Locale thai("th");
492 UErrorCode status = U_ZERO_ERROR;
493 fImpl->fBreakIterator.reset(icu::BreakIterator::createLineInstance(thai, status));
494 if (U_FAILURE(status)) {
495 SkDebugf("Could not create break iterator: %s", u_errorName(status));
496 SK_ABORT("");
497 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400498}
499
500SkShaper::~SkShaper() {}
501
Ben Wagner8d45a382017-11-16 10:08:28 -0500502bool SkShaper::good() const {
503 return fImpl->fHarfBuzzFont &&
504 fImpl->fBuffer &&
505 fImpl->fTypeface &&
506 fImpl->fBreakIterator;
507}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400508
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500509SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
510 const SkPaint& srcPaint,
511 const char* utf8,
512 size_t utf8Bytes,
513 bool leftToRight,
514 SkPoint point,
515 SkScalar width) const {
Ben Wagner67e3a302017-09-05 14:46:19 -0400516 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
Ben Wagnera25fbef2017-08-30 13:56:19 -0400517 SkASSERT(builder);
Ben Wagner8d45a382017-11-16 10:08:28 -0500518 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400519 //hb_script_t script = ...
Ben Wagnera25fbef2017-08-30 13:56:19 -0400520
Ben Wagner8d45a382017-11-16 10:08:28 -0500521 SkTArray<ShapedRun> runs;
522{
523 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400524
Ben Wagner8d45a382017-11-16 10:08:28 -0500525 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
526 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
527 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500528 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400529 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500530 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400531
Ben Wagner8d45a382017-11-16 10:08:28 -0500532 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
533 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
534 ScriptRunIterator* script = maybeScript.getMaybeNull();
535 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500536 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400537 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500538 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400539
Ben Wagner8d45a382017-11-16 10:08:28 -0500540 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
541 fImpl->fTypeface,
542 fImpl->fHarfBuzzFont.get(),
543 std::move(fontMgr)));
544 FontRunIterator* font = maybeFont.getMaybeNull();
545 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500546 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400547 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500548 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400549
Ben Wagner8d45a382017-11-16 10:08:28 -0500550 icu::BreakIterator& breakIterator = *fImpl->fBreakIterator;
551 {
552 UErrorCode status = U_ZERO_ERROR;
553 UText utf8UText = UTEXT_INITIALIZER;
554 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
555 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
556 if (U_FAILURE(status)) {
557 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500558 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500559 }
560 breakIterator.setText(&utf8UText, status);
561 //utext_close(&utf8UText);
562 if (U_FAILURE(status)) {
563 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500564 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500565 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400566 }
567
Ben Wagner8d45a382017-11-16 10:08:28 -0500568 const char* utf8Start = nullptr;
569 const char* utf8End = utf8;
570 while (runSegmenter.advanceRuns()) {
571 utf8Start = utf8End;
572 utf8End = runSegmenter.endOfCurrentRun();
573
574 hb_buffer_t* buffer = fImpl->fBuffer.get();
575 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
576 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
577 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
578
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400579 // Add precontext.
580 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
581
Ben Wagner8d45a382017-11-16 10:08:28 -0500582 // Populate the hb_buffer directly with utf8 cluster indexes.
583 const char* utf8Current = utf8Start;
584 while (utf8Current < utf8End) {
585 unsigned int cluster = utf8Current - utf8Start;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400586 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
Ben Wagner8d45a382017-11-16 10:08:28 -0500587 hb_buffer_add(buffer, u, cluster);
588 }
589
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400590 // Add postcontext.
591 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
592
Ben Wagner8d45a382017-11-16 10:08:28 -0500593 size_t utf8runLength = utf8End - utf8Start;
594 if (!SkTFitsIn<int>(utf8runLength)) {
595 SkDebugf("Shaping error: utf8 too long");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500596 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500597 }
598 hb_buffer_set_script(buffer, script->currentScript());
599 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
600 hb_buffer_set_direction(buffer, direction);
601 // TODO: language
602 hb_buffer_guess_segment_properties(buffer);
603 // TODO: features
604 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
605 unsigned len = hb_buffer_get_length(buffer);
606 if (len == 0) {
607 continue;
608 }
609
610 if (direction == HB_DIRECTION_RTL) {
611 // Put the clusters back in logical order.
612 // Note that the advances remain ltr.
613 hb_buffer_reverse(buffer);
614 }
615 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
616 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
617
618 if (!SkTFitsIn<int>(len)) {
619 SkDebugf("Shaping error: too many glyphs");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500620 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500621 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400622
623 SkPaint paint(srcPaint);
624 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Ben Wagner8d45a382017-11-16 10:08:28 -0500625 paint.setTypeface(sk_ref_sp(font->currentTypeface()));
626 ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, paint, bidi->currentLevel(),
627 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
628 int scaleX, scaleY;
629 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
630 double textSizeY = run.fPaint.getTextSize() / scaleY;
631 double textSizeX = run.fPaint.getTextSize() / scaleX * run.fPaint.getTextScaleX();
632 for (unsigned i = 0; i < len; i++) {
633 ShapedGlyph& glyph = run.fGlyphs[i];
634 glyph.fID = info[i].codepoint;
635 glyph.fCluster = info[i].cluster;
636 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
637 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
638 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
639 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
640 glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
641 //info->mask safe_to_break;
642 glyph.fMustLineBreakBefore = false;
643 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400644
Ben Wagner8d45a382017-11-16 10:08:28 -0500645 int32_t clusterOffset = utf8Start - utf8;
646 uint32_t previousCluster = 0xFFFFFFFF;
647 for (unsigned i = 0; i < len; ++i) {
648 ShapedGlyph& glyph = run.fGlyphs[i];
649 int32_t glyphCluster = glyph.fCluster + clusterOffset;
650 int32_t breakIteratorCurrent = breakIterator.current();
651 while (breakIteratorCurrent != icu::BreakIterator::DONE &&
652 breakIteratorCurrent < glyphCluster)
653 {
654 breakIteratorCurrent = breakIterator.next();
Ben Wagner2868b782017-08-31 14:12:27 -0400655 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500656 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
657 breakIteratorCurrent == glyphCluster;
658 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400659 }
660 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500661}
662
663// Iterate over the glyphs in logical order to mark line endings.
664{
665 SkScalar widthSoFar = 0;
666 bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
667 bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
668 ShapedRunGlyphIterator previousBreak(runs);
669 ShapedRunGlyphIterator glyphIterator(runs);
670 while (ShapedGlyph* glyph = glyphIterator.current()) {
671 if (canAddBreakNow && glyph->fMayLineBreakBefore) {
672 previousBreakValid = true;
673 previousBreak = glyphIterator;
674 }
675 SkScalar glyphWidth = glyph->fAdvance.fX;
676 if (widthSoFar + glyphWidth < width) {
677 widthSoFar += glyphWidth;
678 glyphIterator.next();
679 canAddBreakNow = true;
680 continue;
681 }
682
683 if (widthSoFar == 0) {
684 // Adding just this glyph is too much, just break with this glyph
685 glyphIterator.next();
686 previousBreak = glyphIterator;
687 } else if (!previousBreakValid) {
688 // No break opprotunity found yet, just break without this glyph
689 previousBreak = glyphIterator;
690 }
691 glyphIterator = previousBreak;
692 glyph = glyphIterator.current();
693 if (glyph) {
694 glyph->fMustLineBreakBefore = true;
695 }
696 widthSoFar = 0;
697 previousBreakValid = false;
698 canAddBreakNow = false;
699 }
700}
701
702// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500703 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500704{
705 ShapedRunGlyphIterator previousBreak(runs);
706 ShapedRunGlyphIterator glyphIterator(runs);
707 SkScalar maxAscent = 0;
708 SkScalar maxDescent = 0;
709 SkScalar maxLeading = 0;
710 int previousRunIndex = -1;
711 while (glyphIterator.current()) {
712 int runIndex = glyphIterator.fRunIndex;
713 int glyphIndex = glyphIterator.fGlyphIndex;
714 ShapedGlyph* nextGlyph = glyphIterator.next();
715
716 if (previousRunIndex != runIndex) {
717 SkPaint::FontMetrics metrics;
718 runs[runIndex].fPaint.getFontMetrics(&metrics);
719 maxAscent = SkTMin(maxAscent, metrics.fAscent);
720 maxDescent = SkTMax(maxDescent, metrics.fDescent);
721 maxLeading = SkTMax(maxLeading, metrics.fLeading);
722 previousRunIndex = runIndex;
723 }
724
725 // Nothing can be written until the baseline is known.
726 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
727 continue;
728 }
729
730 currentPoint.fY -= maxAscent;
731
732 int numRuns = runIndex - previousBreak.fRunIndex + 1;
733 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
734 for (int i = 0; i < numRuns; ++i) {
735 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
736 }
737 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
738 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
739
740 for (int i = 0; i < numRuns; ++i) {
741 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
742
743 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
744 ? previousBreak.fGlyphIndex
745 : 0;
746 int endGlyphIndex = (logicalIndex == runIndex)
747 ? glyphIndex + 1
748 : runs[logicalIndex].fNumGlyphs;
749 append(builder, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
750 }
751
752 currentPoint.fY += maxDescent + maxLeading;
753 currentPoint.fX = point.fX;
754 maxAscent = 0;
755 maxDescent = 0;
756 maxLeading = 0;
757 previousRunIndex = -1;
758 previousBreak = glyphIterator;
759 }
760}
761
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500762 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400763}