blob: 821c0da5203aab3efb9523794a940ac1b1fe3dff [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 Wagnera8d94c12019-02-12 14:11:49 -0500309 if (fFont.unicharToGlyph(u)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400310 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 Wagnera8d94c12019-02-12 14:11:49 -0500313 } else if (fFallbackFont.getTypeface() && fFallbackFont.unicharToGlyph(u)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400314 fCurrentFont = &fFallbackFont;
Ben Wagnera900ad52018-08-31 17:48:19 -0400315 fCurrentHBFont = fFallbackHBFont.get();
Ben Wagner8d45a382017-11-16 10:08:28 -0500316 // If not, try to find a fallback typeface
317 } else {
Ben Wagnera8d94c12019-02-12 14:11:49 -0500318 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
319 nullptr, fFont.getTypeface()->fontStyle(), nullptr, 0, u));
320 if (candidate) {
321 fFallbackFont.setTypeface(std::move(candidate));
322 fFallbackHBFont = create_hb_font(fFallbackFont.getTypeface());
323 fCurrentFont = &fFallbackFont;
324 fCurrentHBFont = fFallbackHBFont.get();
325 } else {
326 fCurrentFont = &fFont;
327 fCurrentHBFont = fHBFont.get();
328 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500329 }
330
331 while (fCurrent < fEnd) {
332 const char* prev = fCurrent;
Hal Canaryf107a2f2018-07-25 16:52:48 -0400333 u = utf8_next(&fCurrent, fEnd);
Ben Wagner8d45a382017-11-16 10:08:28 -0500334
Ben Wagnera8d94c12019-02-12 14:11:49 -0500335 // End run if not using initial typeface and initial typeface has this character.
336 if (fCurrentFont->getTypeface() != fFont.getTypeface() && fFont.unicharToGlyph(u)) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500337 fCurrent = prev;
338 return;
339 }
Ben Wagnera8d94c12019-02-12 14:11:49 -0500340
341 // End run if current typeface does not have this character and some other font does.
342 if (!fCurrentFont->unicharToGlyph(u)) {
343 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
344 nullptr, fFont.getTypeface()->fontStyle(), nullptr, 0, u));
345 if (candidate) {
346 fCurrent = prev;
347 return;
348 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500349 }
350 }
351 }
352 const char* endOfCurrentRun() const override {
353 return fCurrent;
354 }
355 bool atEnd() const override {
356 return fCurrent == fEnd;
357 }
358
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400359 SkFont* currentFont() const {
360 return fCurrentFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500361 }
362 hb_font_t* currentHBFont() const {
363 return fCurrentHBFont;
364 }
365private:
366 const char* fCurrent;
367 const char* fEnd;
368 sk_sp<SkFontMgr> fFallbackMgr;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400369 HBFont fHBFont;
370 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500371 HBFont fFallbackHBFont;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400372 SkFont fFallbackFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500373 hb_font_t* fCurrentHBFont;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400374 SkFont* fCurrentFont;
375};
376
377class LanguageRunIterator : public RunIterator {
378public:
379 static SkTLazy<LanguageRunIterator> Make(const char* utf8, size_t utf8Bytes) {
380 SkTLazy<LanguageRunIterator> ret;
381 ret.init(utf8, utf8Bytes);
382 return ret;
383 }
384 LanguageRunIterator(const char* utf8, size_t utf8Bytes)
385 : fCurrent(utf8), fEnd(fCurrent + utf8Bytes)
386 , fLanguage(hb_language_from_string(std::locale().name().c_str(), -1))
387 { }
388 void consume() override {
389 // Ideally something like cld2/3 could be used, or user signals.
390 SkASSERT(fCurrent < fEnd);
391 fCurrent = fEnd;
392 }
393 const char* endOfCurrentRun() const override {
394 return fCurrent;
395 }
396 bool atEnd() const override {
397 return fCurrent == fEnd;
398 }
399
400 hb_language_t currentLanguage() const {
401 return fLanguage;
402 }
403private:
404 const char* fCurrent;
405 const char* fEnd;
406 hb_language_t fLanguage;
Ben Wagner8d45a382017-11-16 10:08:28 -0500407};
408
409class RunIteratorQueue {
410public:
411 void insert(RunIterator* runIterator) {
412 fRunIterators.insert(runIterator);
413 }
414
415 bool advanceRuns() {
416 const RunIterator* leastRun = fRunIterators.peek();
417 if (leastRun->atEnd()) {
418 SkASSERT(this->allRunsAreAtEnd());
419 return false;
420 }
421 const char* leastEnd = leastRun->endOfCurrentRun();
422 RunIterator* currentRun = nullptr;
423 SkDEBUGCODE(const char* previousEndOfCurrentRun);
424 while ((currentRun = fRunIterators.peek())->endOfCurrentRun() <= leastEnd) {
425 fRunIterators.pop();
426 SkDEBUGCODE(previousEndOfCurrentRun = currentRun->endOfCurrentRun());
427 currentRun->consume();
428 SkASSERT(previousEndOfCurrentRun < currentRun->endOfCurrentRun());
429 fRunIterators.insert(currentRun);
430 }
431 return true;
432 }
433
434 const char* endOfCurrentRun() const {
435 return fRunIterators.peek()->endOfCurrentRun();
436 }
437
438private:
439 bool allRunsAreAtEnd() const {
440 for (int i = 0; i < fRunIterators.count(); ++i) {
441 if (!fRunIterators.at(i)->atEnd()) {
442 return false;
443 }
444 }
445 return true;
446 }
447
448 static bool CompareRunIterator(RunIterator* const& a, RunIterator* const& b) {
449 return *a < *b;
450 }
451 SkTDPQueue<RunIterator*, CompareRunIterator> fRunIterators;
452};
453
454struct ShapedGlyph {
455 SkGlyphID fID;
456 uint32_t fCluster;
457 SkPoint fOffset;
458 SkVector fAdvance;
459 bool fMayLineBreakBefore;
460 bool fMustLineBreakBefore;
461 bool fHasVisual;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400462 bool fGraphemeBreakBefore;
463 bool fUnsafeToBreak;
Ben Wagner8d45a382017-11-16 10:08:28 -0500464};
465struct ShapedRun {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500466 ShapedRun(SkSpan<const char> utf8, const SkFont& font, UBiDiLevel level,
467 std::unique_ptr<ShapedGlyph[]> glyphs, int numGlyphs)
468 : fUtf8(utf8), fFont(font), fLevel(level)
469 , fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs)
Ben Wagner8d45a382017-11-16 10:08:28 -0500470 {}
471
Ben Wagner454e5fb2019-02-08 17:46:38 -0500472 SkSpan<const char> fUtf8;
Mike Reed6d595682018-12-05 17:28:14 -0500473 SkFont fFont;
Ben Wagner8d45a382017-11-16 10:08:28 -0500474 UBiDiLevel fLevel;
475 std::unique_ptr<ShapedGlyph[]> fGlyphs;
Ben Wagner454e5fb2019-02-08 17:46:38 -0500476 int fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -0500477 SkVector fAdvance = { 0, 0 };
Ben Wagner8d45a382017-11-16 10:08:28 -0500478};
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400479struct ShapedLine {
480 SkTArray<ShapedRun> runs;
481 SkVector fAdvance = { 0, 0 };
482};
Ben Wagner8d45a382017-11-16 10:08:28 -0500483
484static constexpr bool is_LTR(UBiDiLevel level) {
485 return (level & 1) == 0;
486}
487
Florin Malita950243d2019-01-11 11:08:35 -0500488static void append(SkShaper::RunHandler* handler, const SkShaper::RunHandler::RunInfo& runInfo,
489 const ShapedRun& run, int start, int end,
Florin Malita9867f612018-12-12 10:54:49 -0500490 SkPoint* p) {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500491 const unsigned len = end - start;
Florin Malita9867f612018-12-12 10:54:49 -0500492
Ben Wagner454e5fb2019-02-08 17:46:38 -0500493 const auto buffer = handler->newRunBuffer(runInfo, run.fFont, len, run.fUtf8);
Florin Malita9867f612018-12-12 10:54:49 -0500494 SkASSERT(buffer.glyphs);
495 SkASSERT(buffer.positions);
496
Ben Wagner8d45a382017-11-16 10:08:28 -0500497 for (unsigned i = 0; i < len; i++) {
498 // Glyphs are in logical order, but output ltr since PDF readers seem to expect that.
499 const ShapedGlyph& glyph = run.fGlyphs[is_LTR(run.fLevel) ? start + i : end - 1 - i];
Florin Malita9867f612018-12-12 10:54:49 -0500500 buffer.glyphs[i] = glyph.fID;
501 buffer.positions[i] = SkPoint::Make(p->fX + glyph.fOffset.fX, p->fY - glyph.fOffset.fY);
502 if (buffer.clusters) {
503 buffer.clusters[i] = glyph.fCluster;
504 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500505 p->fX += glyph.fAdvance.fX;
506 p->fY += glyph.fAdvance.fY;
507 }
Ben Wagner454e5fb2019-02-08 17:46:38 -0500508 handler->commitRun();
Ben Wagner8d45a382017-11-16 10:08:28 -0500509}
510
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400511static void emit(const ShapedLine& line, SkShaper::RunHandler* handler,
Florin Malita500133b2019-02-07 10:56:55 -0500512 SkPoint point, SkPoint& currentPoint)
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400513{
514 // Reorder the runs and glyphs per line and write them out.
515 SkScalar maxAscent = 0;
516 SkScalar maxDescent = 0;
517 SkScalar maxLeading = 0;
518 for (const ShapedRun& run : line.runs) {
519 SkFontMetrics metrics;
520 run.fFont.getMetrics(&metrics);
521 maxAscent = SkTMin(maxAscent, metrics.fAscent);
522 maxDescent = SkTMax(maxDescent, metrics.fDescent);
523 maxLeading = SkTMax(maxLeading, metrics.fLeading);
524 }
525
526 int numRuns = line.runs.size();
527 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
528 for (int i = 0; i < numRuns; ++i) {
529 runLevels[i] = line.runs[i].fLevel;
530 }
531 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
532 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
533
534 currentPoint.fY -= maxAscent;
535
536 for (int i = 0; i < numRuns; ++i) {
537 int logicalIndex = logicalFromVisual[i];
538
539 const auto& run = line.runs[logicalIndex];
540 const SkShaper::RunHandler::RunInfo info = {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400541 run.fAdvance,
542 maxAscent,
543 maxDescent,
544 maxLeading,
545 };
546 append(handler, info, run, 0, run.fNumGlyphs, &currentPoint);
547 }
548
549 currentPoint.fY += maxDescent + maxLeading;
550 currentPoint.fX = point.fX;
551
Florin Malita500133b2019-02-07 10:56:55 -0500552 handler->commitLine();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400553}
554
Ben Wagner8d45a382017-11-16 10:08:28 -0500555struct ShapedRunGlyphIterator {
556 ShapedRunGlyphIterator(const SkTArray<ShapedRun>& origRuns)
557 : fRuns(&origRuns), fRunIndex(0), fGlyphIndex(0)
558 { }
559
560 ShapedRunGlyphIterator(const ShapedRunGlyphIterator& that) = default;
561 ShapedRunGlyphIterator& operator=(const ShapedRunGlyphIterator& that) = default;
562 bool operator==(const ShapedRunGlyphIterator& that) const {
563 return fRuns == that.fRuns &&
564 fRunIndex == that.fRunIndex &&
565 fGlyphIndex == that.fGlyphIndex;
566 }
567 bool operator!=(const ShapedRunGlyphIterator& that) const {
568 return fRuns != that.fRuns ||
569 fRunIndex != that.fRunIndex ||
570 fGlyphIndex != that.fGlyphIndex;
571 }
572
573 ShapedGlyph* next() {
574 const SkTArray<ShapedRun>& runs = *fRuns;
575 SkASSERT(fRunIndex < runs.count());
576 SkASSERT(fGlyphIndex < runs[fRunIndex].fNumGlyphs);
577
578 ++fGlyphIndex;
579 if (fGlyphIndex == runs[fRunIndex].fNumGlyphs) {
580 fGlyphIndex = 0;
581 ++fRunIndex;
582 if (fRunIndex >= runs.count()) {
583 return nullptr;
584 }
585 }
586 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
587 }
588
589 ShapedGlyph* current() {
590 const SkTArray<ShapedRun>& runs = *fRuns;
591 if (fRunIndex >= runs.count()) {
592 return nullptr;
593 }
594 return &runs[fRunIndex].fGlyphs[fGlyphIndex];
595 }
596
597 const SkTArray<ShapedRun>* fRuns;
598 int fRunIndex;
599 int fGlyphIndex;
600};
601
602} // namespace
603
604struct SkShaper::Impl {
605 HBFont fHarfBuzzFont;
606 HBBuffer fBuffer;
607 sk_sp<SkTypeface> fTypeface;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400608 ICUBrk fLineBreakIterator;
609 ICUBrk fGraphemeBreakIterator;
610
611 SkPoint shapeCorrect(RunHandler* handler,
612 const char* utf8,
613 size_t utf8Bytes,
614 SkPoint point,
615 SkScalar width,
616 RunIteratorQueue& runSegmenter,
617 const BiDiRunIterator* bidi,
618 const LanguageRunIterator* language,
619 const ScriptRunIterator* script,
620 const FontRunIterator* font) const;
621
622 SkPoint shapeOk(RunHandler* handler,
623 const char* utf8,
624 size_t utf8Bytes,
625 SkPoint point,
626 SkScalar width,
627 RunIteratorQueue& runSegmenter,
628 const BiDiRunIterator* bidi,
629 const LanguageRunIterator* language,
630 const ScriptRunIterator* script,
631 const FontRunIterator* font) const;
632
633 ShapedRun shape(const char* utf8,
634 size_t utf8Bytes,
635 const char* utf8Start,
636 const char* utf8End,
637 const BiDiRunIterator* bidi,
638 const LanguageRunIterator* language,
639 const ScriptRunIterator* script,
640 const FontRunIterator* font) const;
Ben Wagner8d45a382017-11-16 10:08:28 -0500641};
642
Ben Wagnere0001732017-08-31 16:26:26 -0400643SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
Hal Canary61021922019-02-06 12:29:11 -0500644#if defined(SK_USING_THIRD_PARTY_ICU)
645 if (!SkLoadICU()) {
646 SkDebugf("SkLoadICU() failed!\n");
647 return;
648 }
649#endif
Ben Wagnere0001732017-08-31 16:26:26 -0400650 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
651 fImpl->fHarfBuzzFont = create_hb_font(fImpl->fTypeface.get());
Florin Malitaa4e1a632019-01-22 16:27:01 -0500652 if (!fImpl->fHarfBuzzFont) {
653 SkDebugf("create_hb_font failed!\n");
654 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400655 fImpl->fBuffer.reset(hb_buffer_create());
Ben Wagner8d45a382017-11-16 10:08:28 -0500656 SkASSERT(fImpl->fBuffer);
657
Ben Wagner8d45a382017-11-16 10:08:28 -0500658 UErrorCode status = U_ZERO_ERROR;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400659 fImpl->fLineBreakIterator.reset(ubrk_open(UBRK_LINE, "th", nullptr, 0, &status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500660 if (U_FAILURE(status)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400661 SkDebugf("Could not create line break iterator: %s", u_errorName(status));
Ben Wagner8d45a382017-11-16 10:08:28 -0500662 SK_ABORT("");
663 }
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400664
665 fImpl->fGraphemeBreakIterator.reset(ubrk_open(UBRK_CHARACTER, "th", nullptr, 0, &status));
666 if (U_FAILURE(status)) {
667 SkDebugf("Could not create grapheme break iterator: %s", u_errorName(status));
668 SK_ABORT("");
669 }
670
Ben Wagnera25fbef2017-08-30 13:56:19 -0400671}
672
673SkShaper::~SkShaper() {}
674
Ben Wagner8d45a382017-11-16 10:08:28 -0500675bool SkShaper::good() const {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400676 return fImpl->fBuffer &&
677 fImpl->fLineBreakIterator &&
678 fImpl->fGraphemeBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500679}
Ben Wagnera25fbef2017-08-30 13:56:19 -0400680
Florin Malita950243d2019-01-11 11:08:35 -0500681SkPoint SkShaper::shape(RunHandler* handler,
Kevin Lubick57abfe92019-01-28 13:15:51 -0500682 const SkFont& srcFont,
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500683 const char* utf8,
684 size_t utf8Bytes,
685 bool leftToRight,
686 SkPoint point,
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400687 SkScalar width) const
Ben Wagner8d45a382017-11-16 10:08:28 -0500688{
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400689 SkASSERT(handler);
690 sk_sp<SkFontMgr> fontMgr = SkFontMgr::RefDefault();
691 UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
692
Ben Wagner8d45a382017-11-16 10:08:28 -0500693 RunIteratorQueue runSegmenter;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400694
Ben Wagner8d45a382017-11-16 10:08:28 -0500695 SkTLazy<BiDiRunIterator> maybeBidi(BiDiRunIterator::Make(utf8, utf8Bytes, defaultLevel));
696 BiDiRunIterator* bidi = maybeBidi.getMaybeNull();
697 if (!bidi) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500698 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400699 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500700 runSegmenter.insert(bidi);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400701
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400702 SkTLazy<LanguageRunIterator> maybeLanguage(LanguageRunIterator::Make(utf8, utf8Bytes));
703 LanguageRunIterator* language = maybeLanguage.getMaybeNull();
704 if (!language) {
705 return point;
706 }
707 runSegmenter.insert(language);
708
Ben Wagner8d45a382017-11-16 10:08:28 -0500709 hb_unicode_funcs_t* hbUnicode = hb_buffer_get_unicode_funcs(fImpl->fBuffer.get());
710 SkTLazy<ScriptRunIterator> maybeScript(ScriptRunIterator::Make(utf8, utf8Bytes, hbUnicode));
711 ScriptRunIterator* script = maybeScript.getMaybeNull();
712 if (!script) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500713 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400714 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500715 runSegmenter.insert(script);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400716
Ben Wagner8d45a382017-11-16 10:08:28 -0500717 SkTLazy<FontRunIterator> maybeFont(FontRunIterator::Make(utf8, utf8Bytes,
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400718 srcFont, std::move(fontMgr)));
Ben Wagner8d45a382017-11-16 10:08:28 -0500719 FontRunIterator* font = maybeFont.getMaybeNull();
720 if (!font) {
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500721 return point;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400722 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500723 runSegmenter.insert(font);
Ben Wagnera25fbef2017-08-30 13:56:19 -0400724
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400725 if (true) {
726 return fImpl->shapeCorrect(handler, utf8, utf8Bytes, point, width,
727 runSegmenter, bidi, language, script, font);
728 } else {
729 return fImpl->shapeOk(handler, utf8, utf8Bytes, point, width,
730 runSegmenter, bidi, language, script, font);
731 }
732}
733
734SkPoint SkShaper::Impl::shapeCorrect(RunHandler* handler,
735 const char* utf8,
736 size_t utf8Bytes,
737 SkPoint point,
738 SkScalar width,
739 RunIteratorQueue& runSegmenter,
740 const BiDiRunIterator* bidi,
741 const LanguageRunIterator* language,
742 const ScriptRunIterator* script,
743 const FontRunIterator* font) const
744{
745 ShapedLine line;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400746 SkPoint currentPoint = point;
747
748 const char* utf8Start = nullptr;
749 const char* utf8End = utf8;
750 while (runSegmenter.advanceRuns()) { // For each item
751 utf8Start = utf8End;
752 utf8End = runSegmenter.endOfCurrentRun();
753
Ben Wagner454e5fb2019-02-08 17:46:38 -0500754 ShapedRun model(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400755 bool modelNeedsRegenerated = true;
756 int modelOffset = 0;
757
758 struct TextProps {
759 int glyphLen = 0;
760 SkVector advance = {0, 0};
761 };
762 // map from character position to [safe to break, glyph position, advance]
763 std::unique_ptr<TextProps[]> modelText;
764 int modelTextOffset = 0;
765 SkVector modelTextAdvanceOffset = {0, 0};
766
767 while (utf8Start < utf8End) { // While there are still code points left in this item
768 size_t utf8runLength = utf8End - utf8Start;
769 if (modelNeedsRegenerated) {
770 model = shape(utf8, utf8Bytes,
771 utf8Start, utf8End,
772 bidi, language, script, font);
773 modelOffset = 0;
774
775 SkVector advance = {0, 0};
776 modelText.reset(new TextProps[utf8runLength + 1]());
Ben Wagnerb9cc1c62019-02-14 14:12:48 -0500777 size_t modelStartCluster = utf8Start - utf8;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400778 for (int i = 0; i < model.fNumGlyphs; ++i) {
Ben Wagnerb9cc1c62019-02-14 14:12:48 -0500779 SkASSERT(modelStartCluster <= model.fGlyphs[i].fCluster < utf8End - utf8);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400780 if (!model.fGlyphs[i].fUnsafeToBreak) {
Ben Wagnerb9cc1c62019-02-14 14:12:48 -0500781 modelText[model.fGlyphs[i].fCluster - modelStartCluster].glyphLen = i;
782 modelText[model.fGlyphs[i].fCluster - modelStartCluster].advance = advance;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400783 }
784 advance += model.fGlyphs[i].fAdvance;
785 }
786 // Assume it is always safe to break after the end of an item
787 modelText[utf8runLength].glyphLen = model.fNumGlyphs;
788 modelText[utf8runLength].advance = model.fAdvance;
789 modelTextOffset = 0;
790 modelTextAdvanceOffset = {0, 0};
791 modelNeedsRegenerated = false;
792 }
793
794 // TODO: break iterator per item, but just reset position if needed?
795 // Maybe break iterator with model?
796 UBreakIterator& breakIterator = *fLineBreakIterator;
797 {
798 UErrorCode status = U_ZERO_ERROR;
799 UText utf8UText = UTEXT_INITIALIZER;
800 utext_openUTF8(&utf8UText, utf8Start, utf8runLength, &status);
801 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
802 if (U_FAILURE(status)) {
803 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
804 return point;
805 }
806 ubrk_setUText(&breakIterator, &utf8UText, &status);
807 if (U_FAILURE(status)) {
808 SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
809 return point;
810 }
811 }
812
Ben Wagner454e5fb2019-02-08 17:46:38 -0500813 ShapedRun best(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400814 best.fAdvance = { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity };
815 SkScalar widthLeft = width - line.fAdvance.fX;
816
817 for (int32_t breakIteratorCurrent = ubrk_next(&breakIterator);
818 breakIteratorCurrent != UBRK_DONE;
819 breakIteratorCurrent = ubrk_next(&breakIterator))
820 {
821 // TODO: if past a safe to break, future safe to break will be at least as long
822
823 // TODO: adjust breakIteratorCurrent by ignorable whitespace
824 ShapedRun candidate = modelText[breakIteratorCurrent + modelTextOffset].glyphLen
Ben Wagner454e5fb2019-02-08 17:46:38 -0500825 ? ShapedRun(SkSpan<const char>(utf8Start, breakIteratorCurrent),
826 *font->currentFont(), bidi->currentLevel(),
827 std::unique_ptr<ShapedGlyph[]>(),
828 modelText[breakIteratorCurrent + modelTextOffset].glyphLen - modelOffset)
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400829 : shape(utf8, utf8Bytes,
830 utf8Start, utf8Start + breakIteratorCurrent,
831 bidi, language, script, font);
Ben Wagner454e5fb2019-02-08 17:46:38 -0500832 if (!candidate.fUtf8.data()) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400833 //report error
834 return point;
835 }
836 if (!candidate.fGlyphs) {
837 candidate.fAdvance = modelText[breakIteratorCurrent + modelTextOffset].advance - modelTextAdvanceOffset;
838 }
839 auto score = [widthLeft](const ShapedRun& run) -> SkScalar {
840 if (run.fAdvance.fX < widthLeft) {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500841 if (run.fUtf8.data() == nullptr) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400842 return SK_ScalarNegativeInfinity;
843 } else {
Ben Wagner454e5fb2019-02-08 17:46:38 -0500844 return run.fUtf8.size();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400845 }
846 } else {
847 return widthLeft - run.fAdvance.fX;
848 }
849 };
850 if (score(best) < score(candidate)) {
851 best = std::move(candidate);
852 }
853 }
854
855 // If nothing fit (best score is negative) and the line is not empty
856 if (width < line.fAdvance.fX + best.fAdvance.fX && !line.runs.empty()) {
Florin Malita500133b2019-02-07 10:56:55 -0500857 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400858 line.runs.reset();
859 line.fAdvance = {0, 0};
860 } else {
861 if (!best.fGlyphs) {
862 best.fGlyphs.reset(new ShapedGlyph[best.fNumGlyphs]);
863 memcpy(best.fGlyphs.get(), model.fGlyphs.get() + modelOffset,
864 best.fNumGlyphs * sizeof(ShapedGlyph));
865 modelOffset += best.fNumGlyphs;
Ben Wagner454e5fb2019-02-08 17:46:38 -0500866 modelTextOffset += best.fUtf8.size();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400867 modelTextAdvanceOffset += best.fAdvance;
868 } else {
869 modelNeedsRegenerated = true;
870 }
Ben Wagner454e5fb2019-02-08 17:46:38 -0500871 utf8Start = best.fUtf8.end();
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400872 line.fAdvance += best.fAdvance;
873 line.runs.emplace_back(std::move(best));
874
875 // If item broken, emit line (prevent remainder from accidentally fitting)
876 if (utf8Start != utf8End) {
Florin Malita500133b2019-02-07 10:56:55 -0500877 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400878 line.runs.reset();
879 line.fAdvance = {0, 0};
880 }
881 }
882 }
883 }
Florin Malita500133b2019-02-07 10:56:55 -0500884 emit(line, handler, point, currentPoint);
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400885 return currentPoint;
886}
887
888SkPoint SkShaper::Impl::shapeOk(RunHandler* handler,
889 const char* utf8,
890 size_t utf8Bytes,
891 SkPoint point,
892 SkScalar width,
893 RunIteratorQueue& runSegmenter,
894 const BiDiRunIterator* bidi,
895 const LanguageRunIterator* language,
896 const ScriptRunIterator* script,
897 const FontRunIterator* font) const
898{
899 SkTArray<ShapedRun> runs;
900{
901 UBreakIterator& lineBreakIterator = *fLineBreakIterator;
902 UBreakIterator& graphemeBreakIterator = *fGraphemeBreakIterator;
Ben Wagner8d45a382017-11-16 10:08:28 -0500903 {
904 UErrorCode status = U_ZERO_ERROR;
905 UText utf8UText = UTEXT_INITIALIZER;
906 utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
907 std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
908 if (U_FAILURE(status)) {
909 SkDebugf("Could not create utf8UText: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500910 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500911 }
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400912
913 ubrk_setUText(&lineBreakIterator, &utf8UText, &status);
Ben Wagner8d45a382017-11-16 10:08:28 -0500914 if (U_FAILURE(status)) {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400915 SkDebugf("Could not setText on line break iterator: %s", u_errorName(status));
916 return point;
917 }
918 ubrk_setUText(&graphemeBreakIterator, &utf8UText, &status);
919 if (U_FAILURE(status)) {
920 SkDebugf("Could not setText on grapheme break iterator: %s", u_errorName(status));
Ben Wagner5d4dd8b2018-01-25 14:37:17 -0500921 return point;
Ben Wagner8d45a382017-11-16 10:08:28 -0500922 }
Ben Wagnera25fbef2017-08-30 13:56:19 -0400923 }
924
Ben Wagner8d45a382017-11-16 10:08:28 -0500925 const char* utf8Start = nullptr;
926 const char* utf8End = utf8;
927 while (runSegmenter.advanceRuns()) {
928 utf8Start = utf8End;
929 utf8End = runSegmenter.endOfCurrentRun();
930
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400931 runs.emplace_back(shape(utf8, utf8Bytes,
932 utf8Start, utf8End,
933 bidi, language, script, font));
934 ShapedRun& run = runs.back();
Ben Wagnera25fbef2017-08-30 13:56:19 -0400935
Ben Wagner8d45a382017-11-16 10:08:28 -0500936 uint32_t previousCluster = 0xFFFFFFFF;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400937 for (int i = 0; i < run.fNumGlyphs; ++i) {
Ben Wagner8d45a382017-11-16 10:08:28 -0500938 ShapedGlyph& glyph = run.fGlyphs[i];
Ben Wagnerb9cc1c62019-02-14 14:12:48 -0500939 int32_t glyphCluster = glyph.fCluster;
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400940
941 int32_t lineBreakIteratorCurrent = ubrk_current(&lineBreakIterator);
942 while (lineBreakIteratorCurrent != UBRK_DONE &&
943 lineBreakIteratorCurrent < glyphCluster)
Ben Wagner8d45a382017-11-16 10:08:28 -0500944 {
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400945 lineBreakIteratorCurrent = ubrk_next(&lineBreakIterator);
Ben Wagner2868b782017-08-31 14:12:27 -0400946 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500947 glyph.fMayLineBreakBefore = glyph.fCluster != previousCluster &&
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400948 lineBreakIteratorCurrent == glyphCluster;
949
950 int32_t graphemeBreakIteratorCurrent = ubrk_current(&graphemeBreakIterator);
951 while (graphemeBreakIteratorCurrent != UBRK_DONE &&
952 graphemeBreakIteratorCurrent < glyphCluster)
953 {
954 graphemeBreakIteratorCurrent = ubrk_next(&graphemeBreakIterator);
955 }
956 glyph.fGraphemeBreakBefore = glyph.fCluster != previousCluster &&
957 graphemeBreakIteratorCurrent == glyphCluster;
958
Ben Wagner8d45a382017-11-16 10:08:28 -0500959 previousCluster = glyph.fCluster;
Ben Wagnera25fbef2017-08-30 13:56:19 -0400960 }
961 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500962}
963
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400964// Iterate over the glyphs in logical order to find potential line lengths.
Ben Wagner8d45a382017-11-16 10:08:28 -0500965{
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400966 /** The position of the beginning of the line. */
967 ShapedRunGlyphIterator beginning(runs);
968
969 /** The position of the candidate line break. */
970 ShapedRunGlyphIterator candidateLineBreak(runs);
971 SkScalar candidateLineBreakWidth = 0;
972
973 /** The position of the candidate grapheme break. */
974 ShapedRunGlyphIterator candidateGraphemeBreak(runs);
975 SkScalar candidateGraphemeBreakWidth = 0;
976
977 /** The position of the current location. */
978 ShapedRunGlyphIterator current(runs);
979 SkScalar currentWidth = 0;
980 while (ShapedGlyph* glyph = current.current()) {
981 // 'Break' at graphemes until a line boundary, then only at line boundaries.
982 // Only break at graphemes if no line boundary is valid.
983 if (current != beginning) {
984 if (glyph->fGraphemeBreakBefore || glyph->fMayLineBreakBefore) {
985 // TODO: preserve line breaks <= grapheme breaks
986 // and prevent line breaks inside graphemes
987 candidateGraphemeBreak = current;
988 candidateGraphemeBreakWidth = currentWidth;
989 if (glyph->fMayLineBreakBefore) {
990 candidateLineBreak = current;
991 candidateLineBreakWidth = currentWidth;
992 }
993 }
Ben Wagner8d45a382017-11-16 10:08:28 -0500994 }
995
Ben Wagner0ec8ec22018-09-04 18:17:13 -0400996 SkScalar glyphWidth = glyph->fAdvance.fX;
997 // Break when overwidth, the glyph has a visual representation, and some space is used.
998 if (width < currentWidth + glyphWidth && glyph->fHasVisual && candidateGraphemeBreakWidth > 0){
999 if (candidateLineBreak != beginning) {
1000 beginning = candidateLineBreak;
1001 currentWidth -= candidateLineBreakWidth;
1002 candidateGraphemeBreakWidth -= candidateLineBreakWidth;
1003 candidateLineBreakWidth = 0;
1004 } else if (candidateGraphemeBreak != beginning) {
1005 beginning = candidateGraphemeBreak;
1006 candidateLineBreak = beginning;
1007 currentWidth -= candidateGraphemeBreakWidth;
1008 candidateGraphemeBreakWidth = 0;
1009 candidateLineBreakWidth = 0;
1010 } else {
1011 SK_ABORT("");
1012 }
1013
1014 if (width < currentWidth) {
1015 if (width < candidateGraphemeBreakWidth) {
1016 candidateGraphemeBreak = candidateLineBreak;
1017 candidateGraphemeBreakWidth = candidateLineBreakWidth;
1018 }
1019 current = candidateGraphemeBreak;
1020 currentWidth = candidateGraphemeBreakWidth;
1021 }
1022
1023 glyph = beginning.current();
1024 if (glyph) {
1025 glyph->fMustLineBreakBefore = true;
1026 }
1027
1028 } else {
1029 current.next();
1030 currentWidth += glyphWidth;
Ben Wagner8d45a382017-11-16 10:08:28 -05001031 }
Ben Wagner8d45a382017-11-16 10:08:28 -05001032 }
1033}
1034
1035// Reorder the runs and glyphs per line and write them out.
Ben Wagner5d4dd8b2018-01-25 14:37:17 -05001036 SkPoint currentPoint = point;
Ben Wagner8d45a382017-11-16 10:08:28 -05001037{
1038 ShapedRunGlyphIterator previousBreak(runs);
1039 ShapedRunGlyphIterator glyphIterator(runs);
1040 SkScalar maxAscent = 0;
1041 SkScalar maxDescent = 0;
1042 SkScalar maxLeading = 0;
1043 int previousRunIndex = -1;
1044 while (glyphIterator.current()) {
1045 int runIndex = glyphIterator.fRunIndex;
1046 int glyphIndex = glyphIterator.fGlyphIndex;
1047 ShapedGlyph* nextGlyph = glyphIterator.next();
1048
1049 if (previousRunIndex != runIndex) {
Mike Reedb5784ac2018-11-12 09:35:15 -05001050 SkFontMetrics metrics;
Mike Reed6d595682018-12-05 17:28:14 -05001051 runs[runIndex].fFont.getMetrics(&metrics);
Ben Wagner8d45a382017-11-16 10:08:28 -05001052 maxAscent = SkTMin(maxAscent, metrics.fAscent);
1053 maxDescent = SkTMax(maxDescent, metrics.fDescent);
1054 maxLeading = SkTMax(maxLeading, metrics.fLeading);
1055 previousRunIndex = runIndex;
1056 }
1057
1058 // Nothing can be written until the baseline is known.
1059 if (!(nextGlyph == nullptr || nextGlyph->fMustLineBreakBefore)) {
1060 continue;
1061 }
1062
1063 currentPoint.fY -= maxAscent;
1064
1065 int numRuns = runIndex - previousBreak.fRunIndex + 1;
1066 SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
1067 for (int i = 0; i < numRuns; ++i) {
1068 runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
1069 }
1070 SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
1071 ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
1072
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001073 // step through the runs in reverse visual order and the glyphs in reverse logical order
1074 // until a visible glyph is found and force them to the end of the visual line.
1075
Ben Wagner8d45a382017-11-16 10:08:28 -05001076 for (int i = 0; i < numRuns; ++i) {
1077 int logicalIndex = previousBreak.fRunIndex + logicalFromVisual[i];
1078
1079 int startGlyphIndex = (logicalIndex == previousBreak.fRunIndex)
1080 ? previousBreak.fGlyphIndex
1081 : 0;
1082 int endGlyphIndex = (logicalIndex == runIndex)
1083 ? glyphIndex + 1
1084 : runs[logicalIndex].fNumGlyphs;
Florin Malita950243d2019-01-11 11:08:35 -05001085
1086 const auto& run = runs[logicalIndex];
1087 const RunHandler::RunInfo info = {
Florin Malita950243d2019-01-11 11:08:35 -05001088 run.fAdvance,
1089 maxAscent,
1090 maxDescent,
1091 maxLeading,
1092 };
1093 append(handler, info, run, startGlyphIndex, endGlyphIndex, &currentPoint);
Ben Wagner8d45a382017-11-16 10:08:28 -05001094 }
1095
Florin Malita500133b2019-02-07 10:56:55 -05001096 handler->commitLine();
1097
Ben Wagner8d45a382017-11-16 10:08:28 -05001098 currentPoint.fY += maxDescent + maxLeading;
1099 currentPoint.fX = point.fX;
1100 maxAscent = 0;
1101 maxDescent = 0;
1102 maxLeading = 0;
1103 previousRunIndex = -1;
1104 previousBreak = glyphIterator;
1105 }
1106}
1107
Ben Wagner5d4dd8b2018-01-25 14:37:17 -05001108 return currentPoint;
Ben Wagnera25fbef2017-08-30 13:56:19 -04001109}
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001110
1111
1112ShapedRun SkShaper::Impl::shape(const char* utf8,
Ben Wagner2fc14742019-02-06 16:37:44 -05001113 const size_t utf8Bytes,
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001114 const char* utf8Start,
1115 const char* utf8End,
1116 const BiDiRunIterator* bidi,
1117 const LanguageRunIterator* language,
1118 const ScriptRunIterator* script,
1119 const FontRunIterator* font) const
1120{
Ben Wagner454e5fb2019-02-08 17:46:38 -05001121 ShapedRun run(SkSpan<const char>(), SkFont(), 0, nullptr, 0);
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001122
1123 hb_buffer_t* buffer = fBuffer.get();
1124 SkAutoTCallVProc<hb_buffer_t, hb_buffer_clear_contents> autoClearBuffer(buffer);
1125 hb_buffer_set_content_type(buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
1126 hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
1127
Ben Wagner2fc14742019-02-06 16:37:44 -05001128 // See 763e5466c0a03a7c27020e1e2598e488612529a7 for documentation.
1129 hb_buffer_set_flags(buffer, HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT);
1130
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001131 // Add precontext.
1132 hb_buffer_add_utf8(buffer, utf8, utf8Start - utf8, utf8Start - utf8, 0);
1133
1134 // Populate the hb_buffer directly with utf8 cluster indexes.
1135 const char* utf8Current = utf8Start;
1136 while (utf8Current < utf8End) {
Ben Wagnerb9cc1c62019-02-14 14:12:48 -05001137 unsigned int cluster = utf8Current - utf8;
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001138 hb_codepoint_t u = utf8_next(&utf8Current, utf8End);
1139 hb_buffer_add(buffer, u, cluster);
1140 }
1141
1142 // Add postcontext.
1143 hb_buffer_add_utf8(buffer, utf8Current, utf8 + utf8Bytes - utf8Current, 0, 0);
1144
1145 size_t utf8runLength = utf8End - utf8Start;
1146 if (!SkTFitsIn<int>(utf8runLength)) {
1147 SkDebugf("Shaping error: utf8 too long");
1148 return run;
1149 }
1150 hb_direction_t direction = is_LTR(bidi->currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
1151 hb_buffer_set_direction(buffer, direction);
1152 hb_buffer_set_script(buffer, script->currentScript());
1153 hb_buffer_set_language(buffer, language->currentLanguage());
1154 hb_buffer_guess_segment_properties(buffer);
1155 // TODO: features
1156 if (!font->currentHBFont()) {
1157 return run;
1158 }
1159 hb_shape(font->currentHBFont(), buffer, nullptr, 0);
1160 unsigned len = hb_buffer_get_length(buffer);
1161 if (len == 0) {
1162 // TODO: this isn't an error, make it look different
1163 return run;
1164 }
1165
1166 if (direction == HB_DIRECTION_RTL) {
1167 // Put the clusters back in logical order.
1168 // Note that the advances remain ltr.
1169 hb_buffer_reverse(buffer);
1170 }
1171 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, nullptr);
1172 hb_glyph_position_t* pos = hb_buffer_get_glyph_positions(buffer, nullptr);
1173
1174 if (!SkTFitsIn<int>(len)) {
1175 SkDebugf("Shaping error: too many glyphs");
1176 return run;
1177 }
1178
Ben Wagner454e5fb2019-02-08 17:46:38 -05001179 run = ShapedRun(SkSpan<const char>(utf8Start, utf8runLength),
1180 *font->currentFont(), bidi->currentLevel(),
1181 std::unique_ptr<ShapedGlyph[]>(new ShapedGlyph[len]), len);
Ben Wagner0ec8ec22018-09-04 18:17:13 -04001182 int scaleX, scaleY;
1183 hb_font_get_scale(font->currentHBFont(), &scaleX, &scaleY);
1184 double textSizeY = run.fFont.getSize() / scaleY;
1185 double textSizeX = run.fFont.getSize() / scaleX * run.fFont.getScaleX();
1186 SkVector runAdvance = { 0, 0 };
1187 for (unsigned i = 0; i < len; i++) {
1188 ShapedGlyph& glyph = run.fGlyphs[i];
1189 glyph.fID = info[i].codepoint;
1190 glyph.fCluster = info[i].cluster;
1191 glyph.fOffset.fX = pos[i].x_offset * textSizeX;
1192 glyph.fOffset.fY = pos[i].y_offset * textSizeY;
1193 glyph.fAdvance.fX = pos[i].x_advance * textSizeX;
1194 glyph.fAdvance.fY = pos[i].y_advance * textSizeY;
1195
1196 SkRect bounds;
1197 SkScalar advance;
1198 SkPaint p;
1199 run.fFont.getWidthsBounds(&glyph.fID, 1, &advance, &bounds, &p);
1200 glyph.fHasVisual = !bounds.isEmpty(); //!font->currentTypeface()->glyphBoundsAreZero(glyph.fID);
1201 glyph.fUnsafeToBreak = info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
1202 glyph.fMustLineBreakBefore = false;
1203
1204 runAdvance += glyph.fAdvance;
1205 }
1206 run.fAdvance = runAdvance;
1207
1208 return run;
1209}