blob: 22a53a6467e752f6a5d0da1fb267ce71636a6c13 [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 Wagner2fc14742019-02-06 16:37:44 -05008#include "SkBitmaskEnum.h"
Hal Canary61021922019-02-06 12:29:11 -05009#include "SkFont.h"
Ben Wagner17774242018-08-07 14:31:33 -040010#include "SkFontArguments.h"
Hal Canary61021922019-02-06 12:29:11 -050011#include "SkFontMetrics.h"
Ben Wagner67e3a302017-09-05 14:46:19 -040012#include "SkFontMgr.h"
Ben Wagner17774242018-08-07 14:31:33 -040013#include "SkMalloc.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"
Ben Wagner454e5fb2019-02-08 17:46:38 -050018#include "SkSpan.h"
Ben Wagnera25fbef2017-08-30 13:56:19 -040019#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
Ben Wagner0ec8ec22018-09-04 18:17:13 -040040#include <cstring>
41#include <locale>
Ben Wagner17774242018-08-07 14:31:33 -040042#include <memory>
43#include <utility>
Ben Wagnera25fbef2017-08-30 13:56:19 -040044
Hal Canary61021922019-02-06 12:29:11 -050045#if defined(SK_USING_THIRD_PARTY_ICU)
Hal Canary32498f02019-02-04 15:36:31 -050046#include "SkLoadICU.h"
Hal Canary61021922019-02-06 12:29:11 -050047#endif
Hal Canary32498f02019-02-04 15:36:31 -050048
Ben Wagner2fc14742019-02-06 16:37:44 -050049namespace skstd {
50template <> struct is_bitmask_enum<hb_buffer_flags_t> : std::true_type {};
51}
52
Ben Wagnera25fbef2017-08-30 13:56:19 -040053namespace {
54template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -050055using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
56using HBFace = resource<hb_face_t , hb_face_destroy >;
57using HBFont = resource<hb_font_t , hb_font_destroy >;
58using HBBuffer = resource<hb_buffer_t , hb_buffer_destroy>;
59using ICUBiDi = resource<UBiDi , ubidi_close >;
Ben Wagner0ec8ec22018-09-04 18:17:13 -040060using ICUBrk = resource<UBreakIterator, ubrk_close >;
Ben Wagnera25fbef2017-08-30 13:56:19 -040061
62HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
63 size_t size = asset->getLength();
64 HBBlob blob;
65 if (const void* base = asset->getMemoryBase()) {
66 blob.reset(hb_blob_create((char*)base, SkToUInt(size),
67 HB_MEMORY_MODE_READONLY, asset.release(),
68 [](void* p) { delete (SkStreamAsset*)p; }));
69 } else {
70 // SkDebugf("Extra SkStreamAsset copy\n");
71 void* ptr = size ? sk_malloc_throw(size) : nullptr;
72 asset->read(ptr, size);
73 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
74 HB_MEMORY_MODE_READONLY, ptr, sk_free));
75 }
76 SkASSERT(blob);
77 hb_blob_make_immutable(blob.get());
78 return blob;
79}
Ben Wagnera25fbef2017-08-30 13:56:19 -040080
Ben Wagner8d45a382017-11-16 10:08:28 -050081HBFont create_hb_font(SkTypeface* tf) {
Hal Canary0dfa2082018-10-31 13:02:49 -040082 if (!tf) {
83 return nullptr;
84 }
Ben Wagnera25fbef2017-08-30 13:56:19 -040085 int index;
Hal Canaryddef43f2018-11-16 10:53:51 -050086 std::unique_ptr<SkStreamAsset> typefaceAsset(tf->openStream(&index));
87 if (!typefaceAsset) {
88 SkString name;
89 tf->getFamilyName(&name);
90 SkDebugf("Typeface '%s' has no data :(\n", name.c_str());
91 return nullptr;
92 }
93 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
Ben Wagnera25fbef2017-08-30 13:56:19 -040094 HBFace face(hb_face_create(blob.get(), (unsigned)index));
95 SkASSERT(face);
96 if (!face) {
Ben Wagnere0001732017-08-31 16:26:26 -040097 return nullptr;
Ben Wagnera25fbef2017-08-30 13:56:19 -040098 }
99 hb_face_set_index(face.get(), (unsigned)index);
Ben Wagnere0001732017-08-31 16:26:26 -0400100 hb_face_set_upem(face.get(), tf->getUnitsPerEm());
Ben Wagnera25fbef2017-08-30 13:56:19 -0400101
Ben Wagnere0001732017-08-31 16:26:26 -0400102 HBFont font(hb_font_create(face.get()));
103 SkASSERT(font);
104 if (!font) {
105 return nullptr;
106 }
Ben Wagnere0001732017-08-31 16:26:26 -0400107 hb_ot_font_set_funcs(font.get());
108 int axis_count = tf->getVariationDesignPosition(nullptr, 0);
109 if (axis_count > 0) {
110 SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate> axis_values(axis_count);
111 if (tf->getVariationDesignPosition(axis_values, axis_count) == axis_count) {
112 hb_font_set_variations(font.get(),
113 reinterpret_cast<hb_variation_t*>(axis_values.get()),
114 axis_count);
115 }
116 }
117 return font;
118}
119
Hal Canaryf107a2f2018-07-25 16:52:48 -0400120/** this version replaces invalid utf-8 sequences with code point U+FFFD. */
121static inline SkUnichar utf8_next(const char** ptr, const char* end) {
122 SkUnichar val = SkUTF::NextUTF8(ptr, end);
123 if (val < 0) {
124 return 0xFFFD; // REPLACEMENT CHARACTER
125 }
126 return val;
127}
128
Ben Wagner8d45a382017-11-16 10:08:28 -0500129class RunIterator {
130public:
131 virtual ~RunIterator() {}
132 virtual void consume() = 0;
133 // Pointer one past the last (utf8) element in the current run.
134 virtual const char* endOfCurrentRun() const = 0;
135 virtual bool atEnd() const = 0;
136 bool operator<(const RunIterator& that) const {
137 return this->endOfCurrentRun() < that.endOfCurrentRun();
138 }
139};
140
141class BiDiRunIterator : public RunIterator {
142public:
143 static SkTLazy<BiDiRunIterator> Make(const char* utf8, size_t utf8Bytes, UBiDiLevel level) {
144 SkTLazy<BiDiRunIterator> ret;
145
146 // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
147 // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
148 if (!SkTFitsIn<int32_t>(utf8Bytes)) {
149 SkDebugf("Bidi error: text too long");
150 return ret;
151 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500152
153 UErrorCode status = U_ZERO_ERROR;
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500154
155 // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
156 int32_t utf16Units;
157 u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
158 status = U_ZERO_ERROR;
159 std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
160 u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
161 if (U_FAILURE(status)) {
162 SkDebugf("Invalid utf8 input: %s", u_errorName(status));
163 return ret;
164 }
165
166 ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &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 SkASSERT(bidi);
172
173 // The required lifetime of utf16 isn't well documented.
174 // It appears it isn't used after ubidi_setPara except through ubidi_getText.
Ben Wagnerc5aa8eb2019-01-24 16:15:55 -0500175 ubidi_setPara(bidi.get(), utf16.get(), utf16Units, level, nullptr, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500176 if (U_FAILURE(status)) {
177 SkDebugf("Bidi error: %s", u_errorName(status));
178 return ret;
179 }
180
Hal Canary4014ba62018-07-24 11:33:21 -0400181 ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
Ben Wagner8d45a382017-11-16 10:08:28 -0500182 return ret;
183 }
Hal Canary4014ba62018-07-24 11:33:21 -0400184 BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
Ben Wagner8d45a382017-11-16 10:08:28 -0500185 : fBidi(std::move(bidi))
186 , fEndOfCurrentRun(utf8)
Hal Canary4014ba62018-07-24 11:33:21 -0400187 , fEndOfAllRuns(end)
Ben Wagner8d45a382017-11-16 10:08:28 -0500188 , fUTF16LogicalPosition(0)
189 , fLevel(UBIDI_DEFAULT_LTR)
190 {}
191 void consume() override {
192 SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
193 int32_t endPosition = ubidi_getLength(fBidi.get());
194 fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400195 SkUnichar u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
196 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500197 UBiDiLevel level;
198 while (fUTF16LogicalPosition < endPosition) {
199 level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
200 if (level != fLevel) {
201 break;
202 }
Hal Canaryf107a2f2018-07-25 16:52:48 -0400203 u = utf8_next(&fEndOfCurrentRun, fEndOfAllRuns);
204 fUTF16LogicalPosition += SkUTF::ToUTF16(u);
Ben Wagner8d45a382017-11-16 10:08:28 -0500205 }
206 }
207 const char* endOfCurrentRun() const override {
208 return fEndOfCurrentRun;
209 }
210 bool atEnd() const override {
211 return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
212 }
213
214 UBiDiLevel currentLevel() const {
215 return fLevel;
216 }
217private:
218 ICUBiDi fBidi;
219 const char* fEndOfCurrentRun;
Hal Canary4014ba62018-07-24 11:33:21 -0400220 const char* fEndOfAllRuns;
Ben Wagner8d45a382017-11-16 10:08:28 -0500221 int32_t fUTF16LogicalPosition;
222 UBiDiLevel fLevel;
223};
224
225class ScriptRunIterator : public RunIterator {
226public:
227 static SkTLazy<ScriptRunIterator> Make(const char* utf8, size_t utf8Bytes,
228 hb_unicode_funcs_t* hbUnicode)
229 {
230 SkTLazy<ScriptRunIterator> ret;
231 ret.init(utf8, utf8Bytes, hbUnicode);
232 return ret;
233 }
234 ScriptRunIterator(const char* utf8, size_t utf8Bytes, hb_unicode_funcs_t* hbUnicode)
235 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
236 , fHBUnicode(hbUnicode)
237 , fCurrentScript(HB_SCRIPT_UNKNOWN)
238 {}
239 void consume() override {
240 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400241 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500242 fCurrentScript = hb_unicode_script(fHBUnicode, u);
243 while (fCurrent < fEnd) {
244 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400245 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500246 const hb_script_t script = hb_unicode_script(fHBUnicode, u);
247 if (script != fCurrentScript) {
248 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
249 fCurrentScript = script;
250 } else if (script == HB_SCRIPT_INHERITED || script == HB_SCRIPT_COMMON) {
251 continue;
252 } else {
253 fCurrent = prev;
254 break;
255 }
256 }
257 }
258 if (fCurrentScript == HB_SCRIPT_INHERITED) {
259 fCurrentScript = HB_SCRIPT_COMMON;
260 }
261 }
262 const char* endOfCurrentRun() const override {
263 return fCurrent;
264 }
265 bool atEnd() const override {
266 return fCurrent == fEnd;
267 }
268
269 hb_script_t currentScript() const {
270 return fCurrentScript;
271 }
272private:
273 const char* fCurrent;
274 const char* fEnd;
275 hb_unicode_funcs_t* fHBUnicode;
276 hb_script_t fCurrentScript;
277};
278
279class FontRunIterator : public RunIterator {
280public:
281 static SkTLazy<FontRunIterator> Make(const char* utf8, size_t utf8Bytes,
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400282 SkFont font,
Ben Wagner8d45a382017-11-16 10:08:28 -0500283 sk_sp<SkFontMgr> fallbackMgr)
284 {
285 SkTLazy<FontRunIterator> ret;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400286 font.setTypeface(font.refTypefaceOrDefault());
287 HBFont hbFont = create_hb_font(font.getTypeface());
288 if (!hbFont) {
289 SkDebugf("create_hb_font failed!\n");
290 return ret;
291 }
292 ret.init(utf8, utf8Bytes, std::move(font), std::move(hbFont), std::move(fallbackMgr));
Ben Wagner8d45a382017-11-16 10:08:28 -0500293 return ret;
294 }
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400295 FontRunIterator(const char* utf8, size_t utf8Bytes, SkFont font,
296 HBFont hbFont, sk_sp<SkFontMgr> fallbackMgr)
Ben Wagner8d45a382017-11-16 10:08:28 -0500297 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
298 , fFallbackMgr(std::move(fallbackMgr))
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400299 , fHBFont(std::move(hbFont)), fFont(std::move(font))
300 , fFallbackHBFont(nullptr), fFallbackFont(fFont)
301 , fCurrentHBFont(fHBFont.get()), fCurrentFont(&fFont)
302 {
303 fFallbackFont.setTypeface(nullptr);
304 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500305 void consume() override {
306 SkASSERT(fCurrent < fEnd);
Hal Canaryf107a2f2018-07-25 16:52:48 -0400307 SkUnichar u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500308 // If the starting typeface can handle this character, use it.
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400309 if (fFont.getTypeface()->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
310 fCurrentFont = &fFont;
311 fCurrentHBFont = fHBFont.get();
Ben Wagnera900ad52018-08-31 17:48:19 -0400312 // If the current fallback can handle this character, use it.
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400313 } else if (fFallbackFont.getTypeface() &&
314 fFallbackFont.getTypeface()->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
Ben Wagnera900ad52018-08-31 17:48:19 -0400315 {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400316 fCurrentFont = &fFallbackFont;
Ben Wagnera900ad52018-08-31 17:48:19 -0400317 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500318 // If not, try to find a fallback typeface
319 } else {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400320 fFallbackFont.setTypeface(sk_ref_sp(fFallbackMgr->matchFamilyStyleCharacter(
321 nullptr, fFont.getTypeface()->fontStyle(), nullptr, 0, u)));
322 fFallbackHBFont = create_hb_font(fFallbackFont.getTypeface());
323 fCurrentFont = &fFallbackFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500324 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500325 }
326
327 while (fCurrent < fEnd) {
328 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400329 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500330
Ben Wagnera900ad52018-08-31 17:48:19 -0400331 // If not using initial typeface and initial typeface has this character, stop fallback.
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400332 if (fCurrentFont->getTypeface() != fFont.getTypeface() &&
333 fFont.getTypeface()->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1))
Ben Wagner8d45a382017-11-16 10:08:28 -0500334 {
335 fCurrent = prev;
336 return;
337 }
338 // If the current typeface cannot handle this character, stop using it.
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400339 if (!fCurrentFont->getTypeface()->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500340 fCurrent = prev;
341 return;
342 }
343 }
344 }
345 const char* endOfCurrentRun() const override {
346 return fCurrent;
347 }
348 bool atEnd() const override {
349 return fCurrent == fEnd;
350 }
351
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400352 SkFont* currentFont() const {
353 return fCurrentFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500354 }
355 hb_font_t* currentHBFont() const {
356 return fCurrentHBFont;
357 }
358private:
359 const char* fCurrent;
360 const char* fEnd;
361 sk_sp<SkFontMgr> fFallbackMgr;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400362 HBFont fHBFont;
363 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500364 HBFont fFallbackHBFont;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400365 SkFont fFallbackFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500366 hb_font_t* fCurrentHBFont;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400367 SkFont* fCurrentFont;
368};
369
370class LanguageRunIterator : public RunIterator {
371public:
372 static SkTLazy<LanguageRunIterator> Make(const char* utf8, size_t utf8Bytes) {
373 SkTLazy<LanguageRunIterator> ret;
374 ret.init(utf8, utf8Bytes);
375 return ret;
376 }
377 LanguageRunIterator(const char* utf8, size_t utf8Bytes)
378 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
379 , fLanguage(hb_language_from_string(std::locale().name().c_str(), -1))
380 { }
381 void consume() override {
382 // Ideally something like cld2/3 could be used, or user signals.
383 SkASSERT(fCurrent < fEnd);
384 fCurrent = fEnd;
385 }
386 const char* endOfCurrentRun() const override {
387 return fCurrent;
388 }
389 bool atEnd() const override {
390 return fCurrent == fEnd;
391 }
392
393 hb_language_t currentLanguage() const {
394 return fLanguage;
395 }
396private:
397 const char* fCurrent;
398 const char* fEnd;
399 hb_language_t fLanguage;
Ben Wagner8d45a382017-11-16 10:08:28 -0500400};
401
402class RunIteratorQueue {
403public:
404 void insert(RunIterator* runIterator) {
405 fRunIterators.insert(runIterator);
406 }
407
408 bool advanceRuns() {
409 const RunIterator* leastRun = fRunIterators.peek();
410 if (leastRun->atEnd()) {
411 SkASSERT(this->allRunsAreAtEnd());
412 return false;
413 }
414 const char* leastEnd = leastRun->endOfCurrentRun();
415 RunIterator* currentRun = nullptr;
416 SkDEBUGCODE(const char* previousEndOfCurrentRun);
417 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
418 fRunIterators.pop();
419 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
420 currentRun->consume();
421 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
422 fRunIterators.insert(currentRun);
423 }
424 return true;
425 }
426
427 const char* endOfCurrentRun() const {
428 return fRunIterators.peek()->endOfCurrentRun();
429 }
430
431private:
432 bool allRunsAreAtEnd() const {
433 for (int i = 0; i < fRunIterators.count(); ++i) {
434 if (!fRunIterators.at(i)->atEnd()) {
435 return false;
436 }
437 }
438 return true;
439 }
440
441 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
442 return *a < *b;
443 }
444 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
445};
446
447struct ShapedGlyph {
448 SkGlyphID fID;
449 uint32_t fCluster;
450 SkPoint fOffset;
451 SkVector fAdvance;
452 bool fMayLineBreakBefore;
453 bool fMustLineBreakBefore;
454 bool fHasVisual;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400455 bool fGraphemeBreakBefore;
456 bool fUnsafeToBreak;
Ben Wagner8d45a382017-11-16 10:08:28 -0500457};
458struct ShapedRun {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500459 ShapedRun(SkSpan<const char> utf8, const SkFont& font, UBiDiLevel level,
460 std::unique_ptr<ShapedGlyph[]> glyphs, int numGlyphs)
461 : fUtf8(utf8), fFont(font), fLevel(level)
462 , fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs)
Ben Wagner8d45a382017-11-16 10:08:28 -0500463 {}
464
Ben Wagner454e5fb2019-02-08 17:46:38 -0500465 SkSpan<const char> fUtf8;
Mike Reed6d595682018-12-05 17:28:14 -0500466 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500467 UBiDiLevel fLevel;
468 std::unique_ptr<ShapedGlyph[]> fGlyphs;
Ben Wagner454e5fb2019-02-08 17:46:38 -0500469 int fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500470 SkVector fAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500471};
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400472struct ShapedLine {
473 SkTArray<ShapedRun> runs;
474 SkVector fAdvance = { 0, 0 };
475};
Ben Wagner8d45a382017-11-16 10:08:28 -0500476
477static constexpr bool is_LTR(UBiDiLevel level) {
478 return (level & 1) == 0;
479}
480
Florin Malita950243d2019-01-11 11:08:35 -0500481static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
482 const ShapedRun& run, int start, int end,
Florin Malita9867f612018-12-12 10:54:49 -0500483 SkPoint* p) {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500484 const unsigned len = end - start;
Florin Malita9867f612018-12-12 10:54:49 -0500485
Ben Wagner454e5fb2019-02-08 17:46:38 -0500486 const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8);
Florin Malita9867f612018-12-12 10:54:49 -0500487 SkASSERT(buffer.glyphs);
488 SkASSERT(buffer.positions);
489
Ben Wagner8d45a382017-11-16 10:08:28 -0500490 for (unsigned i = 0; i < len; i++) {
491 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
492 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
Florin Malita9867f612018-12-12 10:54:49 -0500493 buffer.glyphs[i] = glyph.fID;
494 buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
495 if (buffer.clusters) {
496 buffer.clusters[i] = glyph.fCluster;
497 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500498 p->fX += glyph.fAdvance.fX;
499 p->fY += glyph.fAdvance.fY;
500 }
Ben Wagner454e5fb2019-02-08 17:46:38 -0500501 handler->commitRun();
Ben Wagner8d45a382017-11-16 10:08:28 -0500502}
503
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400504static void emit(const ShapedLine& line, SkShaper::RunHandler* handler,
Florin Malita500133b2019-02-07 10:56:55 -0500505 SkPoint point, SkPoint& currentPoint)
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400506{
507 // Reorder the runs and glyphs per line and write them out.
508 SkScalar maxAscent = 0;
509 SkScalar maxDescent = 0;
510 SkScalar maxLeading = 0;
511 for (const ShapedRun& run : line.runs) {
512 SkFontMetrics metrics;
513 run.fFont.getMetrics(&metrics);
514 maxAscent = SkTMin(maxAscent, metrics.fAscent);
515 maxDescent = SkTMax(maxDescent, metrics.fDescent);
516 maxLeading = SkTMax(maxLeading, metrics.fLeading);
517 }
518
519 int numRuns = line.runs.size();
520 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
521 for (int i = 0; i < numRuns; ++i) {
522 runLevels[i] = line.runs[i].fLevel;
523 }
524 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
525 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
526
527 currentPoint.fY -= maxAscent;
528
529 for (int i = 0; i < numRuns; ++i) {
530 int logicalIndex = logicalFromVisual[i];
531
532 const auto& run = line.runs[logicalIndex];
533 const SkShaper::RunHandler::RunInfo info = {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400534 run.fAdvance,
535 maxAscent,
536 maxDescent,
537 maxLeading,
538 };
539 append(handler, info, run, 0, run.fNumGlyphs, &currentPoint);
540 }
541
542 currentPoint.fY += maxDescent + maxLeading;
543 currentPoint.fX = point.fX;
544
Florin Malita500133b2019-02-07 10:56:55 -0500545 handler->commitLine();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400546}
547
Ben Wagner8d45a382017-11-16 10:08:28 -0500548struct ShapedRunGlyphIterator {
549 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
550 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
551 { }
552
553 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
554 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
555 bool operator==(const ShapedRunGlyphIterator& that) const {
556 return fRuns == that.fRuns &&
557 fRunIndex == that.fRunIndex &&
558 fGlyphIndex == that.fGlyphIndex;
559 }
560 bool operator!=(const ShapedRunGlyphIterator& that) const {
561 return fRuns != that.fRuns ||
562 fRunIndex != that.fRunIndex ||
563 fGlyphIndex != that.fGlyphIndex;
564 }
565
566 ShapedGlyph* next() {
567 const SkTArray<ShapedRun>& runs = *fRuns;
568 SkASSERT(fRunIndex < runs.count());
569 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
570
571 ++fGlyphIndex;
572 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
573 fGlyphIndex = 0;
574 ++fRunIndex;
575 if (fRunIndex >= runs.count()) {
576 return nullptr;
577 }
578 }
579 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
580 }
581
582 ShapedGlyph* current() {
583 const SkTArray<ShapedRun>& runs = *fRuns;
584 if (fRunIndex >= runs.count()) {
585 return nullptr;
586 }
587 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
588 }
589
590 const SkTArray<ShapedRun>* fRuns;
591 int fRunIndex;
592 int fGlyphIndex;
593};
594
595} // namespace
596
597struct SkShaper::Impl {
598 HBFont fHarfBuzzFont;
599 HBBuffer fBuffer;
600 sk_sp<SkTypeface> fTypeface;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400601 ICUBrk fLineBreakIterator;
602 ICUBrk fGraphemeBreakIterator;
603
604 SkPoint shapeCorrect(RunHandler* handler,
605 const char* utf8,
606 size_t utf8Bytes,
607 SkPoint point,
608 SkScalar width,
609 RunIteratorQueue& runSegmenter,
610 const BiDiRunIterator* bidi,
611 const LanguageRunIterator* language,
612 const ScriptRunIterator* script,
613 const FontRunIterator* font) const;
614
615 SkPoint shapeOk(RunHandler* handler,
616 const char* utf8,
617 size_t utf8Bytes,
618 SkPoint point,
619 SkScalar width,
620 RunIteratorQueue& runSegmenter,
621 const BiDiRunIterator* bidi,
622 const LanguageRunIterator* language,
623 const ScriptRunIterator* script,
624 const FontRunIterator* font) const;
625
626 ShapedRun shape(const char* utf8,
627 size_t utf8Bytes,
628 const char* utf8Start,
629 const char* utf8End,
630 const BiDiRunIterator* bidi,
631 const LanguageRunIterator* language,
632 const ScriptRunIterator* script,
633 const FontRunIterator* font) const;
Ben Wagner8d45a382017-11-16 10:08:28 -0500634};
635
Ben Wagnere0001732017-08-31 16:26:26 -0400636SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary61021922019-02-06 12:29:11 -0500637#if defined(SK_USING_THIRD_PARTY_ICU)
638 if (!SkLoadICU()) {
639 SkDebugf("SkLoadICU() failed!\n");
640 return;
641 }
642#endif
Ben Wagnere0001732017-08-31 16:26:26 -0400643 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
644 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Florin Malitaa4e1a632019-01-22 16:27:01 -0500645 if (!fImpl->fHarfBuzzFont) {
646 SkDebugf("create_hb_font failed!\n");
647 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400648 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500649 SkASSERT(fImpl->fBuffer);
650
Ben Wagner8d45a382017-11-16 10:08:28 -0500651 UErrorCode status = U_ZERO_ERROR;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400652 fImpl->fLineBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500653 if (U_FAILURE(status)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400654 SkDebugf("Could not create line break iterator: %s", u_errorName(status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500655 SK_ABORT("");
656 }
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400657
658 fImpl->fGraphemeBreakIterator.reset(ubrk_open(UBRK_CHARACTER, "th", nullptr, 0, &status));
659 if (U_FAILURE(status)) {
660 SkDebugf("Could not create grapheme break iterator: %s", u_errorName(status));
661 SK_ABORT("");
662 }
663
Ben Wagnera25fbef2017-08-30 13:56:19 -0400664}
665
666SkShaper::~SkShaper() {}
667
Ben Wagner8d45a382017-11-16 10:08:28 -0500668bool SkShaper::good() const {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400669 return fImpl->fBuffer &&
670 fImpl->fLineBreakIterator &&
671 fImpl->fGraphemeBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500672}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400673
Florin Malita950243d2019-01-11 11:08:35 -0500674SkPoint SkShaper::shape(RunHandler* handler,
Kevin Lubick57abfe92019-01-28 13:15:51 -0500675 const SkFont& srcFont,
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500676 const char* utf8,
677 size_t utf8Bytes,
678 bool leftToRight,
679 SkPoint point,
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400680 SkScalar width) const
Ben Wagner8d45a382017-11-16 10:08:28 -0500681{
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400682 SkASSERT(handler);
683 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
684 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
685
Ben Wagner8d45a382017-11-16 10:08:28 -0500686 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400687
Ben Wagner8d45a382017-11-16 10:08:28 -0500688 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
689 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
690 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500691 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400692 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500693 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400694
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400695 SkTLazy<LanguageRunIterator> maybeLanguage(LanguageRunIterator::Make(utf8, utf8Bytes));
696 LanguageRunIterator* language = maybeLanguage.getMaybeNull();
697 if (!language) {
698 return point;
699 }
700 runSegmenter.insert(language);
701
Ben Wagner8d45a382017-11-16 10:08:28 -0500702 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
703 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
704 ScriptRunIterator* script = maybeScript.getMaybeNull();
705 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500706 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400707 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500708 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400709
Ben Wagner8d45a382017-11-16 10:08:28 -0500710 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400711 srcFont, std::move(fontMgr)));
Ben Wagner8d45a382017-11-16 10:08:28 -0500712 FontRunIterator* font = maybeFont.getMaybeNull();
713 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500714 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400715 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500716 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400717
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400718 if (true) {
719 return fImpl->shapeCorrect(handler, utf8, utf8Bytes, point, width,
720 runSegmenter, bidi, language, script, font);
721 } else {
722 return fImpl->shapeOk(handler, utf8, utf8Bytes, point, width,
723 runSegmenter, bidi, language, script, font);
724 }
725}
726
727SkPoint SkShaper::Impl::shapeCorrect(RunHandler* handler,
728 const char* utf8,
729 size_t utf8Bytes,
730 SkPoint point,
731 SkScalar width,
732 RunIteratorQueue& runSegmenter,
733 const BiDiRunIterator* bidi,
734 const LanguageRunIterator* language,
735 const ScriptRunIterator* script,
736 const FontRunIterator* font) const
737{
738 ShapedLine line;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400739 SkPoint currentPoint = point;
740
741 const char* utf8Start = nullptr;
742 const char* utf8End = utf8;
743 while (runSegmenter.advanceRuns()) { // For each item
744 utf8Start = utf8End;
745 utf8End = runSegmenter.endOfCurrentRun();
746
Ben Wagner454e5fb2019-02-08 17:46:38 -0500747 ShapedRun model(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400748 bool modelNeedsRegenerated = true;
749 int modelOffset = 0;
750
751 struct TextProps {
752 int glyphLen = 0;
753 SkVector advance = {0, 0};
754 };
755 // map from character position to [safe to break, glyph position, advance]
756 std::unique_ptr<TextProps[]> modelText;
757 int modelTextOffset = 0;
758 SkVector modelTextAdvanceOffset = {0, 0};
759
760 while (utf8Start < utf8End) { // While there are still code points left in this item
761 size_t utf8runLength = utf8End - utf8Start;
762 if (modelNeedsRegenerated) {
763 model = shape(utf8, utf8Bytes,
764 utf8Start, utf8End,
765 bidi, language, script, font);
766 modelOffset = 0;
767
768 SkVector advance = {0, 0};
769 modelText.reset(new TextProps[utf8runLength + 1]());
770 for (int i = 0; i < model.fNumGlyphs; ++i) {
771 SkASSERT(model.fGlyphs[i].fCluster < utf8runLength);
772 if (!model.fGlyphs[i].fUnsafeToBreak) {
773 modelText[model.fGlyphs[i].fCluster].glyphLen = i;
774 modelText[model.fGlyphs[i].fCluster].advance = advance;
775 }
776 advance += model.fGlyphs[i].fAdvance;
777 }
778 // Assume it is always safe to break after the end of an item
779 modelText[utf8runLength].glyphLen = model.fNumGlyphs;
780 modelText[utf8runLength].advance = model.fAdvance;
781 modelTextOffset = 0;
782 modelTextAdvanceOffset = {0, 0};
783 modelNeedsRegenerated = false;
784 }
785
786 // TODO: break iterator per item, but just reset position if needed?
787 // Maybe break iterator with model?
788 UBreakIterator& breakIterator = *fLineBreakIterator;
789 {
790 UErrorCode status = U_ZERO_ERROR;
791 UText utf8UText = UTEXT_INITIALIZER;
792 utext_openUTF8(&utf8UText, utf8Start, utf8runLength, &status);
793 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
794 if (U_FAILURE(status)) {
795 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
796 return point;
797 }
798 ubrk_setUText(&breakIterator, &utf8UText, &status);
799 if (U_FAILURE(status)) {
800 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
801 return point;
802 }
803 }
804
Ben Wagner454e5fb2019-02-08 17:46:38 -0500805 ShapedRun best(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400806 best.fAdvance = { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity };
807 SkScalar widthLeft = width - line.fAdvance.fX;
808
809 for (int32_t breakIteratorCurrent = ubrk_next(&breakIterator);
810 breakIteratorCurrent != UBRK_DONE;
811 breakIteratorCurrent = ubrk_next(&breakIterator))
812 {
813 // TODO: if past a safe to break, future safe to break will be at least as long
814
815 // TODO: adjust breakIteratorCurrent by ignorable whitespace
816 ShapedRun candidate = modelText[breakIteratorCurrent + modelTextOffset].glyphLen
Ben Wagner454e5fb2019-02-08 17:46:38 -0500817 ? ShapedRun(SkSpan<const char>(utf8Start, breakIteratorCurrent),
818 *font->currentFont(), bidi->currentLevel(),
819 std::unique_ptr<ShapedGlyph[]>(),
820 modelText[breakIteratorCurrent + modelTextOffset].glyphLen - modelOffset)
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400821 : shape(utf8, utf8Bytes,
822 utf8Start, utf8Start + breakIteratorCurrent,
823 bidi, language, script, font);
Ben Wagner454e5fb2019-02-08 17:46:38 -0500824 if (!candidate.fUtf8.data()) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400825 //report error
826 return point;
827 }
828 if (!candidate.fGlyphs) {
829 candidate.fAdvance = modelText[breakIteratorCurrent + modelTextOffset].advance - modelTextAdvanceOffset;
830 }
831 auto score = [widthLeft](const ShapedRun& run) -> SkScalar {
832 if (run.fAdvance.fX < widthLeft) {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500833 if (run.fUtf8.data() == nullptr) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400834 return SK_ScalarNegativeInfinity;
835 } else {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500836 return run.fUtf8.size();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400837 }
838 } else {
839 return widthLeft - run.fAdvance.fX;
840 }
841 };
842 if (score(best) < score(candidate)) {
843 best = std::move(candidate);
844 }
845 }
846
847 // If nothing fit (best score is negative) and the line is not empty
848 if (width < line.fAdvance.fX + best.fAdvance.fX && !line.runs.empty()) {
Florin Malita500133b2019-02-07 10:56:55 -0500849 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400850 line.runs.reset();
851 line.fAdvance = {0, 0};
852 } else {
853 if (!best.fGlyphs) {
854 best.fGlyphs.reset(new ShapedGlyph[best.fNumGlyphs]);
855 memcpy(best.fGlyphs.get(), model.fGlyphs.get() + modelOffset,
856 best.fNumGlyphs * sizeof(ShapedGlyph));
857 modelOffset += best.fNumGlyphs;
Ben Wagner454e5fb2019-02-08 17:46:38 -0500858 modelTextOffset += best.fUtf8.size();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400859 modelTextAdvanceOffset += best.fAdvance;
860 } else {
861 modelNeedsRegenerated = true;
862 }
Ben Wagner454e5fb2019-02-08 17:46:38 -0500863 utf8Start = best.fUtf8.end();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400864 line.fAdvance += best.fAdvance;
865 line.runs.emplace_back(std::move(best));
866
867 // If item broken, emit line (prevent remainder from accidentally fitting)
868 if (utf8Start != utf8End) {
Florin Malita500133b2019-02-07 10:56:55 -0500869 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400870 line.runs.reset();
871 line.fAdvance = {0, 0};
872 }
873 }
874 }
875 }
Florin Malita500133b2019-02-07 10:56:55 -0500876 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400877 return currentPoint;
878}
879
880SkPoint SkShaper::Impl::shapeOk(RunHandler* handler,
881 const char* utf8,
882 size_t utf8Bytes,
883 SkPoint point,
884 SkScalar width,
885 RunIteratorQueue& runSegmenter,
886 const BiDiRunIterator* bidi,
887 const LanguageRunIterator* language,
888 const ScriptRunIterator* script,
889 const FontRunIterator* font) const
890{
891 SkTArray<ShapedRun> runs;
892{
893 UBreakIterator& lineBreakIterator = *fLineBreakIterator;
894 UBreakIterator& graphemeBreakIterator = *fGraphemeBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500895 {
896 UErrorCode status = U_ZERO_ERROR;
897 UText utf8UText = UTEXT_INITIALIZER;
898 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
899 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
900 if (U_FAILURE(status)) {
901 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500902 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500903 }
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400904
905 ubrk_setUText(&lineBreakIterator, &utf8UText, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500906 if (U_FAILURE(status)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400907 SkDebugf("Could not setText on line break iterator: %s", u_errorName(status));
908 return point;
909 }
910 ubrk_setUText(&graphemeBreakIterator, &utf8UText, &status);
911 if (U_FAILURE(status)) {
912 SkDebugf("Could not setText on grapheme break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500913 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500914 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400915 }
916
Ben Wagner8d45a382017-11-16 10:08:28 -0500917 const char* utf8Start = nullptr;
918 const char* utf8End = utf8;
919 while (runSegmenter.advanceRuns()) {
920 utf8Start = utf8End;
921 utf8End = runSegmenter.endOfCurrentRun();
922
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400923 runs.emplace_back(shape(utf8, utf8Bytes,
924 utf8Start, utf8End,
925 bidi, language, script, font));
926 ShapedRun& run = runs.back();
Ben Wagnera25fbef2017-08-30 13:56:19 -0400927
Ben Wagner8d45a382017-11-16 10:08:28 -0500928 int32_t clusterOffset = utf8Start - utf8;
929 uint32_t previousCluster = 0xFFFFFFFF;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400930 for (int i = 0; i < run.fNumGlyphs; ++i) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500931 ShapedGlyph& glyph = run.fGlyphs[i];
932 int32_t glyphCluster = glyph.fCluster + clusterOffset;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400933
934 int32_t lineBreakIteratorCurrent = ubrk_current(&lineBreakIterator);
935 while (lineBreakIteratorCurrent != UBRK_DONE &&
936 lineBreakIteratorCurrent < glyphCluster)
Ben Wagner8d45a382017-11-16 10:08:28 -0500937 {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400938 lineBreakIteratorCurrent = ubrk_next(&lineBreakIterator);
Ben Wagner2868b782017-08-31 14:12:27 -0400939 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500940 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400941 lineBreakIteratorCurrent == glyphCluster;
942
943 int32_t graphemeBreakIteratorCurrent = ubrk_current(&graphemeBreakIterator);
944 while (graphemeBreakIteratorCurrent != UBRK_DONE &&
945 graphemeBreakIteratorCurrent < glyphCluster)
946 {
947 graphemeBreakIteratorCurrent = ubrk_next(&graphemeBreakIterator);
948 }
949 glyph.fGraphemeBreakBefore = glyph.fCluster != previousCluster &&
950 graphemeBreakIteratorCurrent == glyphCluster;
951
Ben Wagner8d45a382017-11-16 10:08:28 -0500952 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400953 }
954 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500955}
956
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400957// Iterate over the glyphs in logical order to find potential line lengths.
Ben Wagner8d45a382017-11-16 10:08:28 -0500958{
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400959 /** The position of the beginning of the line. */
960 ShapedRunGlyphIterator beginning(runs);
961
962 /** The position of the candidate line break. */
963 ShapedRunGlyphIterator candidateLineBreak(runs);
964 SkScalar candidateLineBreakWidth = 0;
965
966 /** The position of the candidate grapheme break. */
967 ShapedRunGlyphIterator candidateGraphemeBreak(runs);
968 SkScalar candidateGraphemeBreakWidth = 0;
969
970 /** The position of the current location. */
971 ShapedRunGlyphIterator current(runs);
972 SkScalar currentWidth = 0;
973 while (ShapedGlyph* glyph = current.current()) {
974 // 'Break' at graphemes until a line boundary, then only at line boundaries.
975 // Only break at graphemes if no line boundary is valid.
976 if (current != beginning) {
977 if (glyph->fGraphemeBreakBefore || glyph->fMayLineBreakBefore) {
978 // TODO: preserve line breaks <= grapheme breaks
979 // and prevent line breaks inside graphemes
980 candidateGraphemeBreak = current;
981 candidateGraphemeBreakWidth = currentWidth;
982 if (glyph->fMayLineBreakBefore) {
983 candidateLineBreak = current;
984 candidateLineBreakWidth = currentWidth;
985 }
986 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500987 }
988
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400989 SkScalar glyphWidth = glyph->fAdvance.fX;
990 // Break when overwidth, the glyph has a visual representation, and some space is used.
991 if (width < currentWidth + glyphWidth && glyph->fHasVisual && candidateGraphemeBreakWidth > 0){
992 if (candidateLineBreak != beginning) {
993 beginning = candidateLineBreak;
994 currentWidth -= candidateLineBreakWidth;
995 candidateGraphemeBreakWidth -= candidateLineBreakWidth;
996 candidateLineBreakWidth = 0;
997 } else if (candidateGraphemeBreak != beginning) {
998 beginning = candidateGraphemeBreak;
999 candidateLineBreak = beginning;
1000 currentWidth -= candidateGraphemeBreakWidth;
1001 candidateGraphemeBreakWidth = 0;
1002 candidateLineBreakWidth = 0;
1003 } else {
1004 SK_ABORT("");
1005 }
1006
1007 if (width < currentWidth) {
1008 if (width < candidateGraphemeBreakWidth) {
1009 candidateGraphemeBreak = candidateLineBreak;
1010 candidateGraphemeBreakWidth = candidateLineBreakWidth;
1011 }
1012 current = candidateGraphemeBreak;
1013 currentWidth = candidateGraphemeBreakWidth;
1014 }
1015
1016 glyph = beginning.current();
1017 if (glyph) {
1018 glyph->fMustLineBreakBefore = true;
1019 }
1020
1021 } else {
1022 current.next();
1023 currentWidth += glyphWidth;
Ben Wagner8d45a382017-11-16 10:08:28 -05001024 }
Ben Wagner8d45a382017-11-16 10:08:28 -05001025 }
1026}
1027
1028// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -05001029 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -05001030{
1031 ShapedRunGlyphIterator previousBreak(runs);
1032 ShapedRunGlyphIterator glyphIterator(runs);
1033 SkScalar maxAscent = 0;
1034 SkScalar maxDescent = 0;
1035 SkScalar maxLeading = 0;
1036 int previousRunIndex = -1;
1037 while (glyphIterator.current()) {
1038 int runIndex = glyphIterator.fRunIndex;
1039 int glyphIndex = glyphIterator.fGlyphIndex;
1040 ShapedGlyph* nextGlyph = glyphIterator.next();
1041
1042 if (previousRunIndex != runIndex) {
Mike Reedb5784ac2018-11-12 09:35:15 -05001043 SkFontMetrics metrics;
Mike Reed6d595682018-12-05 17:28:14 -05001044 runs[runIndex].fFont.getMetrics(&metrics);
Ben Wagner8d45a382017-11-16 10:08:28 -05001045 maxAscent = SkTMin(maxAscent, metrics.fAscent);
1046 maxDescent = SkTMax(maxDescent, metrics.fDescent);
1047 maxLeading = SkTMax(maxLeading, metrics.fLeading);
1048 previousRunIndex = runIndex;
1049 }
1050
1051 // Nothing can be written until the baseline is known.
1052 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
1053 continue;
1054 }
1055
1056 currentPoint.fY -= maxAscent;
1057
1058 int numRuns = runIndex - previousBreak.fRunIndex + 1;
1059 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
1060 for (int i = 0; i < numRuns; ++i) {
1061 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
1062 }
1063 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
1064 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
1065
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001066 // step through the runs in reverse visual order and the glyphs in reverse logical order
1067 // until a visible glyph is found and force them to the end of the visual line.
1068
Ben Wagner8d45a382017-11-16 10:08:28 -05001069 for (int i = 0; i < numRuns; ++i) {
1070 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
1071
1072 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
1073 ? previousBreak.fGlyphIndex
1074 : 0;
1075 int endGlyphIndex = (logicalIndex == runIndex)
1076 ? glyphIndex + 1
1077 : runs[logicalIndex].fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -05001078
1079 const auto& run = runs[logicalIndex];
1080 const RunHandler::RunInfo info = {
Florin Malita950243d2019-01-11 11:08:35 -05001081 run.fAdvance,
1082 maxAscent,
1083 maxDescent,
1084 maxLeading,
1085 };
1086 append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
Ben Wagner8d45a382017-11-16 10:08:28 -05001087 }
1088
Florin Malita500133b2019-02-07 10:56:55 -05001089 handler->commitLine();
1090
Ben Wagner8d45a382017-11-16 10:08:28 -05001091 currentPoint.fY += maxDescent + maxLeading;
1092 currentPoint.fX = point.fX;
1093 maxAscent = 0;
1094 maxDescent = 0;
1095 maxLeading = 0;
1096 previousRunIndex = -1;
1097 previousBreak = glyphIterator;
1098 }
1099}
1100
Ben Wagner5d4dd8b2018-01-25 14:37:17 -05001101 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -04001102}
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001103
1104
1105ShapedRun SkShaper::Impl::shape(const char* utf8,
Ben Wagner2fc14742019-02-06 16:37:44 -05001106 const size_t utf8Bytes,
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001107 const char* utf8Start,
1108 const char* utf8End,
1109 const BiDiRunIterator* bidi,
1110 const LanguageRunIterator* language,
1111 const ScriptRunIterator* script,
1112 const FontRunIterator* font) const
1113{
Ben Wagner454e5fb2019-02-08 17:46:38 -05001114 ShapedRun run(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001115
1116 hb_buffer_t* buffer = fBuffer.get();
1117 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
1118 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1119 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
1120
Ben Wagner2fc14742019-02-06 16:37:44 -05001121 // See 763e5466c0a03a7c27020e1e2598e488612529a7 for documentation.
1122 hb_buffer_set_flags(buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
1123
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001124 // Add precontext.
1125 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
1126
1127 // Populate the hb_buffer directly with utf8 cluster indexes.
1128 const char* utf8Current = utf8Start;
1129 while (utf8Current < utf8End) {
1130 unsigned int cluster = utf8Current - utf8Start;
1131 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
1132 hb_buffer_add(buffer, u, cluster);
1133 }
1134
1135 // Add postcontext.
1136 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
1137
1138 size_t utf8runLength = utf8End - utf8Start;
1139 if (!SkTFitsIn<int>(utf8runLength)) {
1140 SkDebugf("Shaping error: utf8 too long");
1141 return run;
1142 }
1143 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
1144 hb_buffer_set_direction(buffer, direction);
1145 hb_buffer_set_script(buffer, script->currentScript());
1146 hb_buffer_set_language(buffer, language->currentLanguage());
1147 hb_buffer_guess_segment_properties(buffer);
1148 // TODO: features
1149 if (!font->currentHBFont()) {
1150 return run;
1151 }
1152 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
1153 unsigned len = hb_buffer_get_length(buffer);
1154 if (len == 0) {
1155 // TODO: this isn't an error, make it look different
1156 return run;
1157 }
1158
1159 if (direction == HB_DIRECTION_RTL) {
1160 // Put the clusters back in logical order.
1161 // Note that the advances remain ltr.
1162 hb_buffer_reverse(buffer);
1163 }
1164 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
1165 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
1166
1167 if (!SkTFitsIn<int>(len)) {
1168 SkDebugf("Shaping error: too many glyphs");
1169 return run;
1170 }
1171
Ben Wagner454e5fb2019-02-08 17:46:38 -05001172 run = ShapedRun(SkSpan<const char>(utf8Start, utf8runLength),
1173 *font->currentFont(), bidi->currentLevel(),
1174 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]), len);
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001175 int scaleX, scaleY;
1176 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
1177 double textSizeY = run.fFont.getSize() / scaleY;
1178 double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
1179 SkVector runAdvance = { 0, 0 };
1180 for (unsigned i = 0; i < len; i++) {
1181 ShapedGlyph& glyph = run.fGlyphs[i];
1182 glyph.fID = info[i].codepoint;
1183 glyph.fCluster = info[i].cluster;
1184 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
1185 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
1186 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
1187 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
1188
1189 SkRect bounds;
1190 SkScalar advance;
1191 SkPaint p;
1192 run.fFont.getWidthsBounds(&glyph.fID, 1, &advance, &bounds, &p);
1193 glyph.fHasVisual = !bounds.isEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1194 glyph.fUnsafeToBreak = info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
1195 glyph.fMustLineBreakBefore = false;
1196
1197 runAdvance += glyph.fAdvance;
1198 }
1199 run.fAdvance = runAdvance;
1200
1201 return run;
1202}