Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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)
67 if (auto unicode = SkUnicodes::Libgrapheme::Make()) {
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(
180 SkShaper::MakeStdLanguageRunIterator(utf8, utf8Bytes));
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
226DEF_SLIDE(return new TextBoxSlide(SkShapers::Primitive::PrimitiveText,
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,
262 SkShapers::Primitive::PrimitiveText(),
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[],
292 SkScalar size,
293 std::unique_ptr<SkShaper> shaper,
294 MakeBidiIteratorCallback bidiCallback,
295 MakeScriptRunCallback scriptRunCallback) {
296 if (!shaper) return;
297
298 SkTextBlobBuilderRunHandler builder(str, {0, 0});
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_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
uint32_t SkFourByteTag
Definition SkTypes.h:166
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition SkTypes.h:167
#define DEF_SLIDE(code)
Definition Slide.h:25
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)
void translate(SkScalar dx, SkScalar dy)
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition SkCanvas.h:1182
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
static sk_sp< SkFontMgr > RefEmpty()
static constexpr SkFontStyle Bold()
Definition SkFontStyle.h:69
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
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::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()
font
Font Metadata and Metrics.
static sk_sp< SkUnicode > get_unicode()
SkScalar w
SkScalar h
int32_t width
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
SkScalar width() const
Definition SkSize.h:76
SkScalar height() const
Definition SkSize.h:77