blob: ced56ee512b4a7632d010665927fa6f8a598b6e4 [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"
Hal Canary2a1848d2018-11-26 17:23:24 -050013#include "SkFont.h"
Ben Wagner17774242018-08-07 14:31:33 -040014#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) {
Hal Canary0dfa2082018-10-31 13:02:49 -040074 if (!tf) {
75 return nullptr;
76 }
Ben Wagnera25fbef2017-08-30 13:56:19 -040077 int index;
Hal Canaryddef43f2018-11-16 10:53:51 -050078 std::unique_ptr<SkStreamAsset> typefaceAsset(tf->openStream(&index));
79 if (!typefaceAsset) {
80 SkString name;
81 tf->getFamilyName(&name);
82 SkDebugf("Typeface '%s' has no data :(\n", name.c_str());
83 return nullptr;
84 }
85 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
Ben Wagnera25fbef2017-08-30 13:56:19 -040086 HBFace face(hb_face_create(blob.get(), (unsigned)index));
87 SkASSERT(face);
88 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040089 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040090 }
91 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -040092 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -040093
Ben Wagnere0001732017-08-31 16:26:26 -040094 HBFont font(hb_font_create(face.get()));
95 SkASSERT(font);
96 if (!font) {
97 return nullptr;
98 }
Ben Wagnere0001732017-08-31 16:26:26 -040099 hb_ot_font_set_funcs(font.get());
100 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
101 if (axis_count > 0) {
102 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
103 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
104 hb_font_set_variations(font.get(),
105 reinterpret_cast<hb_variation_t*>(axis_values.get()),
106 axis_count);
107 }
108 }
109 return font;
110}
111
Hal Canaryf107a2f2018-07-25 16:52:48 -0400112/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
113static inline SkUnichar utf8_next(const char** ptr, const char* end) {
114 SkUnichar val = SkUTF::NextUTF8(ptr, end);
115 if (val < 0) {
116 return 0xFFFD; // REPLACEMENT CHARACTER
117 }
118 return val;
119}
120
Ben Wagner8d45a382017-11-16 10:08:28 -0500121class RunIterator {
122public:
123 virtual ~RunIterator() {}
124 virtual void consume() = 0;
125 // Pointer one past the last (utf8) element in the current run.
126 virtual const char* endOfCurrentRun() const = 0;
127 virtual bool atEnd() const = 0;
128 bool operator<(const RunIterator& that) const {
129 return this->endOfCurrentRun() < that.endOfCurrentRun();
130 }
131};
132
133class BiDiRunIterator : public RunIterator {
134public:
135 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
136 SkTLazy<BiDiRunIterator> ret;
137
138 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
139 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
140 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
141 SkDebugf("Bidi error: text too long");
142 return ret;
143 }
144 icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(utf8, utf8Bytes));
145
146 UErrorCode status = U_ZERO_ERROR;
147 ICUBiDi bidi(ubidi_openSized(utf16.length(), 0, &status));
148 if (U_FAILURE(status)) {
149 SkDebugf("Bidi error: %s", u_errorName(status));
150 return ret;
151 }
152 SkASSERT(bidi);
153
154 // The required lifetime of utf16 isn't well documented.
155 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
156 ubidi_setPara(bidi.get(), utf16.getBuffer(), utf16.length(), level, nullptr, &status);
157 if (U_FAILURE(status)) {
158 SkDebugf("Bidi error: %s", u_errorName(status));
159 return ret;
160 }
161
Hal Canary4014ba62018-07-24 11:33:21 -0400162 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500163 return ret;
164 }
Hal Canary4014ba62018-07-24 11:33:21 -0400165 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500166 : fBidi(std::move(bidi))
167 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400168 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500169 , fUTF16LogicalPosition(0)
170 , fLevel(UBIDI_DEFAULT_LTR)
171 {}
172 void consume() override {
173 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
174 int32_t endPosition = ubidi_getLength(fBidi.get());
175 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400176 SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
177 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500178 UBiDiLevel level;
179 while (fUTF16LogicalPosition < endPosition) {
180 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
181 if (level != fLevel) {
182 break;
183 }
Hal Canaryf107a2f2018-07-25 16:52:48 -0400184 u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
185 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500186 }
187 }
188 const char* endOfCurrentRun() const override {
189 return fEndOfCurrentRun;
190 }
191 bool atEnd() const override {
192 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
193 }
194
195 UBiDiLevel currentLevel() const {
196 return fLevel;
197 }
198private:
199 ICUBiDi fBidi;
200 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400201 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500202 int32_t fUTF16LogicalPosition;
203 UBiDiLevel fLevel;
204};
205
206class ScriptRunIterator : public RunIterator {
207public:
208 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
209 hb_unicode_funcs_t* hbUnicode)
210 {
211 SkTLazy<ScriptRunIterator> ret;
212 ret.init(utf8, utf8Bytes, hbUnicode);
213 return ret;
214 }
215 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
216 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
217 , fHBUnicode(hbUnicode)
218 , fCurrentScript(HB_SCRIPT_UNKNOWN)
219 {}
220 void consume() override {
221 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400222 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500223 fCurrentScript = hb_unicode_script(fHBUnicode, u);
224 while (fCurrent < fEnd) {
225 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400226 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500227 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
228 if (script != fCurrentScript) {
229 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
230 fCurrentScript = script;
231 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
232 continue;
233 } else {
234 fCurrent = prev;
235 break;
236 }
237 }
238 }
239 if (fCurrentScript == HB_SCRIPT_INHERITED) {
240 fCurrentScript = HB_SCRIPT_COMMON;
241 }
242 }
243 const char* endOfCurrentRun() const override {
244 return fCurrent;
245 }
246 bool atEnd() const override {
247 return fCurrent == fEnd;
248 }
249
250 hb_script_t currentScript() const {
251 return fCurrentScript;
252 }
253private:
254 const char* fCurrent;
255 const char* fEnd;
256 hb_unicode_funcs_t* fHBUnicode;
257 hb_script_t fCurrentScript;
258};
259
260class FontRunIterator : public RunIterator {
261public:
262 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
263 sk_sp<SkTypeface> typeface,
264 hb_font_t* hbFace,
265 sk_sp<SkFontMgr> fallbackMgr)
266 {
267 SkTLazy<FontRunIterator> ret;
268 ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
269 return ret;
270 }
271 FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
272 hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
273 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
274 , fFallbackMgr(std::move(fallbackMgr))
275 , fHBFont(hbFace), fTypeface(std::move(typeface))
276 , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
277 , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
278 {}
279 void consume() override {
280 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400281 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500282 // If the starting typeface can handle this character, use it.
283 if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400284 fCurrentTypeface = fTypeface.get();
285 fCurrentHBFont = fHBFont;
286 // If the current fallback can handle this character, use it.
287 } else if (fFallbackTypeface &&
288 fFallbackTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
289 {
290 fCurrentTypeface = fFallbackTypeface.get();
291 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500292 // If not, try to find a fallback typeface
293 } else {
294 fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
295 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
Ben Wagner8d45a382017-11-16 10:08:28 -0500296 fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
297 fCurrentTypeface = fFallbackTypeface.get();
298 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500299 }
300
301 while (fCurrent < fEnd) {
302 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400303 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500304
Ben Wagnera900ad52018-08-31 17:48:19 -0400305 // If not using initial typeface and initial typeface has this character, stop fallback.
306 if (fCurrentTypeface != fTypeface.get() &&
Ben Wagner8d45a382017-11-16 10:08:28 -0500307 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
308 {
309 fCurrent = prev;
310 return;
311 }
312 // If the current typeface cannot handle this character, stop using it.
313 if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
314 fCurrent = prev;
315 return;
316 }
317 }
318 }
319 const char* endOfCurrentRun() const override {
320 return fCurrent;
321 }
322 bool atEnd() const override {
323 return fCurrent == fEnd;
324 }
325
326 SkTypeface* currentTypeface() const {
327 return fCurrentTypeface;
328 }
329 hb_font_t* currentHBFont() const {
330 return fCurrentHBFont;
331 }
332private:
333 const char* fCurrent;
334 const char* fEnd;
335 sk_sp<SkFontMgr> fFallbackMgr;
336 hb_font_t* fHBFont;
337 sk_sp<SkTypeface> fTypeface;
338 HBFont fFallbackHBFont;
339 sk_sp<SkTypeface> fFallbackTypeface;
340 hb_font_t* fCurrentHBFont;
341 SkTypeface* fCurrentTypeface;
342};
343
344class RunIteratorQueue {
345public:
346 void insert(RunIterator* runIterator) {
347 fRunIterators.insert(runIterator);
348 }
349
350 bool advanceRuns() {
351 const RunIterator* leastRun = fRunIterators.peek();
352 if (leastRun->atEnd()) {
353 SkASSERT(this->allRunsAreAtEnd());
354 return false;
355 }
356 const char* leastEnd = leastRun->endOfCurrentRun();
357 RunIterator* currentRun = nullptr;
358 SkDEBUGCODE(const char* previousEndOfCurrentRun);
359 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
360 fRunIterators.pop();
361 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
362 currentRun->consume();
363 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
364 fRunIterators.insert(currentRun);
365 }
366 return true;
367 }
368
369 const char* endOfCurrentRun() const {
370 return fRunIterators.peek()->endOfCurrentRun();
371 }
372
373private:
374 bool allRunsAreAtEnd() const {
375 for (int i = 0; i < fRunIterators.count(); ++i) {
376 if (!fRunIterators.at(i)->atEnd()) {
377 return false;
378 }
379 }
380 return true;
381 }
382
383 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
384 return *a < *b;
385 }
386 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
387};
388
389struct ShapedGlyph {
390 SkGlyphID fID;
391 uint32_t fCluster;
392 SkPoint fOffset;
393 SkVector fAdvance;
394 bool fMayLineBreakBefore;
395 bool fMustLineBreakBefore;
396 bool fHasVisual;
397};
398struct ShapedRun {
Hal Canary2a1848d2018-11-26 17:23:24 -0500399 ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkFont& paint,
Ben Wagner8d45a382017-11-16 10:08:28 -0500400 UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
401 : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fPaint(paint)
402 , fLevel(level), fGlyphs(std::move(glyphs))
403 {}
404
405 const char* fUtf8Start;
406 const char* fUtf8End;
407 int fNumGlyphs;
Hal Canary2a1848d2018-11-26 17:23:24 -0500408 SkFont fPaint;
Ben Wagner8d45a382017-11-16 10:08:28 -0500409 UBiDiLevel fLevel;
410 std::unique_ptr<ShapedGlyph[]> fGlyphs;
411};
412
413static constexpr bool is_LTR(UBiDiLevel level) {
414 return (level & 1) == 0;
415}
416
417static void append(SkTextBlobBuilder* b, const ShapedRun& run, int start, int end, SkPoint* p) {
418 unsigned len = end - start;
Hal Canary2a1848d2018-11-26 17:23:24 -0500419 SkPaint tmpPaint;
420 run.fPaint.LEGACY_applyToPaint(&tmpPaint);
421 auto runBuffer = SkTextBlobBuilderPriv::AllocRunTextPos(b, tmpPaint, len,
Cary Clarke12a0902018-08-09 10:07:33 -0400422 run.fUtf8End - run.fUtf8Start, SkString());
Ben Wagner8d45a382017-11-16 10:08:28 -0500423 memcpy(runBuffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
424
425 for (unsigned i = 0; i < len; i++) {
426 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
427 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
428 runBuffer.glyphs[i] = glyph.fID;
429 runBuffer.clusters[i] = glyph.fCluster;
430 reinterpret_cast<SkPoint*>(runBuffer.pos)[i] =
431 SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
432 p->fX += glyph.fAdvance.fX;
433 p->fY += glyph.fAdvance.fY;
434 }
435}
436
437struct ShapedRunGlyphIterator {
438 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
439 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
440 { }
441
442 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
443 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
444 bool operator==(const ShapedRunGlyphIterator& that) const {
445 return fRuns == that.fRuns &&
446 fRunIndex == that.fRunIndex &&
447 fGlyphIndex == that.fGlyphIndex;
448 }
449 bool operator!=(const ShapedRunGlyphIterator& that) const {
450 return fRuns != that.fRuns ||
451 fRunIndex != that.fRunIndex ||
452 fGlyphIndex != that.fGlyphIndex;
453 }
454
455 ShapedGlyph* next() {
456 const SkTArray<ShapedRun>& runs = *fRuns;
457 SkASSERT(fRunIndex < runs.count());
458 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
459
460 ++fGlyphIndex;
461 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
462 fGlyphIndex = 0;
463 ++fRunIndex;
464 if (fRunIndex >= runs.count()) {
465 return nullptr;
466 }
467 }
468 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
469 }
470
471 ShapedGlyph* current() {
472 const SkTArray<ShapedRun>& runs = *fRuns;
473 if (fRunIndex >= runs.count()) {
474 return nullptr;
475 }
476 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
477 }
478
479 const SkTArray<ShapedRun>* fRuns;
480 int fRunIndex;
481 int fGlyphIndex;
482};
483
484} // namespace
485
486struct SkShaper::Impl {
487 HBFont fHarfBuzzFont;
488 HBBuffer fBuffer;
489 sk_sp<SkTypeface> fTypeface;
490 std::unique_ptr<icu::BreakIterator> fBreakIterator;
491};
492
Ben Wagnere0001732017-08-31 16:26:26 -0400493SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary0e07ad72018-02-08 13:06:56 -0500494 SkOnce once;
495 once([] { SkLoadICU(); });
496
Ben Wagnere0001732017-08-31 16:26:26 -0400497 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
498 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Ben Wagnera25fbef2017-08-30 13:56:19 -0400499 SkASSERT(fImpl->fHarfBuzzFont);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400500 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500501 SkASSERT(fImpl->fBuffer);
502
503 icu::Locale thai("th");
504 UErrorCode status = U_ZERO_ERROR;
505 fImpl->fBreakIterator.reset(icu::BreakIterator::createLineInstance(thai, status));
506 if (U_FAILURE(status)) {
507 SkDebugf("Could not create break iterator: %s", u_errorName(status));
508 SK_ABORT("");
509 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400510}
511
512SkShaper::~SkShaper() {}
513
Ben Wagner8d45a382017-11-16 10:08:28 -0500514bool SkShaper::good() const {
515 return fImpl->fHarfBuzzFont &&
516 fImpl->fBuffer &&
517 fImpl->fTypeface &&
518 fImpl->fBreakIterator;
519}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400520
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500521SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
Hal Canary2a1848d2018-11-26 17:23:24 -0500522 const SkFont& srcPaint,
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500523 const char* utf8,
524 size_t utf8Bytes,
525 bool leftToRight,
526 SkPoint point,
527 SkScalar width) const {
Ben Wagner67e3a302017-09-05 14:46:19 -0400528 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
Ben Wagnera25fbef2017-08-30 13:56:19 -0400529 SkASSERT(builder);
Ben Wagner8d45a382017-11-16 10:08:28 -0500530 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400531 //hb_script_t script = ...
Ben Wagnera25fbef2017-08-30 13:56:19 -0400532
Ben Wagner8d45a382017-11-16 10:08:28 -0500533 SkTArray<ShapedRun> runs;
534{
535 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400536
Ben Wagner8d45a382017-11-16 10:08:28 -0500537 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
538 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
539 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500540 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400541 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500542 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400543
Ben Wagner8d45a382017-11-16 10:08:28 -0500544 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
545 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
546 ScriptRunIterator* script = maybeScript.getMaybeNull();
547 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500548 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400549 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500550 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400551
Ben Wagner8d45a382017-11-16 10:08:28 -0500552 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
553 fImpl->fTypeface,
554 fImpl->fHarfBuzzFont.get(),
555 std::move(fontMgr)));
556 FontRunIterator* font = maybeFont.getMaybeNull();
557 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500558 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400559 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500560 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400561
Ben Wagner8d45a382017-11-16 10:08:28 -0500562 icu::BreakIterator& breakIterator = *fImpl->fBreakIterator;
563 {
564 UErrorCode status = U_ZERO_ERROR;
565 UText utf8UText = UTEXT_INITIALIZER;
566 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
567 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
568 if (U_FAILURE(status)) {
569 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500570 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500571 }
572 breakIterator.setText(&utf8UText, status);
573 //utext_close(&utf8UText);
574 if (U_FAILURE(status)) {
575 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500576 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500577 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400578 }
579
Ben Wagner8d45a382017-11-16 10:08:28 -0500580 const char* utf8Start = nullptr;
581 const char* utf8End = utf8;
582 while (runSegmenter.advanceRuns()) {
583 utf8Start = utf8End;
584 utf8End = runSegmenter.endOfCurrentRun();
585
586 hb_buffer_t* buffer = fImpl->fBuffer.get();
587 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
588 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
589 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
590
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400591 // Add precontext.
592 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
593
Ben Wagner8d45a382017-11-16 10:08:28 -0500594 // Populate the hb_buffer directly with utf8 cluster indexes.
595 const char* utf8Current = utf8Start;
596 while (utf8Current < utf8End) {
597 unsigned int cluster = utf8Current - utf8Start;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400598 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
Ben Wagner8d45a382017-11-16 10:08:28 -0500599 hb_buffer_add(buffer, u, cluster);
600 }
601
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400602 // Add postcontext.
603 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
604
Ben Wagner8d45a382017-11-16 10:08:28 -0500605 size_t utf8runLength = utf8End - utf8Start;
606 if (!SkTFitsIn<int>(utf8runLength)) {
607 SkDebugf("Shaping error: utf8 too long");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500608 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500609 }
610 hb_buffer_set_script(buffer, script->currentScript());
611 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
612 hb_buffer_set_direction(buffer, direction);
613 // TODO: language
614 hb_buffer_guess_segment_properties(buffer);
615 // TODO: features
Hal Canary0dfa2082018-10-31 13:02:49 -0400616 if (!font->currentHBFont()) {
617 continue;
618 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500619 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
620 unsigned len = hb_buffer_get_length(buffer);
621 if (len == 0) {
622 continue;
623 }
624
625 if (direction == HB_DIRECTION_RTL) {
626 // Put the clusters back in logical order.
627 // Note that the advances remain ltr.
628 hb_buffer_reverse(buffer);
629 }
630 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
631 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
632
633 if (!SkTFitsIn<int>(len)) {
634 SkDebugf("Shaping error: too many glyphs");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500635 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500636 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400637
Hal Canary2a1848d2018-11-26 17:23:24 -0500638 SkFont paint(srcPaint);
Ben Wagner8d45a382017-11-16 10:08:28 -0500639 paint.setTypeface(sk_ref_sp(font->currentTypeface()));
640 ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, paint, bidi->currentLevel(),
641 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
642 int scaleX, scaleY;
643 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
Hal Canary2a1848d2018-11-26 17:23:24 -0500644 double textSizeY = run.fPaint.getSize() / scaleY;
645 double textSizeX = run.fPaint.getSize() / scaleX * run.fPaint.getScaleX();
Ben Wagner8d45a382017-11-16 10:08:28 -0500646 for (unsigned i = 0; i < len; i++) {
647 ShapedGlyph& glyph = run.fGlyphs[i];
648 glyph.fID = info[i].codepoint;
649 glyph.fCluster = info[i].cluster;
650 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
651 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
652 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
653 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
654 glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
655 //info->mask safe_to_break;
656 glyph.fMustLineBreakBefore = false;
657 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400658
Ben Wagner8d45a382017-11-16 10:08:28 -0500659 int32_t clusterOffset = utf8Start - utf8;
660 uint32_t previousCluster = 0xFFFFFFFF;
661 for (unsigned i = 0; i < len; ++i) {
662 ShapedGlyph& glyph = run.fGlyphs[i];
663 int32_t glyphCluster = glyph.fCluster + clusterOffset;
664 int32_t breakIteratorCurrent = breakIterator.current();
665 while (breakIteratorCurrent != icu::BreakIterator::DONE &&
666 breakIteratorCurrent < glyphCluster)
667 {
668 breakIteratorCurrent = breakIterator.next();
Ben Wagner2868b782017-08-31 14:12:27 -0400669 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500670 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
671 breakIteratorCurrent == glyphCluster;
672 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400673 }
674 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500675}
676
677// Iterate over the glyphs in logical order to mark line endings.
678{
679 SkScalar widthSoFar = 0;
680 bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
681 bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
682 ShapedRunGlyphIterator previousBreak(runs);
683 ShapedRunGlyphIterator glyphIterator(runs);
684 while (ShapedGlyph* glyph = glyphIterator.current()) {
685 if (canAddBreakNow && glyph->fMayLineBreakBefore) {
686 previousBreakValid = true;
687 previousBreak = glyphIterator;
688 }
689 SkScalar glyphWidth = glyph->fAdvance.fX;
Ben Wagnera900ad52018-08-31 17:48:19 -0400690 // TODO: if the glyph is non-visible it can be added.
Ben Wagner8d45a382017-11-16 10:08:28 -0500691 if (widthSoFar + glyphWidth < width) {
692 widthSoFar += glyphWidth;
693 glyphIterator.next();
694 canAddBreakNow = true;
695 continue;
696 }
697
Ben Wagnera900ad52018-08-31 17:48:19 -0400698 // TODO: for both of these emergency break cases
699 // don't break grapheme clusters and pull in any zero width or non-visible
Ben Wagner8d45a382017-11-16 10:08:28 -0500700 if (widthSoFar == 0) {
701 // Adding just this glyph is too much, just break with this glyph
702 glyphIterator.next();
703 previousBreak = glyphIterator;
704 } else if (!previousBreakValid) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400705 // No break opportunity found yet, just break without this glyph
Ben Wagner8d45a382017-11-16 10:08:28 -0500706 previousBreak = glyphIterator;
707 }
708 glyphIterator = previousBreak;
709 glyph = glyphIterator.current();
710 if (glyph) {
711 glyph->fMustLineBreakBefore = true;
712 }
713 widthSoFar = 0;
714 previousBreakValid = false;
715 canAddBreakNow = false;
716 }
717}
718
719// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500720 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500721{
722 ShapedRunGlyphIterator previousBreak(runs);
723 ShapedRunGlyphIterator glyphIterator(runs);
724 SkScalar maxAscent = 0;
725 SkScalar maxDescent = 0;
726 SkScalar maxLeading = 0;
727 int previousRunIndex = -1;
728 while (glyphIterator.current()) {
729 int runIndex = glyphIterator.fRunIndex;
730 int glyphIndex = glyphIterator.fGlyphIndex;
731 ShapedGlyph* nextGlyph = glyphIterator.next();
732
733 if (previousRunIndex != runIndex) {
Mike Reedb5784ac2018-11-12 09:35:15 -0500734 SkFontMetrics metrics;
Hal Canary2a1848d2018-11-26 17:23:24 -0500735 runs[runIndex].fPaint.getMetrics(&metrics);
Ben Wagner8d45a382017-11-16 10:08:28 -0500736 maxAscent = SkTMin(maxAscent, metrics.fAscent);
737 maxDescent = SkTMax(maxDescent, metrics.fDescent);
738 maxLeading = SkTMax(maxLeading, metrics.fLeading);
739 previousRunIndex = runIndex;
740 }
741
742 // Nothing can be written until the baseline is known.
743 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
744 continue;
745 }
746
747 currentPoint.fY -= maxAscent;
748
749 int numRuns = runIndex - previousBreak.fRunIndex + 1;
750 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
751 for (int i = 0; i < numRuns; ++i) {
752 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
753 }
754 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
755 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
756
757 for (int i = 0; i < numRuns; ++i) {
758 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
759
760 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
761 ? previousBreak.fGlyphIndex
762 : 0;
763 int endGlyphIndex = (logicalIndex == runIndex)
764 ? glyphIndex + 1
765 : runs[logicalIndex].fNumGlyphs;
766 append(builder, runs[logicalIndex], startGlyphIndex, endGlyphIndex, &currentPoint);
767 }
768
769 currentPoint.fY += maxDescent + maxLeading;
770 currentPoint.fX = point.fX;
771 maxAscent = 0;
772 maxDescent = 0;
773 maxLeading = 0;
774 previousRunIndex = -1;
775 previousBreak = glyphIterator;
776 }
777}
778
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500779 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400780}