Flutter Engine
The Flutter Engine
TextBoxSlide.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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
12#include "include/core/SkPath.h"
22#include "src/base/SkRandom.h"
23#include "src/base/SkTime.h"
24#include "src/base/SkUTF.h"
25#include "src/core/SkOSFile.h"
27#include "tools/viewer/Slide.h"
28
29#if defined(SK_SHAPER_CORETEXT_AVAILABLE)
31#endif
32
33#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE)
35#endif
36
37#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
39#endif
40
41#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
43#endif
44
45#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
47#endif
48
49typedef std::unique_ptr<SkShaper> (*ShaperFactory)();
50
51static const char gText[] =
52 "When in the Course of human events it becomes necessary for one people "
53 "to dissolve the political bands which have connected them with another "
54 "and to assume among the powers of the earth, the separate and equal "
55 "station to which the Laws of Nature and of Nature's God entitle them, "
56 "a decent respect to the opinions of mankind requires that they should "
57 "declare the causes which impel them to the separation.";
58
59namespace {
61#if defined(SK_UNICODE_ICU_IMPLEMENTATION)
62 if (auto unicode = SkUnicodes::ICU::Make()) {
63 return unicode;
64 }
65#endif // defined(SK_UNICODE_ICU_IMPLEMENTATION)
66#if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
68 return unicode;
69 }
70#endif
71#if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
72 if (auto unicode = SkUnicodes::ICU4X::Make()) {
73 return unicode;
74 }
75#endif
76 return nullptr;
77}
78}
79
80using MakeBidiIteratorCallback = std::unique_ptr<SkShaper::BiDiRunIterator> (*)(sk_sp<SkUnicode> unicode,
81 const char* utf8,
82 size_t utf8Bytes,
83 uint8_t bidiLevel);
84using MakeScriptRunCallback = std::unique_ptr<SkShaper::ScriptRunIterator> (*)(
85 const char* utf8, size_t utf8Bytes, SkFourByteTag script);
86
87static std::unique_ptr<SkShaper::BiDiRunIterator> make_trivial_bidi(sk_sp<SkUnicode>,
88 const char*,
89 size_t utf8Bytes,
90 uint8_t bidiLevel) {
91 return std::make_unique<SkShaper::TrivialBiDiRunIterator>(bidiLevel, utf8Bytes);
92}
93
94#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
95static std::unique_ptr<SkShaper::BiDiRunIterator> make_unicode_bidi(sk_sp<SkUnicode> unicode,
96 const char* utf8,
97 size_t utf8Bytes,
98 uint8_t bidiLevel) {
99 if (auto bidi = SkShapers::unicode::BidiRunIterator(unicode, utf8, utf8Bytes, bidiLevel)) {
100 return bidi;
101 }
102 return make_trivial_bidi(unicode, utf8, utf8Bytes, bidiLevel);
103}
104#endif
105
106static std::unique_ptr<SkShaper::ScriptRunIterator> make_trivial_script_runner(
107 const char*, size_t utf8Bytes, SkFourByteTag scriptTag) {
108 return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
109}
110
111#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
112static std::unique_ptr<SkShaper::ScriptRunIterator> make_harfbuzz_script_runner(
113 const char* utf8, size_t utf8Bytes, SkFourByteTag scriptTag) {
114 std::unique_ptr<SkShaper::ScriptRunIterator> script =
115 SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes, scriptTag);
116 if (script) {
117 return script;
118 }
119 return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
120}
121#endif
122
123class TextBoxSlide : public Slide {
124public:
128 const char suffix[])
129 : fShaper(fact()), fBidiCallback(bidi), fScriptRunCallback(script) {
130 fName = SkStringPrintf("TextBox_%s", suffix);
131 }
132
133 void load(SkScalar w, SkScalar h) override { fSize = {w, h}; }
134
135 void resize(SkScalar w, SkScalar h) override { fSize = {w, h}; }
136
137 void draw(SkCanvas* canvas) override {
138 SkScalar width = fSize.width() / 3;
139 drawTest(canvas, width, fSize.height(), SK_ColorBLACK, SK_ColorWHITE);
140 canvas->translate(width, 0);
141 drawTest(canvas, width, fSize.height(), SK_ColorWHITE, SK_ColorBLACK);
142 canvas->translate(width, 0);
143 drawTest(canvas, width, fSize.height()/2, SK_ColorGRAY, SK_ColorWHITE);
144 canvas->translate(0, fSize.height()/2);
145 drawTest(canvas, width, fSize.height()/2, SK_ColorGRAY, SK_ColorBLACK);
146 }
147
148private:
149 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
150 SkAutoCanvasRestore acr(canvas, true);
151
152 canvas->clipRect(SkRect::MakeWH(w, h));
153 canvas->drawColor(bg);
154
155 SkScalar margin = 20;
156
158 paint.setColor(fg);
159
160 for (int i = 9; i < 24; i += 2) {
161#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
163#endif
164 SkTextBlobBuilderRunHandler builder(gText, { margin, margin });
165 SkFont srcFont(nullptr, SkIntToScalar(i));
166 srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
167 srcFont.setSubpixel(true);
168
169 const char* utf8 = gText;
170 size_t utf8Bytes = sizeof(gText) - 1;
171
172 auto unicode = get_unicode();
173 std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
174 fBidiCallback(unicode, utf8, utf8Bytes, 0xfe);
175 if (!bidi) {
176 return;
177 }
178
179 std::unique_ptr<SkShaper::LanguageRunIterator> language(
181 if (!language) {
182 return;
183 }
184
185 SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
186 std::unique_ptr<SkShaper::ScriptRunIterator> script =
187 fScriptRunCallback(utf8, utf8Bytes, undeterminedScript);
188 if (!script) {
189 return;
190 }
191
192 std::unique_ptr<SkShaper::FontRunIterator> font(
194 utf8Bytes,
195 srcFont,
197 "Arial",
199 &*language));
200 if (!font) {
201 return;
202 }
203
204 fShaper->shape(utf8,
205 utf8Bytes,
206 *font,
207 *bidi,
208 *script,
209 *language,
210 nullptr,
211 0,
212 w - margin,
213 &builder);
214 canvas->drawTextBlob(builder.makeBlob(), 0, 0, paint);
215
216 canvas->translate(0, builder.endPoint().y());
217 }
218 }
219
220 SkSize fSize;
221 std::unique_ptr<SkShaper> fShaper;
222 MakeBidiIteratorCallback fBidiCallback;
223 MakeScriptRunCallback fScriptRunCallback;
224};
225
229 "primitive"););
230
231#if defined(SK_SHAPER_CORETEXT_AVAILABLE)
235 "coretext"););
236#endif
237
238#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
239DEF_SLIDE(return new TextBoxSlide(
240 []() {
243 },
244 make_unicode_bidi,
245 make_harfbuzz_script_runner,
246 "harfbuzz"););
247#endif
248
249class ShaperSlide : public Slide {
250public:
251 ShaperSlide() { fName = "shaper"; }
252
253 void draw(SkCanvas* canvas) override {
254 canvas->translate(10, 30);
255
256 const char text[] = "world";
257
258 for (SkScalar size = 30; size <= 30; size += 10) {
259 this->drawTest(canvas,
260 text,
261 size,
265 canvas->translate(0, size + 5);
266#if defined(SK_SHAPER_CORETEXT_AVAILABLE)
267 this->drawTest(canvas,
268 text,
269 size,
273#endif
274 canvas->translate(0, size + 5);
275#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
276 auto unicode = get_unicode();
277 this->drawTest(
278 canvas,
279 text,
280 size,
282 make_unicode_bidi,
283 make_harfbuzz_script_runner);
284#endif
285 canvas->translate(0, size*2);
286 }
287 }
288
289private:
290 void drawTest(SkCanvas* canvas,
291 const char str[],
293 std::unique_ptr<SkShaper> shaper,
294 MakeBidiIteratorCallback bidiCallback,
295 MakeScriptRunCallback scriptRunCallback) {
296 if (!shaper) return;
297
299 SkFont srcFont;
300 srcFont.setSize(size);
301 srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
302 srcFont.setSubpixel(true);
303
304 size_t len = strlen(str);
305
306 auto unicode = get_unicode();
307 std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
308 bidiCallback(unicode, str, len, 0xfe);
309 if (!bidi) {
310 return;
311 }
312
313 std::unique_ptr<SkShaper::LanguageRunIterator> language(
315 if (!language) {
316 return;
317 }
318
319 SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
320 std::unique_ptr<SkShaper::ScriptRunIterator> script(
321 scriptRunCallback(str, len, undeterminedScript));
322 if (!script) {
323 return;
324 }
325
326 std::unique_ptr<SkShaper::FontRunIterator> font(
328 len,
329 srcFont,
331 "Arial",
333 &*language));
334 if (!font) {
335 return;
336 }
337
338 shaper->shape(str, len, *font, *bidi, *script, *language, nullptr, 0, 2000, &builder);
339
340 canvas->drawTextBlob(builder.makeBlob(), 0, 0, SkPaint());
341 }
342};
343
344DEF_SLIDE( return new ShaperSlide; );
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
#define SkIntToScalar(x)
Definition: SkScalar.h:57
sk_sp< SkUnicode > get_unicode()
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
uint32_t SkFourByteTag
Definition: SkTypes.h:166
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition: SkTypes.h:167
DEF_SLIDE(return new TextBoxSlide(SkShapers::Primitive::PrimitiveText, make_trivial_bidi, make_trivial_script_runner, "primitive");)
static std::unique_ptr< SkShaper::ScriptRunIterator > make_trivial_script_runner(const char *, size_t utf8Bytes, SkFourByteTag scriptTag)
std::unique_ptr< SkShaper >(* ShaperFactory)()
static std::unique_ptr< SkShaper::BiDiRunIterator > make_trivial_bidi(sk_sp< SkUnicode >, const char *, size_t utf8Bytes, uint8_t bidiLevel)
static const char gText[]
std::unique_ptr< SkShaper::BiDiRunIterator >(*)(sk_sp< SkUnicode > unicode, const char *utf8, size_t utf8Bytes, uint8_t bidiLevel) MakeBidiIteratorCallback
std::unique_ptr< SkShaper::ScriptRunIterator >(*)(const char *utf8, size_t utf8Bytes, SkFourByteTag script) MakeScriptRunCallback
void draw(SkCanvas *canvas) override
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition: SkCanvas.h:1182
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
Definition: SkCanvas.cpp:2484
static sk_sp< SkFontMgr > RefEmpty()
Definition: SkFontMgr.cpp:154
static constexpr SkFontStyle Bold()
Definition: SkFontStyle.h:69
Definition: SkFont.h:35
void setSize(SkScalar textSize)
Definition: SkFont.cpp:129
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
static std::unique_ptr< FontRunIterator > MakeFontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallback)
Definition: SkShaper.cpp:187
static std::unique_ptr< LanguageRunIterator > MakeStdLanguageRunIterator(const char *utf8, size_t utf8Bytes)
Definition: SkShaper.cpp:204
Definition: Slide.h:29
SkString fName
Definition: Slide.h:54
void draw(SkCanvas *canvas) override
void load(SkScalar w, SkScalar h) override
void resize(SkScalar w, SkScalar h) override
TextBoxSlide(ShaperFactory fact, MakeBidiIteratorCallback bidi, MakeScriptRunCallback script, const char suffix[])
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
std::u16string text
SKSHAPER_API std::unique_ptr< SkShaper > CoreText()
SKSHAPER_API std::unique_ptr< SkShaper > ShaperDrivenWrapper(sk_sp< SkUnicode > unicode, sk_sp< SkFontMgr > fallback)
SKSHAPER_API void PurgeCaches()
SKSHAPER_API std::unique_ptr< SkShaper::ScriptRunIterator > ScriptRunIterator(const char *utf8, size_t utf8Bytes)
SKSHAPER_API std::unique_ptr< SkShaper > PrimitiveText()
SKSHAPER_API std::unique_ptr< SkShaper::BiDiRunIterator > BidiRunIterator(sk_sp< SkUnicode > unicode, const char *utf8, size_t utf8Bytes, uint8_t bidiLevel)
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
SKUNICODE_API sk_sp< SkUnicode > Make()
sk_sp< SkFontMgr > TestFontMgr()
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
SkScalar w
SkScalar h
int32_t width
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
Definition: SkSize.h:52
SkScalar width() const
Definition: SkSize.h:76
SkScalar height() const
Definition: SkSize.h:77