blob: 07323caabcbacff553023f50b00204c0fa92705a [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"
Ben Wagner17774242018-08-07 14:31:33 -040010#include "SkMalloc.h"
Hal Canary0e07ad72018-02-08 13:06:56 -050011#include "SkOnce.h"
Hal Canary2a1848d2018-11-26 17:23:24 -050012#include "SkFont.h"
Mike Reed77f94ea2019-01-22 16:30:40 -050013#include "SkFontMetrics.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"
Hal Canaryc640d0d2018-06-13 09:59:02 -040025#include "SkTo.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040026#include "SkTypeface.h"
Ben Wagner17774242018-08-07 14:31:33 -040027#include "SkTypes.h"
28#include "SkUTF.h"
29
30#include <hb.h>
31#include <hb-ot.h>
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050032#include <unicode/ubrk.h>
Ben Wagner17774242018-08-07 14:31:33 -040033#include <unicode/ubidi.h>
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050034#include <unicode/ustring.h>
Ben Wagner17774242018-08-07 14:31:33 -040035#include <unicode/urename.h>
36#include <unicode/utext.h>
37#include <unicode/utypes.h>
38
39#include <memory>
40#include <utility>
41#include <cstring>
Ben Wagnera25fbef2017-08-30 13:56:19 -040042
Hal Canary32498f02019-02-04 15:36:31 -050043#ifdef SK_USING_THIRD_PARTY_ICU
44#include "SkLoadICU.h"
45#else
46static inline void SkLoadICU() {}
47#endif // SK_USING_THIRD_PARTY_ICU
48
Ben Wagnera25fbef2017-08-30 13:56:19 -040049namespace {
50template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050051using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
52using HBFace = resource<hb_face_t , hb_face_destroy >;
53using HBFont = resource<hb_font_t , hb_font_destroy >;
54using HBBuffer = resource<hb_buffer_t , hb_buffer_destroy>;
55using ICUBiDi = resource<UBiDi , ubidi_close >;
56using ICUBrk = resource<UBreakIterator, ubrk_close >;
Ben Wagnera25fbef2017-08-30 13:56:19 -040057
58HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
59 size_t size = asset->getLength();
60 HBBlob blob;
61 if (const void* base = asset->getMemoryBase()) {
62 blob.reset(hb_blob_create((char*)base, SkToUInt(size),
63 HB_MEMORY_MODE_READONLY, asset.release(),
64 [](void* p) { delete (SkStreamAsset*)p; }));
65 } else {
66 // SkDebugf("Extra SkStreamAsset copy\n");
67 void* ptr = size ? sk_malloc_throw(size) : nullptr;
68 asset->read(ptr, size);
69 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
70 HB_MEMORY_MODE_READONLY, ptr, sk_free));
71 }
72 SkASSERT(blob);
73 hb_blob_make_immutable(blob.get());
74 return blob;
75}
Ben Wagnera25fbef2017-08-30 13:56:19 -040076
Ben Wagner8d45a382017-11-16 10:08:28 -050077HBFont create_hb_font(SkTypeface* tf) {
Hal Canary0dfa2082018-10-31 13:02:49 -040078 if (!tf) {
79 return nullptr;
80 }
Ben Wagnera25fbef2017-08-30 13:56:19 -040081 int index;
Hal Canaryddef43f2018-11-16 10:53:51 -050082 std::unique_ptr<SkStreamAsset> typefaceAsset(tf->openStream(&index));
83 if (!typefaceAsset) {
84 SkString name;
85 tf->getFamilyName(&name);
86 SkDebugf("Typeface '%s' has no data :(\n", name.c_str());
87 return nullptr;
88 }
89 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
Ben Wagnera25fbef2017-08-30 13:56:19 -040090 HBFace face(hb_face_create(blob.get(), (unsigned)index));
91 SkASSERT(face);
92 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040093 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040094 }
95 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -040096 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -040097
Ben Wagnere0001732017-08-31 16:26:26 -040098 HBFont font(hb_font_create(face.get()));
99 SkASSERT(font);
100 if (!font) {
101 return nullptr;
102 }
Ben Wagnere0001732017-08-31 16:26:26 -0400103 hb_ot_font_set_funcs(font.get());
104 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
105 if (axis_count > 0) {
106 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
107 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
108 hb_font_set_variations(font.get(),
109 reinterpret_cast<hb_variation_t*>(axis_values.get()),
110 axis_count);
111 }
112 }
113 return font;
114}
115
Hal Canaryf107a2f2018-07-25 16:52:48 -0400116/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
117static inline SkUnichar utf8_next(const char** ptr, const char* end) {
118 SkUnichar val = SkUTF::NextUTF8(ptr, end);
119 if (val < 0) {
120 return 0xFFFD; // REPLACEMENT CHARACTER
121 }
122 return val;
123}
124
Ben Wagner8d45a382017-11-16 10:08:28 -0500125class RunIterator {
126public:
127 virtual ~RunIterator() {}
128 virtual void consume() = 0;
129 // Pointer one past the last (utf8) element in the current run.
130 virtual const char* endOfCurrentRun() const = 0;
131 virtual bool atEnd() const = 0;
132 bool operator<(const RunIterator& that) const {
133 return this->endOfCurrentRun() < that.endOfCurrentRun();
134 }
135};
136
137class BiDiRunIterator : public RunIterator {
138public:
139 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
140 SkTLazy<BiDiRunIterator> ret;
141
142 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
143 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
144 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
145 SkDebugf("Bidi error: text too long");
146 return ret;
147 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500148
149 UErrorCode status = U_ZERO_ERROR;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500150
151 // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
152 int32_t utf16Units;
153 u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
154 status = U_ZERO_ERROR;
155 std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
156 u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
157 if (U_FAILURE(status)) {
158 SkDebugf("Invalid utf8 input: %s", u_errorName(status));
159 return ret;
160 }
161
162 ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500163 if (U_FAILURE(status)) {
164 SkDebugf("Bidi error: %s", u_errorName(status));
165 return ret;
166 }
167 SkASSERT(bidi);
168
169 // The required lifetime of utf16 isn't well documented.
170 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500171 ubidi_setPara(bidi.get(), utf16.get(), utf16Units, level, nullptr, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500172 if (U_FAILURE(status)) {
173 SkDebugf("Bidi error: %s", u_errorName(status));
174 return ret;
175 }
176
Hal Canary4014ba62018-07-24 11:33:21 -0400177 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500178 return ret;
179 }
Hal Canary4014ba62018-07-24 11:33:21 -0400180 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500181 : fBidi(std::move(bidi))
182 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400183 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500184 , fUTF16LogicalPosition(0)
185 , fLevel(UBIDI_DEFAULT_LTR)
186 {}
187 void consume() override {
188 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
189 int32_t endPosition = ubidi_getLength(fBidi.get());
190 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400191 SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
192 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500193 UBiDiLevel level;
194 while (fUTF16LogicalPosition < endPosition) {
195 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
196 if (level != fLevel) {
197 break;
198 }
Hal Canaryf107a2f2018-07-25 16:52:48 -0400199 u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
200 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500201 }
202 }
203 const char* endOfCurrentRun() const override {
204 return fEndOfCurrentRun;
205 }
206 bool atEnd() const override {
207 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
208 }
209
210 UBiDiLevel currentLevel() const {
211 return fLevel;
212 }
213private:
214 ICUBiDi fBidi;
215 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400216 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500217 int32_t fUTF16LogicalPosition;
218 UBiDiLevel fLevel;
219};
220
221class ScriptRunIterator : public RunIterator {
222public:
223 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
224 hb_unicode_funcs_t* hbUnicode)
225 {
226 SkTLazy<ScriptRunIterator> ret;
227 ret.init(utf8, utf8Bytes, hbUnicode);
228 return ret;
229 }
230 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
231 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
232 , fHBUnicode(hbUnicode)
233 , fCurrentScript(HB_SCRIPT_UNKNOWN)
234 {}
235 void consume() override {
236 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400237 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500238 fCurrentScript = hb_unicode_script(fHBUnicode, u);
239 while (fCurrent < fEnd) {
240 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400241 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500242 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
243 if (script != fCurrentScript) {
244 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
245 fCurrentScript = script;
246 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
247 continue;
248 } else {
249 fCurrent = prev;
250 break;
251 }
252 }
253 }
254 if (fCurrentScript == HB_SCRIPT_INHERITED) {
255 fCurrentScript = HB_SCRIPT_COMMON;
256 }
257 }
258 const char* endOfCurrentRun() const override {
259 return fCurrent;
260 }
261 bool atEnd() const override {
262 return fCurrent == fEnd;
263 }
264
265 hb_script_t currentScript() const {
266 return fCurrentScript;
267 }
268private:
269 const char* fCurrent;
270 const char* fEnd;
271 hb_unicode_funcs_t* fHBUnicode;
272 hb_script_t fCurrentScript;
273};
274
275class FontRunIterator : public RunIterator {
276public:
277 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
278 sk_sp<SkTypeface> typeface,
279 hb_font_t* hbFace,
280 sk_sp<SkFontMgr> fallbackMgr)
281 {
282 SkTLazy<FontRunIterator> ret;
283 ret.init(utf8, utf8Bytes, std::move(typeface), hbFace, std::move(fallbackMgr));
284 return ret;
285 }
286 FontRunIterator(const char* utf8, size_t utf8Bytes, sk_sp<SkTypeface> typeface,
287 hb_font_t* hbFace, sk_sp<SkFontMgr> fallbackMgr)
288 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
289 , fFallbackMgr(std::move(fallbackMgr))
290 , fHBFont(hbFace), fTypeface(std::move(typeface))
291 , fFallbackHBFont(nullptr), fFallbackTypeface(nullptr)
292 , fCurrentHBFont(fHBFont), fCurrentTypeface(fTypeface.get())
293 {}
294 void consume() override {
295 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400296 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500297 // If the starting typeface can handle this character, use it.
298 if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400299 fCurrentTypeface = fTypeface.get();
300 fCurrentHBFont = fHBFont;
301 // If the current fallback can handle this character, use it.
302 } else if (fFallbackTypeface &&
303 fFallbackTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
304 {
305 fCurrentTypeface = fFallbackTypeface.get();
306 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500307 // If not, try to find a fallback typeface
308 } else {
309 fFallbackTypeface.reset(fFallbackMgr->matchFamilyStyleCharacter(
310 nullptr, fTypeface->fontStyle(), nullptr, 0, u));
Ben Wagner8d45a382017-11-16 10:08:28 -0500311 fFallbackHBFont = create_hb_font(fFallbackTypeface.get());
312 fCurrentTypeface = fFallbackTypeface.get();
313 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500314 }
315
316 while (fCurrent < fEnd) {
317 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400318 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500319
Ben Wagnera900ad52018-08-31 17:48:19 -0400320 // If not using initial typeface and initial typeface has this character, stop fallback.
321 if (fCurrentTypeface != fTypeface.get() &&
Ben Wagner8d45a382017-11-16 10:08:28 -0500322 fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
323 {
324 fCurrent = prev;
325 return;
326 }
327 // If the current typeface cannot handle this character, stop using it.
328 if (!fCurrentTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
329 fCurrent = prev;
330 return;
331 }
332 }
333 }
334 const char* endOfCurrentRun() const override {
335 return fCurrent;
336 }
337 bool atEnd() const override {
338 return fCurrent == fEnd;
339 }
340
341 SkTypeface* currentTypeface() const {
342 return fCurrentTypeface;
343 }
344 hb_font_t* currentHBFont() const {
345 return fCurrentHBFont;
346 }
347private:
348 const char* fCurrent;
349 const char* fEnd;
350 sk_sp<SkFontMgr> fFallbackMgr;
351 hb_font_t* fHBFont;
352 sk_sp<SkTypeface> fTypeface;
353 HBFont fFallbackHBFont;
354 sk_sp<SkTypeface> fFallbackTypeface;
355 hb_font_t* fCurrentHBFont;
356 SkTypeface* fCurrentTypeface;
357};
358
359class RunIteratorQueue {
360public:
361 void insert(RunIterator* runIterator) {
362 fRunIterators.insert(runIterator);
363 }
364
365 bool advanceRuns() {
366 const RunIterator* leastRun = fRunIterators.peek();
367 if (leastRun->atEnd()) {
368 SkASSERT(this->allRunsAreAtEnd());
369 return false;
370 }
371 const char* leastEnd = leastRun->endOfCurrentRun();
372 RunIterator* currentRun = nullptr;
373 SkDEBUGCODE(const char* previousEndOfCurrentRun);
374 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
375 fRunIterators.pop();
376 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
377 currentRun->consume();
378 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
379 fRunIterators.insert(currentRun);
380 }
381 return true;
382 }
383
384 const char* endOfCurrentRun() const {
385 return fRunIterators.peek()->endOfCurrentRun();
386 }
387
388private:
389 bool allRunsAreAtEnd() const {
390 for (int i = 0; i < fRunIterators.count(); ++i) {
391 if (!fRunIterators.at(i)->atEnd()) {
392 return false;
393 }
394 }
395 return true;
396 }
397
398 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
399 return *a < *b;
400 }
401 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
402};
403
404struct ShapedGlyph {
405 SkGlyphID fID;
406 uint32_t fCluster;
407 SkPoint fOffset;
408 SkVector fAdvance;
409 bool fMayLineBreakBefore;
410 bool fMustLineBreakBefore;
411 bool fHasVisual;
412};
413struct ShapedRun {
Mike Reed6d595682018-12-05 17:28:14 -0500414 ShapedRun(const char* utf8Start, const char* utf8End, int numGlyphs, const SkFont& font,
Ben Wagner8d45a382017-11-16 10:08:28 -0500415 UBiDiLevel level, std::unique_ptr<ShapedGlyph[]> glyphs)
Mike Reed6d595682018-12-05 17:28:14 -0500416 : fUtf8Start(utf8Start), fUtf8End(utf8End), fNumGlyphs(numGlyphs), fFont(font)
Ben Wagner8d45a382017-11-16 10:08:28 -0500417 , fLevel(level), fGlyphs(std::move(glyphs))
418 {}
419
420 const char* fUtf8Start;
421 const char* fUtf8End;
422 int fNumGlyphs;
Mike Reed6d595682018-12-05 17:28:14 -0500423 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500424 UBiDiLevel fLevel;
425 std::unique_ptr<ShapedGlyph[]> fGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500426 SkVector fAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500427};
428
429static constexpr bool is_LTR(UBiDiLevel level) {
430 return (level & 1) == 0;
431}
432
Florin Malita950243d2019-01-11 11:08:35 -0500433static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
434 const ShapedRun& run, int start, int end,
Florin Malita9867f612018-12-12 10:54:49 -0500435 SkPoint* p) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500436 unsigned len = end - start;
Florin Malita9867f612018-12-12 10:54:49 -0500437
Florin Malita950243d2019-01-11 11:08:35 -0500438 const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8End - run.fUtf8Start);
Florin Malita9867f612018-12-12 10:54:49 -0500439 SkASSERT(buffer.glyphs);
440 SkASSERT(buffer.positions);
441
442 if (buffer.utf8text) {
443 memcpy(buffer.utf8text, run.fUtf8Start, run.fUtf8End - run.fUtf8Start);
444 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500445
446 for (unsigned i = 0; i < len; i++) {
447 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
448 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
Florin Malita9867f612018-12-12 10:54:49 -0500449 buffer.glyphs[i] = glyph.fID;
450 buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
451 if (buffer.clusters) {
452 buffer.clusters[i] = glyph.fCluster;
453 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500454 p->fX += glyph.fAdvance.fX;
455 p->fY += glyph.fAdvance.fY;
456 }
457}
458
459struct ShapedRunGlyphIterator {
460 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
461 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
462 { }
463
464 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
465 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
466 bool operator==(const ShapedRunGlyphIterator& that) const {
467 return fRuns == that.fRuns &&
468 fRunIndex == that.fRunIndex &&
469 fGlyphIndex == that.fGlyphIndex;
470 }
471 bool operator!=(const ShapedRunGlyphIterator& that) const {
472 return fRuns != that.fRuns ||
473 fRunIndex != that.fRunIndex ||
474 fGlyphIndex != that.fGlyphIndex;
475 }
476
477 ShapedGlyph* next() {
478 const SkTArray<ShapedRun>& runs = *fRuns;
479 SkASSERT(fRunIndex < runs.count());
480 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
481
482 ++fGlyphIndex;
483 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
484 fGlyphIndex = 0;
485 ++fRunIndex;
486 if (fRunIndex >= runs.count()) {
487 return nullptr;
488 }
489 }
490 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
491 }
492
493 ShapedGlyph* current() {
494 const SkTArray<ShapedRun>& runs = *fRuns;
495 if (fRunIndex >= runs.count()) {
496 return nullptr;
497 }
498 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
499 }
500
501 const SkTArray<ShapedRun>* fRuns;
502 int fRunIndex;
503 int fGlyphIndex;
504};
505
506} // namespace
507
508struct SkShaper::Impl {
509 HBFont fHarfBuzzFont;
510 HBBuffer fBuffer;
511 sk_sp<SkTypeface> fTypeface;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500512 ICUBrk fBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500513};
514
Ben Wagnere0001732017-08-31 16:26:26 -0400515SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary0e07ad72018-02-08 13:06:56 -0500516 SkOnce once;
517 once([] { SkLoadICU(); });
518
Ben Wagnere0001732017-08-31 16:26:26 -0400519 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
520 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Florin Malitaa4e1a632019-01-22 16:27:01 -0500521 if (!fImpl->fHarfBuzzFont) {
522 SkDebugf("create_hb_font failed!\n");
523 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400524 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500525 SkASSERT(fImpl->fBuffer);
526
Ben Wagner8d45a382017-11-16 10:08:28 -0500527 UErrorCode status = U_ZERO_ERROR;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500528 fImpl->fBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500529 if (U_FAILURE(status)) {
530 SkDebugf("Could not create break iterator: %s", u_errorName(status));
531 SK_ABORT("");
532 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400533}
534
535SkShaper::~SkShaper() {}
536
Ben Wagner8d45a382017-11-16 10:08:28 -0500537bool SkShaper::good() const {
538 return fImpl->fHarfBuzzFont &&
539 fImpl->fBuffer &&
540 fImpl->fTypeface &&
541 fImpl->fBreakIterator;
542}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400543
Florin Malita950243d2019-01-11 11:08:35 -0500544SkPoint SkShaper::shape(RunHandler* handler,
Kevin Lubick57abfe92019-01-28 13:15:51 -0500545 const SkFont& srcFont,
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500546 const char* utf8,
547 size_t utf8Bytes,
548 bool leftToRight,
549 SkPoint point,
550 SkScalar width) const {
Ben Wagner67e3a302017-09-05 14:46:19 -0400551 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
Florin Malita9867f612018-12-12 10:54:49 -0500552 SkASSERT(handler);
Ben Wagner8d45a382017-11-16 10:08:28 -0500553 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400554 //hb_script_t script = ...
Ben Wagnera25fbef2017-08-30 13:56:19 -0400555
Ben Wagner8d45a382017-11-16 10:08:28 -0500556 SkTArray<ShapedRun> runs;
557{
558 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400559
Ben Wagner8d45a382017-11-16 10:08:28 -0500560 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
561 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
562 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500563 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400564 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500565 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400566
Ben Wagner8d45a382017-11-16 10:08:28 -0500567 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
568 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
569 ScriptRunIterator* script = maybeScript.getMaybeNull();
570 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500571 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400572 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500573 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400574
Ben Wagner8d45a382017-11-16 10:08:28 -0500575 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
576 fImpl->fTypeface,
577 fImpl->fHarfBuzzFont.get(),
578 std::move(fontMgr)));
579 FontRunIterator* font = maybeFont.getMaybeNull();
580 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500581 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400582 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500583 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400584
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500585 UBreakIterator& breakIterator = *fImpl->fBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500586 {
587 UErrorCode status = U_ZERO_ERROR;
588 UText utf8UText = UTEXT_INITIALIZER;
589 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
590 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
591 if (U_FAILURE(status)) {
592 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500593 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500594 }
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500595 ubrk_setUText(&breakIterator, &utf8UText, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500596 //utext_close(&utf8UText);
597 if (U_FAILURE(status)) {
598 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500599 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500600 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400601 }
602
Ben Wagner8d45a382017-11-16 10:08:28 -0500603 const char* utf8Start = nullptr;
604 const char* utf8End = utf8;
605 while (runSegmenter.advanceRuns()) {
606 utf8Start = utf8End;
607 utf8End = runSegmenter.endOfCurrentRun();
608
609 hb_buffer_t* buffer = fImpl->fBuffer.get();
610 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
611 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
612 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
613
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400614 // Add precontext.
615 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
616
Ben Wagner8d45a382017-11-16 10:08:28 -0500617 // Populate the hb_buffer directly with utf8 cluster indexes.
618 const char* utf8Current = utf8Start;
619 while (utf8Current < utf8End) {
620 unsigned int cluster = utf8Current - utf8Start;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400621 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
Ben Wagner8d45a382017-11-16 10:08:28 -0500622 hb_buffer_add(buffer, u, cluster);
623 }
624
Ben Wagnerc0c99b32018-08-07 10:14:18 -0400625 // Add postcontext.
626 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
627
Ben Wagner8d45a382017-11-16 10:08:28 -0500628 size_t utf8runLength = utf8End - utf8Start;
629 if (!SkTFitsIn<int>(utf8runLength)) {
630 SkDebugf("Shaping error: utf8 too long");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500631 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500632 }
633 hb_buffer_set_script(buffer, script->currentScript());
634 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
635 hb_buffer_set_direction(buffer, direction);
636 // TODO: language
637 hb_buffer_guess_segment_properties(buffer);
638 // TODO: features
Hal Canary0dfa2082018-10-31 13:02:49 -0400639 if (!font->currentHBFont()) {
640 continue;
641 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500642 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
643 unsigned len = hb_buffer_get_length(buffer);
644 if (len == 0) {
645 continue;
646 }
647
648 if (direction == HB_DIRECTION_RTL) {
649 // Put the clusters back in logical order.
650 // Note that the advances remain ltr.
651 hb_buffer_reverse(buffer);
652 }
653 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
654 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
655
656 if (!SkTFitsIn<int>(len)) {
657 SkDebugf("Shaping error: too many glyphs");
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500658 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500659 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400660
Kevin Lubick57abfe92019-01-28 13:15:51 -0500661 SkFont runFont(srcFont);
662 runFont.setTypeface(sk_ref_sp(font->currentTypeface()));
663 ShapedRun& run = runs.emplace_back(utf8Start, utf8End, len, runFont, bidi->currentLevel(),
Ben Wagner8d45a382017-11-16 10:08:28 -0500664 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]));
665 int scaleX, scaleY;
666 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
Mike Reed6d595682018-12-05 17:28:14 -0500667 double textSizeY = run.fFont.getSize() / scaleY;
668 double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
Florin Malita950243d2019-01-11 11:08:35 -0500669 SkVector runAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500670 for (unsigned i = 0; i < len; i++) {
671 ShapedGlyph& glyph = run.fGlyphs[i];
672 glyph.fID = info[i].codepoint;
673 glyph.fCluster = info[i].cluster;
674 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
675 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
676 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
677 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
678 glyph.fHasVisual = true; //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
679 //info->mask safe_to_break;
680 glyph.fMustLineBreakBefore = false;
Florin Malita950243d2019-01-11 11:08:35 -0500681
682 runAdvance += glyph.fAdvance;
Ben Wagner8d45a382017-11-16 10:08:28 -0500683 }
Florin Malita950243d2019-01-11 11:08:35 -0500684 run.fAdvance = runAdvance;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400685
Ben Wagner8d45a382017-11-16 10:08:28 -0500686 int32_t clusterOffset = utf8Start - utf8;
687 uint32_t previousCluster = 0xFFFFFFFF;
688 for (unsigned i = 0; i < len; ++i) {
689 ShapedGlyph& glyph = run.fGlyphs[i];
690 int32_t glyphCluster = glyph.fCluster + clusterOffset;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500691 int32_t breakIteratorCurrent = ubrk_current(&breakIterator);
692 while (breakIteratorCurrent != UBRK_DONE &&
Ben Wagner8d45a382017-11-16 10:08:28 -0500693 breakIteratorCurrent < glyphCluster)
694 {
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500695 breakIteratorCurrent = ubrk_next(&breakIterator);
Ben Wagner2868b782017-08-31 14:12:27 -0400696 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500697 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
698 breakIteratorCurrent == glyphCluster;
699 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400700 }
701 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500702}
703
704// Iterate over the glyphs in logical order to mark line endings.
705{
706 SkScalar widthSoFar = 0;
707 bool previousBreakValid = false; // Set when previousBreak is set to a valid candidate break.
708 bool canAddBreakNow = false; // Disallow line breaks before the first glyph of a run.
709 ShapedRunGlyphIterator previousBreak(runs);
710 ShapedRunGlyphIterator glyphIterator(runs);
711 while (ShapedGlyph* glyph = glyphIterator.current()) {
712 if (canAddBreakNow && glyph->fMayLineBreakBefore) {
713 previousBreakValid = true;
714 previousBreak = glyphIterator;
715 }
716 SkScalar glyphWidth = glyph->fAdvance.fX;
Ben Wagnera900ad52018-08-31 17:48:19 -0400717 // TODO: if the glyph is non-visible it can be added.
Ben Wagner8d45a382017-11-16 10:08:28 -0500718 if (widthSoFar + glyphWidth < width) {
719 widthSoFar += glyphWidth;
720 glyphIterator.next();
721 canAddBreakNow = true;
722 continue;
723 }
724
Ben Wagnera900ad52018-08-31 17:48:19 -0400725 // TODO: for both of these emergency break cases
726 // don't break grapheme clusters and pull in any zero width or non-visible
Ben Wagner8d45a382017-11-16 10:08:28 -0500727 if (widthSoFar == 0) {
728 // Adding just this glyph is too much, just break with this glyph
729 glyphIterator.next();
730 previousBreak = glyphIterator;
731 } else if (!previousBreakValid) {
Ben Wagnera900ad52018-08-31 17:48:19 -0400732 // No break opportunity found yet, just break without this glyph
Ben Wagner8d45a382017-11-16 10:08:28 -0500733 previousBreak = glyphIterator;
734 }
735 glyphIterator = previousBreak;
736 glyph = glyphIterator.current();
737 if (glyph) {
738 glyph->fMustLineBreakBefore = true;
739 }
740 widthSoFar = 0;
741 previousBreakValid = false;
742 canAddBreakNow = false;
743 }
744}
745
746// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500747 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500748{
749 ShapedRunGlyphIterator previousBreak(runs);
750 ShapedRunGlyphIterator glyphIterator(runs);
751 SkScalar maxAscent = 0;
752 SkScalar maxDescent = 0;
753 SkScalar maxLeading = 0;
754 int previousRunIndex = -1;
Florin Malita950243d2019-01-11 11:08:35 -0500755 size_t lineIndex = 0;
Ben Wagner8d45a382017-11-16 10:08:28 -0500756 while (glyphIterator.current()) {
757 int runIndex = glyphIterator.fRunIndex;
758 int glyphIndex = glyphIterator.fGlyphIndex;
759 ShapedGlyph* nextGlyph = glyphIterator.next();
760
761 if (previousRunIndex != runIndex) {
Mike Reedb5784ac2018-11-12 09:35:15 -0500762 SkFontMetrics metrics;
Mike Reed6d595682018-12-05 17:28:14 -0500763 runs[runIndex].fFont.getMetrics(&metrics);
Ben Wagner8d45a382017-11-16 10:08:28 -0500764 maxAscent = SkTMin(maxAscent, metrics.fAscent);
765 maxDescent = SkTMax(maxDescent, metrics.fDescent);
766 maxLeading = SkTMax(maxLeading, metrics.fLeading);
767 previousRunIndex = runIndex;
768 }
769
770 // Nothing can be written until the baseline is known.
771 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
772 continue;
773 }
774
775 currentPoint.fY -= maxAscent;
776
777 int numRuns = runIndex - previousBreak.fRunIndex + 1;
778 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
779 for (int i = 0; i < numRuns; ++i) {
780 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
781 }
782 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
783 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
784
785 for (int i = 0; i < numRuns; ++i) {
786 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
787
788 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
789 ? previousBreak.fGlyphIndex
790 : 0;
791 int endGlyphIndex = (logicalIndex == runIndex)
792 ? glyphIndex + 1
793 : runs[logicalIndex].fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500794
795 const auto& run = runs[logicalIndex];
796 const RunHandler::RunInfo info = {
797 lineIndex,
798 run.fAdvance,
799 maxAscent,
800 maxDescent,
801 maxLeading,
802 };
803 append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
Ben Wagner8d45a382017-11-16 10:08:28 -0500804 }
805
806 currentPoint.fY += maxDescent + maxLeading;
807 currentPoint.fX = point.fX;
808 maxAscent = 0;
809 maxDescent = 0;
810 maxLeading = 0;
811 previousRunIndex = -1;
Florin Malita950243d2019-01-11 11:08:35 -0500812 ++lineIndex;
Ben Wagner8d45a382017-11-16 10:08:28 -0500813 previousBreak = glyphIterator;
814 }
815}
816
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500817 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400818}