blob: 0ff0be9829c1474d5ef93abb7780629d10708771 [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"
Mike Reed77f94ea2019-01-22 16:30:40 -050014#include "SkFontMetrics.h"
Ben Wagner17774242018-08-07 14:31:33 -040015#include "SkPoint.h"
16#include "SkRefCnt.h"
17#include "SkScalar.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040018#include "SkShaper.h"
19#include "SkStream.h"
Ben Wagner17774242018-08-07 14:31:33 -040020#include "SkString.h"
21#include "SkTArray.h"
Ben Wagner8d45a382017-11-16 10:08:28 -050022#include "SkTDPQueue.h"
Ben Wagner17774242018-08-07 14:31:33 -040023#include "SkTFitsIn.h"
Ben Wagner8d45a382017-11-16 10:08:28 -050024#include "SkTLazy.h"
Ben Wagnere0001732017-08-31 16:26:26 -040025#include "SkTemplates.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>
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050033#include <unicode/ubrk.h>
Ben Wagner17774242018-08-07 14:31:33 -040034#include <unicode/ubidi.h>
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050035#include <unicode/ustring.h>
Ben Wagner17774242018-08-07 14:31:33 -040036#include <unicode/urename.h>
37#include <unicode/utext.h>
38#include <unicode/utypes.h>
39
40#include <memory>
41#include <utility>
42#include <cstring>
Ben Wagnera25fbef2017-08-30 13:56:19 -040043
Ben Wagnera25fbef2017-08-30 13:56:19 -040044namespace {
45template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050046using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
47using HBFace = resource<hb_face_t , hb_face_destroy >;
48using HBFont = resource<hb_font_t , hb_font_destroy >;
49using HBBuffer = resource<hb_buffer_t , hb_buffer_destroy>;
50using ICUBiDi = resource<UBiDi , ubidi_close >;
51using ICUBrk = resource<UBreakIterator, ubrk_close >;
Ben Wagnera25fbef2017-08-30 13:56:19 -040052
53HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
54 size_t size = asset->getLength();
55 HBBlob blob;
56 if (const void* base = asset->getMemoryBase()) {
57 blob.reset(hb_blob_create((char*)base, SkToUInt(size),
58 HB_MEMORY_MODE_READONLY, asset.release(),
59 [](void* p) { delete (SkStreamAsset*)p; }));
60 } else {
61 // SkDebugf("Extra SkStreamAsset copy\n");
62 void* ptr = size ? sk_malloc_throw(size) : nullptr;
63 asset->read(ptr, size);
64 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
65 HB_MEMORY_MODE_READONLY, ptr, sk_free));
66 }
67 SkASSERT(blob);
68 hb_blob_make_immutable(blob.get());
69 return blob;
70}
Ben Wagnera25fbef2017-08-30 13:56:19 -040071
Ben Wagner8d45a382017-11-16 10:08:28 -050072HBFont create_hb_font(SkTypeface* tf) {
Hal Canary0dfa2082018-10-31 13:02:49 -040073 if (!tf) {
74 return nullptr;
75 }
Ben Wagnera25fbef2017-08-30 13:56:19 -040076 int index;
Hal Canaryddef43f2018-11-16 10:53:51 -050077 std::unique_ptr<SkStreamAsset> typefaceAsset(tf->openStream(&index));
78 if (!typefaceAsset) {
79 SkString name;
80 tf->getFamilyName(&name);
81 SkDebugf("Typeface '%s' has no data :(\n", name.c_str());
82 return nullptr;
83 }
84 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
Ben Wagnera25fbef2017-08-30 13:56:19 -040085 HBFace face(hb_face_create(blob.get(), (unsigned)index));
86 SkASSERT(face);
87 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040088 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040089 }
90 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -040091 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -040092
Ben Wagnere0001732017-08-31 16:26:26 -040093 HBFont font(hb_font_create(face.get()));
94 SkASSERT(font);
95 if (!font) {
96 return nullptr;
97 }
Ben Wagnere0001732017-08-31 16:26:26 -040098 hb_ot_font_set_funcs(font.get());
99 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
100 if (axis_count > 0) {
101 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
102 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
103 hb_font_set_variations(font.get(),
104 reinterpret_cast<hb_variation_t*>(axis_values.get()),
105 axis_count);
106 }
107 }
108 return font;
109}
110
Hal Canaryf107a2f2018-07-25 16:52:48 -0400111/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
112static inline SkUnichar utf8_next(const char** ptr, const char* end) {
113 SkUnichar val = SkUTF::NextUTF8(ptr, end);
114 if (val < 0) {
115 return 0xFFFD; // REPLACEMENT CHARACTER
116 }
117 return val;
118}
119
Ben Wagner8d45a382017-11-16 10:08:28 -0500120class RunIterator {
121public:
122 virtual ~RunIterator() {}
123 virtual void consume() = 0;
124 // Pointer one past the last (utf8) element in the current run.
125 virtual const char* endOfCurrentRun() const = 0;
126 virtual bool atEnd() const = 0;
127 bool operator<(const RunIterator& that) const {
128 return this->endOfCurrentRun() < that.endOfCurrentRun();
129 }
130};
131
132class BiDiRunIterator : public RunIterator {
133public:
134 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
135 SkTLazy<BiDiRunIterator> ret;
136
137 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
138 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
139 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
140 SkDebugf("Bidi error: text too long");
141 return ret;
142 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500143
144 UErrorCode status = U_ZERO_ERROR;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500145
146 // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
147 int32_t utf16Units;
148 u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
149 status = U_ZERO_ERROR;
150 std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
151 u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
152 if (U_FAILURE(status)) {
153 SkDebugf("Invalid utf8 input: %s", u_errorName(status));
154 return ret;
155 }
156
157 ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500158 if (U_FAILURE(status)) {
159 SkDebugf("Bidi error: %s", u_errorName(status));
160 return ret;
161 }
162 SkASSERT(bidi);
163
164 // The required lifetime of utf16 isn't well documented.
165 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500166 ubidi_setPara(bidi.get(), utf16.get(), utf16Units, level, nullptr, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500167 if (U_FAILURE(status)) {
168 SkDebugf("Bidi error: %s", u_errorName(status));
169 return ret;
170 }
171
Hal Canary4014ba62018-07-24 11:33:21 -0400172 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500173 return ret;
174 }
Hal Canary4014ba62018-07-24 11:33:21 -0400175 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500176 : fBidi(std::move(bidi))
177 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400178 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500179 , fUTF16LogicalPosition(0)
180 , fLevel(UBIDI_DEFAULT_LTR)
181 {}
182 void consume() override {
183 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
184 int32_t endPosition = ubidi_getLength(fBidi.get());
185 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400186 SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
187 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500188 UBiDiLevel level;
189 while (fUTF16LogicalPosition < endPosition) {
190 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
191 if (level != fLevel) {
192 break;
193 }
Hal Canaryf107a2f2018-07-25 16:52:48 -0400194 u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
195 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500196 }
197 }
198 const char* endOfCurrentRun() const override {
199 return fEndOfCurrentRun;
200 }
201 bool atEnd() const override {
202 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
203 }
204
205 UBiDiLevel currentLevel() const {
206 return fLevel;
207 }
208private:
209 ICUBiDi fBidi;
210 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400211 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500212 int32_t fUTF16LogicalPosition;
213 UBiDiLevel fLevel;
214};
215
216class ScriptRunIterator : public RunIterator {
217public:
218 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
219 hb_unicode_funcs_t* hbUnicode)
220 {
221 SkTLazy<ScriptRunIterator> ret;
222 ret.init(utf8, utf8Bytes, hbUnicode);
223 return ret;
224 }
225 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
226 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
227 , fHBUnicode(hbUnicode)
228 , fCurrentScript(HB_SCRIPT_UNKNOWN)
229 {}
230 void consume() override {
231 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400232 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500233 fCurrentScript = hb_unicode_script(fHBUnicode, u);
234 while (fCurrent < fEnd) {
235 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400236 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500237 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
238 if (script != fCurrentScript) {
239 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
240 fCurrentScript = script;
241 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
242 continue;
243 } else {
244 fCurrent = prev;
245 break;
246 }
247 }
248 }
249 if (fCurrentScript == HB_SCRIPT_INHERITED) {
250 fCurrentScript = HB_SCRIPT_COMMON;
251 }
252 }
253 const char* endOfCurrentRun() const override {
254 return fCurrent;
255 }
256 bool atEnd() const override {
257 return fCurrent == fEnd;
258 }
259
260 hb_script_t currentScript() const {
261 return fCurrentScript;
262 }
263private:
264 const char* fCurrent;
265 const char* fEnd;
266 hb_unicode_funcs_t* fHBUnicode;
267 hb_script_t fCurrentScript;
268};
269
270class FontRunIterator : public RunIterator {
271public:
272 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
273 sk_sp<SkTypeface> typeface,
274 hb_font_t* hbFace,
275 sk_sp<SkFontMgr> fallbackMgr)
276 {
277 SkTLazy<FontRunIterator> ret;
278 ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
279 return ret;
280 }
281 FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
282 hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
283 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
284 , fFallbackMgr(std::move(fallbackMgr))
285 , fHBFont(hbFace), fTypeface(std::move(typeface))
286 , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
287 , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
288 {}
289 void consume() override {
290 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400291 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500292 // If the starting typeface can handle this character, use it.
293 if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400294 fCurrentTypeface = fTypeface.get();
295 fCurrentHBFont = fHBFont;
296 // If the current fallback can handle this character, use it.
297 } else if (fFallbackTypeface &&
298 fFallbackTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
299 {
300 fCurrentTypeface = fFallbackTypeface.get();
301 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500302 // If not, try to find a fallback typeface
303 } else {
304 fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
305 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
Ben Wagner8d45a382017-11-16 10:08:28 -0500306 fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
307 fCurrentTypeface = fFallbackTypeface.get();
308 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500309 }
310
311 while (fCurrent < fEnd) {
312 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400313 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500314
Ben Wagnera900ad52018-08-31 17:48:19 -0400315 // If not using initial typeface and initial typeface has this character, stop fallback.
316 if (fCurrentTypeface != fTypeface.get() &&
Ben Wagner8d45a382017-11-16 10:08:28 -0500317 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
318 {
319 fCurrent = prev;
320 return;
321 }
322 // If the current typeface cannot handle this character, stop using it.
323 if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
324 fCurrent = prev;
325 return;
326 }
327 }
328 }
329 const char* endOfCurrentRun() const override {
330 return fCurrent;
331 }
332 bool atEnd() const override {
333 return fCurrent == fEnd;
334 }
335
336 SkTypeface* currentTypeface() const {
337 return fCurrentTypeface;
338 }
339 hb_font_t* currentHBFont() const {
340 return fCurrentHBFont;
341 }
342private:
343 const char* fCurrent;
344 const char* fEnd;
345 sk_sp<SkFontMgr> fFallbackMgr;
346 hb_font_t* fHBFont;
347 sk_sp<SkTypeface> fTypeface;
348 HBFont fFallbackHBFont;
349 sk_sp<SkTypeface> fFallbackTypeface;
350 hb_font_t* fCurrentHBFont;
351 SkTypeface* fCurrentTypeface;
352};
353
354class RunIteratorQueue {
355public:
356 void insert(RunIterator* runIterator) {
357 fRunIterators.insert(runIterator);
358 }
359
360 bool advanceRuns() {
361 const RunIterator* leastRun = fRunIterators.peek();
362 if (leastRun->atEnd()) {
363 SkASSERT(this->allRunsAreAtEnd());
364 return false;
365 }
366 const char* leastEnd = leastRun->endOfCurrentRun();
367 RunIterator* currentRun = nullptr;
368 SkDEBUGCODE(const char* previousEndOfCurrentRun);
369 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
370 fRunIterators.pop();
371 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
372 currentRun->consume();
373 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
374 fRunIterators.insert(currentRun);
375 }
376 return true;
377 }
378
379 const char* endOfCurrentRun() const {
380 return fRunIterators.peek()->endOfCurrentRun();
381 }
382
383private:
384 bool allRunsAreAtEnd() const {
385 for (int i = 0; i < fRunIterators.count(); ++i) {
386 if (!fRunIterators.at(i)->atEnd()) {
387 return false;
388 }
389 }
390 return true;
391 }
392
393 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
394 return *a < *b;
395 }
396 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
397};
398
399struct ShapedGlyph {
400 SkGlyphID fID;
401 uint32_t fCluster;
402 SkPoint fOffset;
403 SkVector fAdvance;
404 bool fMayLineBreakBefore;
405 bool fMustLineBreakBefore;
406 bool fHasVisual;
407};
408struct ShapedRun {
Mike Reed6d595682018-12-05 17:28:14 -0500409 ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkFont& font,
Ben Wagner8d45a382017-11-16 10:08:28 -0500410 UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
Mike Reed6d595682018-12-05 17:28:14 -0500411 : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fFont(font)
Ben Wagner8d45a382017-11-16 10:08:28 -0500412 , fLevel(level), fGlyphs(std::move(glyphs))
413 {}
414
415 const char* fUtf8Start;
416 const char* fUtf8End;
417 int fNumGlyphs;
Mike Reed6d595682018-12-05 17:28:14 -0500418 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500419 UBiDiLevel fLevel;
420 std::unique_ptr<ShapedGlyph[]> fGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500421 SkVector fAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500422};
423
424static constexpr bool is_LTR(UBiDiLevel level) {
425 return (level & 1) == 0;
426}
427
Florin Malita950243d2019-01-11 11:08:35 -0500428static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
429 const ShapedRun& run, int start, int end,
Florin Malita9867f612018-12-12 10:54:49 -0500430 SkPoint* p) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500431 unsigned len = end - start;
Florin Malita9867f612018-12-12 10:54:49 -0500432
Florin Malita950243d2019-01-11 11:08:35 -0500433 const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8End - run.fUtf8Start);
Florin Malita9867f612018-12-12 10:54:49 -0500434 SkASSERT(buffer.glyphs);
435 SkASSERT(buffer.positions);
436
437 if (buffer.utf8text) {
438 memcpy(buffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
439 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500440
441 for (unsigned i = 0; i < len; i++) {
442 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
443 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
Florin Malita9867f612018-12-12 10:54:49 -0500444 buffer.glyphs[i] = glyph.fID;
445 buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
446 if (buffer.clusters) {
447 buffer.clusters[i] = glyph.fCluster;
448 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500449 p->fX += glyph.fAdvance.fX;
450 p->fY += glyph.fAdvance.fY;
451 }
452}
453
454struct ShapedRunGlyphIterator {
455 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
456 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
457 { }
458
459 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
460 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
461 bool operator==(const ShapedRunGlyphIterator& that) const {
462 return fRuns == that.fRuns &&
463 fRunIndex == that.fRunIndex &&
464 fGlyphIndex == that.fGlyphIndex;
465 }
466 bool operator!=(const ShapedRunGlyphIterator& that) const {
467 return fRuns != that.fRuns ||
468 fRunIndex != that.fRunIndex ||
469 fGlyphIndex != that.fGlyphIndex;
470 }
471
472 ShapedGlyph* next() {
473 const SkTArray<ShapedRun>& runs = *fRuns;
474 SkASSERT(fRunIndex < runs.count());
475 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
476
477 ++fGlyphIndex;
478 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
479 fGlyphIndex = 0;
480 ++fRunIndex;
481 if (fRunIndex >= runs.count()) {
482 return nullptr;
483 }
484 }
485 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
486 }
487
488 ShapedGlyph* current() {
489 const SkTArray<ShapedRun>& runs = *fRuns;
490 if (fRunIndex >= runs.count()) {
491 return nullptr;
492 }
493 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
494 }
495
496 const SkTArray<ShapedRun>* fRuns;
497 int fRunIndex;
498 int fGlyphIndex;
499};
500
501} // namespace
502
503struct SkShaper::Impl {
504 HBFont fHarfBuzzFont;
505 HBBuffer fBuffer;
506 sk_sp<SkTypeface> fTypeface;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500507 ICUBrk fBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500508};
509
Ben Wagnere0001732017-08-31 16:26:26 -0400510SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary0e07ad72018-02-08 13:06:56 -0500511 SkOnce once;
512 once([] { SkLoadICU(); });
513
Ben Wagnere0001732017-08-31 16:26:26 -0400514 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
515 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Florin Malitaa4e1a632019-01-22 16:27:01 -0500516 if (!fImpl->fHarfBuzzFont) {
517 SkDebugf("create_hb_font failed!\n");
518 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400519 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500520 SkASSERT(fImpl->fBuffer);
521
Ben Wagner8d45a382017-11-16 10:08:28 -0500522 UErrorCode status = U_ZERO_ERROR;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500523 fImpl->fBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500524 if (U_FAILURE(status)) {
525 SkDebugf("Could not create break iterator: %s", u_errorName(status));
526 SK_ABORT("");
527 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400528}
529
530SkShaper::~SkShaper() {}
531
Ben Wagner8d45a382017-11-16 10:08:28 -0500532bool SkShaper::good() const {
533 return fImpl->fHarfBuzzFont &&
534 fImpl->fBuffer &&
535 fImpl->fTypeface &&
536 fImpl->fBreakIterator;
537}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400538
Florin Malita950243d2019-01-11 11:08:35 -0500539SkPoint SkShaper::shape(RunHandler* handler,
Kevin Lubick57abfe92019-01-28 13:15:51 -0500540 const SkFont& srcFont,
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500541 const char* utf8,
542 size_t utf8Bytes,
543 bool leftToRight,
544 SkPoint point,
545 SkScalar width) const {
Ben Wagner67e3a302017-09-05 14:46:19 -0400546 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
Florin Malita9867f612018-12-12 10:54:49 -0500547 SkASSERT(handler);
Ben Wagner8d45a382017-11-16 10:08:28 -0500548 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400549 //hb_script_t script = ...
Ben Wagnera25fbef2017-08-30 13:56:19 -0400550
Ben Wagner8d45a382017-11-16 10:08:28 -0500551 SkTArray<ShapedRun> runs;
552{
553 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400554
Ben Wagner8d45a382017-11-16 10:08:28 -0500555 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
556 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
557 if (!bidi) {
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(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400561
Ben Wagner8d45a382017-11-16 10:08:28 -0500562 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
563 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
564 ScriptRunIterator* script = maybeScript.getMaybeNull();
565 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500566 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400567 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500568 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400569
Ben Wagner8d45a382017-11-16 10:08:28 -0500570 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
571 fImpl->fTypeface,
572 fImpl->fHarfBuzzFont.get(),
573 std::move(fontMgr)));
574 FontRunIterator* font = maybeFont.getMaybeNull();
575 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500576 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400577 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500578 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400579
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500580 UBreakIterator& breakIterator = *fImpl->fBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500581 {
582 UErrorCode status = U_ZERO_ERROR;
583 UText utf8UText = UTEXT_INITIALIZER;
584 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
585 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
586 if (U_FAILURE(status)) {
587 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500588 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500589 }
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500590 ubrk_setUText(&breakIterator, &utf8UText, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500591 //utext_close(&utf8UText);
592 if (U_FAILURE(status)) {
593 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500594 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500595 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400596 }
597
Ben Wagner8d45a382017-11-16 10:08:28 -0500598 const char* utf8Start = nullptr;
599 const char* utf8End = utf8;
600 while (runSegmenter.advanceRuns()) {
601 utf8Start = utf8End;
602 utf8End = runSegmenter.endOfCurrentRun();
603
604 hb_buffer_t* buffer = fImpl->fBuffer.get();
605 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
606 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
607 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
608
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400609 // Add precontext.
610 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
611
Ben Wagner8d45a382017-11-16 10:08:28 -0500612 // Populate the hb_buffer directly with utf8 cluster indexes.
613 const char* utf8Current = utf8Start;
614 while (utf8Current < utf8End) {
615 unsigned int cluster = utf8Current - utf8Start;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400616 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
Ben Wagner8d45a382017-11-16 10:08:28 -0500617 hb_buffer_add(buffer, u, cluster);
618 }
619
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400620 // Add postcontext.
621 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
622
Ben Wagner8d45a382017-11-16 10:08:28 -0500623 size_t utf8runLength = utf8End - utf8Start;
624 if (!SkTFitsIn<int>(utf8runLength)) {
625 SkDebugf("Shaping error: utf8 too long");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500626 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500627 }
628 hb_buffer_set_script(buffer, script->currentScript());
629 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
630 hb_buffer_set_direction(buffer, direction);
631 // TODO: language
632 hb_buffer_guess_segment_properties(buffer);
633 // TODO: features
Hal Canary0dfa2082018-10-31 13:02:49 -0400634 if (!font->currentHBFont()) {
635 continue;
636 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500637 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
638 unsigned len = hb_buffer_get_length(buffer);
639 if (len == 0) {
640 continue;
641 }
642
643 if (direction == HB_DIRECTION_RTL) {
644 // Put the clusters back in logical order.
645 // Note that the advances remain ltr.
646 hb_buffer_reverse(buffer);
647 }
648 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
649 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
650
651 if (!SkTFitsIn<int>(len)) {
652 SkDebugf("Shaping error: too many glyphs");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500653 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500654 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400655
Kevin Lubick57abfe92019-01-28 13:15:51 -0500656 SkFont runFont(srcFont);
657 runFont.setTypeface(sk_ref_sp(font->currentTypeface()));
658 ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, runFont, bidi->currentLevel(),
Ben Wagner8d45a382017-11-16 10:08:28 -0500659 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
660 int scaleX, scaleY;
661 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
Mike Reed6d595682018-12-05 17:28:14 -0500662 double textSizeY = run.fFont.getSize() / scaleY;
663 double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
Florin Malita950243d2019-01-11 11:08:35 -0500664 SkVector runAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500665 for (unsigned i = 0; i < len; i++) {
666 ShapedGlyph& glyph = run.fGlyphs[i];
667 glyph.fID = info[i].codepoint;
668 glyph.fCluster = info[i].cluster;
669 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
670 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
671 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
672 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
673 glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
674 //info->mask safe_to_break;
675 glyph.fMustLineBreakBefore = false;
Florin Malita950243d2019-01-11 11:08:35 -0500676
677 runAdvance += glyph.fAdvance;
Ben Wagner8d45a382017-11-16 10:08:28 -0500678 }
Florin Malita950243d2019-01-11 11:08:35 -0500679 run.fAdvance = runAdvance;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400680
Ben Wagner8d45a382017-11-16 10:08:28 -0500681 int32_t clusterOffset = utf8Start - utf8;
682 uint32_t previousCluster = 0xFFFFFFFF;
683 for (unsigned i = 0; i < len; ++i) {
684 ShapedGlyph& glyph = run.fGlyphs[i];
685 int32_t glyphCluster = glyph.fCluster + clusterOffset;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500686 int32_t breakIteratorCurrent = ubrk_current(&breakIterator);
687 while (breakIteratorCurrent != UBRK_DONE &&
Ben Wagner8d45a382017-11-16 10:08:28 -0500688 breakIteratorCurrent < glyphCluster)
689 {
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500690 breakIteratorCurrent = ubrk_next(&breakIterator);
Ben Wagner2868b782017-08-31 14:12:27 -0400691 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500692 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
693 breakIteratorCurrent == glyphCluster;
694 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400695 }
696 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500697}
698
699// Iterate over the glyphs in logical order to mark line endings.
700{
701 SkScalar widthSoFar = 0;
702 bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
703 bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
704 ShapedRunGlyphIterator previousBreak(runs);
705 ShapedRunGlyphIterator glyphIterator(runs);
706 while (ShapedGlyph* glyph = glyphIterator.current()) {
707 if (canAddBreakNow && glyph->fMayLineBreakBefore) {
708 previousBreakValid = true;
709 previousBreak = glyphIterator;
710 }
711 SkScalar glyphWidth = glyph->fAdvance.fX;
Ben Wagnera900ad52018-08-31 17:48:19 -0400712 // TODO: if the glyph is non-visible it can be added.
Ben Wagner8d45a382017-11-16 10:08:28 -0500713 if (widthSoFar + glyphWidth < width) {
714 widthSoFar += glyphWidth;
715 glyphIterator.next();
716 canAddBreakNow = true;
717 continue;
718 }
719
Ben Wagnera900ad52018-08-31 17:48:19 -0400720 // TODO: for both of these emergency break cases
721 // don't break grapheme clusters and pull in any zero width or non-visible
Ben Wagner8d45a382017-11-16 10:08:28 -0500722 if (widthSoFar == 0) {
723 // Adding just this glyph is too much, just break with this glyph
724 glyphIterator.next();
725 previousBreak = glyphIterator;
726 } else if (!previousBreakValid) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400727 // No break opportunity found yet, just break without this glyph
Ben Wagner8d45a382017-11-16 10:08:28 -0500728 previousBreak = glyphIterator;
729 }
730 glyphIterator = previousBreak;
731 glyph = glyphIterator.current();
732 if (glyph) {
733 glyph->fMustLineBreakBefore = true;
734 }
735 widthSoFar = 0;
736 previousBreakValid = false;
737 canAddBreakNow = false;
738 }
739}
740
741// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500742 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500743{
744 ShapedRunGlyphIterator previousBreak(runs);
745 ShapedRunGlyphIterator glyphIterator(runs);
746 SkScalar maxAscent = 0;
747 SkScalar maxDescent = 0;
748 SkScalar maxLeading = 0;
749 int previousRunIndex = -1;
Florin Malita950243d2019-01-11 11:08:35 -0500750 size_t lineIndex = 0;
Ben Wagner8d45a382017-11-16 10:08:28 -0500751 while (glyphIterator.current()) {
752 int runIndex = glyphIterator.fRunIndex;
753 int glyphIndex = glyphIterator.fGlyphIndex;
754 ShapedGlyph* nextGlyph = glyphIterator.next();
755
756 if (previousRunIndex != runIndex) {
Mike Reedb5784ac2018-11-12 09:35:15 -0500757 SkFontMetrics metrics;
Mike Reed6d595682018-12-05 17:28:14 -0500758 runs[runIndex].fFont.getMetrics(&metrics);
Ben Wagner8d45a382017-11-16 10:08:28 -0500759 maxAscent = SkTMin(maxAscent, metrics.fAscent);
760 maxDescent = SkTMax(maxDescent, metrics.fDescent);
761 maxLeading = SkTMax(maxLeading, metrics.fLeading);
762 previousRunIndex = runIndex;
763 }
764
765 // Nothing can be written until the baseline is known.
766 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
767 continue;
768 }
769
770 currentPoint.fY -= maxAscent;
771
772 int numRuns = runIndex - previousBreak.fRunIndex + 1;
773 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
774 for (int i = 0; i < numRuns; ++i) {
775 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
776 }
777 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
778 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
779
780 for (int i = 0; i < numRuns; ++i) {
781 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
782
783 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
784 ? previousBreak.fGlyphIndex
785 : 0;
786 int endGlyphIndex = (logicalIndex == runIndex)
787 ? glyphIndex + 1
788 : runs[logicalIndex].fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500789
790 const auto& run = runs[logicalIndex];
791 const RunHandler::RunInfo info = {
792 lineIndex,
793 run.fAdvance,
794 maxAscent,
795 maxDescent,
796 maxLeading,
797 };
798 append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
Ben Wagner8d45a382017-11-16 10:08:28 -0500799 }
800
801 currentPoint.fY += maxDescent + maxLeading;
802 currentPoint.fX = point.fX;
803 maxAscent = 0;
804 maxDescent = 0;
805 maxLeading = 0;
806 previousRunIndex = -1;
Florin Malita950243d2019-01-11 11:08:35 -0500807 ++lineIndex;
Ben Wagner8d45a382017-11-16 10:08:28 -0500808 previousBreak = glyphIterator;
809 }
810}
811
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500812 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400813}