xref: /aosp_15_r20/external/skia/tools/viewer/TextBoxSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkGraphics.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRegion.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_skunicode.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTime.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkUTF.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOSFile.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/Slide.h"
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_CORETEXT_AVAILABLE)
30*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_coretext.h"
31*c8dee2aaSAndroid Build Coastguard Worker #endif
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE)
34*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_harfbuzz.h"
35*c8dee2aaSAndroid Build Coastguard Worker #endif
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
38*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode_icu.h"
39*c8dee2aaSAndroid Build Coastguard Worker #endif
40*c8dee2aaSAndroid Build Coastguard Worker 
41*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
42*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode_libgrapheme.h"
43*c8dee2aaSAndroid Build Coastguard Worker #endif
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
46*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode_icu4x.h"
47*c8dee2aaSAndroid Build Coastguard Worker #endif
48*c8dee2aaSAndroid Build Coastguard Worker 
49*c8dee2aaSAndroid Build Coastguard Worker typedef std::unique_ptr<SkShaper> (*ShaperFactory)();
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker static const char gText[] =
52*c8dee2aaSAndroid Build Coastguard Worker     "When in the Course of human events it becomes necessary for one people "
53*c8dee2aaSAndroid Build Coastguard Worker     "to dissolve the political bands which have connected them with another "
54*c8dee2aaSAndroid Build Coastguard Worker     "and to assume among the powers of the earth, the separate and equal "
55*c8dee2aaSAndroid Build Coastguard Worker     "station to which the Laws of Nature and of Nature's God entitle them, "
56*c8dee2aaSAndroid Build Coastguard Worker     "a decent respect to the opinions of mankind requires that they should "
57*c8dee2aaSAndroid Build Coastguard Worker     "declare the causes which impel them to the separation.";
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker namespace {
get_unicode()60*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkUnicode> get_unicode() {
61*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU_IMPLEMENTATION)
62*c8dee2aaSAndroid Build Coastguard Worker     if (auto unicode = SkUnicodes::ICU::Make()) {
63*c8dee2aaSAndroid Build Coastguard Worker         return unicode;
64*c8dee2aaSAndroid Build Coastguard Worker     }
65*c8dee2aaSAndroid Build Coastguard Worker #endif  // defined(SK_UNICODE_ICU_IMPLEMENTATION)
66*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_LIBGRAPHEME_IMPLEMENTATION)
67*c8dee2aaSAndroid Build Coastguard Worker     if (auto unicode = SkUnicodes::Libgrapheme::Make()) {
68*c8dee2aaSAndroid Build Coastguard Worker         return unicode;
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker #endif
71*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_UNICODE_ICU4X_IMPLEMENTATION)
72*c8dee2aaSAndroid Build Coastguard Worker     if (auto unicode = SkUnicodes::ICU4X::Make()) {
73*c8dee2aaSAndroid Build Coastguard Worker         return unicode;
74*c8dee2aaSAndroid Build Coastguard Worker     }
75*c8dee2aaSAndroid Build Coastguard Worker #endif
76*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker using MakeBidiIteratorCallback = std::unique_ptr<SkShaper::BiDiRunIterator> (*)(sk_sp<SkUnicode> unicode,
81*c8dee2aaSAndroid Build Coastguard Worker                                                                                 const char* utf8,
82*c8dee2aaSAndroid Build Coastguard Worker                                                                                 size_t utf8Bytes,
83*c8dee2aaSAndroid Build Coastguard Worker                                                                                 uint8_t bidiLevel);
84*c8dee2aaSAndroid Build Coastguard Worker using MakeScriptRunCallback = std::unique_ptr<SkShaper::ScriptRunIterator> (*)(
85*c8dee2aaSAndroid Build Coastguard Worker         const char* utf8, size_t utf8Bytes, SkFourByteTag script);
86*c8dee2aaSAndroid Build Coastguard Worker 
make_trivial_bidi(sk_sp<SkUnicode>,const char *,size_t utf8Bytes,uint8_t bidiLevel)87*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkShaper::BiDiRunIterator> make_trivial_bidi(sk_sp<SkUnicode>,
88*c8dee2aaSAndroid Build Coastguard Worker                                                                     const char*,
89*c8dee2aaSAndroid Build Coastguard Worker                                                                     size_t utf8Bytes,
90*c8dee2aaSAndroid Build Coastguard Worker                                                                     uint8_t bidiLevel) {
91*c8dee2aaSAndroid Build Coastguard Worker     return std::make_unique<SkShaper::TrivialBiDiRunIterator>(bidiLevel, utf8Bytes);
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
make_unicode_bidi(sk_sp<SkUnicode> unicode,const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)95*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkShaper::BiDiRunIterator> make_unicode_bidi(sk_sp<SkUnicode> unicode,
96*c8dee2aaSAndroid Build Coastguard Worker                                                                     const char* utf8,
97*c8dee2aaSAndroid Build Coastguard Worker                                                                     size_t utf8Bytes,
98*c8dee2aaSAndroid Build Coastguard Worker                                                                     uint8_t bidiLevel) {
99*c8dee2aaSAndroid Build Coastguard Worker     if (auto bidi = SkShapers::unicode::BidiRunIterator(unicode, utf8, utf8Bytes, bidiLevel)) {
100*c8dee2aaSAndroid Build Coastguard Worker         return bidi;
101*c8dee2aaSAndroid Build Coastguard Worker     }
102*c8dee2aaSAndroid Build Coastguard Worker     return make_trivial_bidi(unicode, utf8, utf8Bytes, bidiLevel);
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker #endif
105*c8dee2aaSAndroid Build Coastguard Worker 
make_trivial_script_runner(const char *,size_t utf8Bytes,SkFourByteTag scriptTag)106*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkShaper::ScriptRunIterator> make_trivial_script_runner(
107*c8dee2aaSAndroid Build Coastguard Worker         const char*, size_t utf8Bytes, SkFourByteTag scriptTag) {
108*c8dee2aaSAndroid Build Coastguard Worker     return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
make_harfbuzz_script_runner(const char * utf8,size_t utf8Bytes,SkFourByteTag scriptTag)112*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<SkShaper::ScriptRunIterator> make_harfbuzz_script_runner(
113*c8dee2aaSAndroid Build Coastguard Worker         const char* utf8, size_t utf8Bytes, SkFourByteTag scriptTag) {
114*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkShaper::ScriptRunIterator> script =
115*c8dee2aaSAndroid Build Coastguard Worker             SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes, scriptTag);
116*c8dee2aaSAndroid Build Coastguard Worker     if (script) {
117*c8dee2aaSAndroid Build Coastguard Worker         return script;
118*c8dee2aaSAndroid Build Coastguard Worker     }
119*c8dee2aaSAndroid Build Coastguard Worker     return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker #endif
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker class TextBoxSlide : public Slide {
124*c8dee2aaSAndroid Build Coastguard Worker public:
TextBoxSlide(ShaperFactory fact,MakeBidiIteratorCallback bidi,MakeScriptRunCallback script,const char suffix[])125*c8dee2aaSAndroid Build Coastguard Worker     TextBoxSlide(ShaperFactory fact,
126*c8dee2aaSAndroid Build Coastguard Worker                  MakeBidiIteratorCallback bidi,
127*c8dee2aaSAndroid Build Coastguard Worker                  MakeScriptRunCallback script,
128*c8dee2aaSAndroid Build Coastguard Worker                  const char suffix[])
129*c8dee2aaSAndroid Build Coastguard Worker             : fShaper(fact()), fBidiCallback(bidi), fScriptRunCallback(script) {
130*c8dee2aaSAndroid Build Coastguard Worker         fName = SkStringPrintf("TextBox_%s", suffix);
131*c8dee2aaSAndroid Build Coastguard Worker     }
132*c8dee2aaSAndroid Build Coastguard Worker 
load(SkScalar w,SkScalar h)133*c8dee2aaSAndroid Build Coastguard Worker     void load(SkScalar w, SkScalar h) override { fSize = {w, h}; }
134*c8dee2aaSAndroid Build Coastguard Worker 
resize(SkScalar w,SkScalar h)135*c8dee2aaSAndroid Build Coastguard Worker     void resize(SkScalar w, SkScalar h) override { fSize = {w, h}; }
136*c8dee2aaSAndroid Build Coastguard Worker 
draw(SkCanvas * canvas)137*c8dee2aaSAndroid Build Coastguard Worker     void draw(SkCanvas* canvas) override {
138*c8dee2aaSAndroid Build Coastguard Worker         SkScalar width = fSize.width() / 3;
139*c8dee2aaSAndroid Build Coastguard Worker         drawTest(canvas, width, fSize.height(), SK_ColorBLACK, SK_ColorWHITE);
140*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(width, 0);
141*c8dee2aaSAndroid Build Coastguard Worker         drawTest(canvas, width, fSize.height(), SK_ColorWHITE, SK_ColorBLACK);
142*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(width, 0);
143*c8dee2aaSAndroid Build Coastguard Worker         drawTest(canvas, width, fSize.height()/2, SK_ColorGRAY, SK_ColorWHITE);
144*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0, fSize.height()/2);
145*c8dee2aaSAndroid Build Coastguard Worker         drawTest(canvas, width, fSize.height()/2, SK_ColorGRAY, SK_ColorBLACK);
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker private:
drawTest(SkCanvas * canvas,SkScalar w,SkScalar h,SkColor fg,SkColor bg)149*c8dee2aaSAndroid Build Coastguard Worker     void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
150*c8dee2aaSAndroid Build Coastguard Worker         SkAutoCanvasRestore acr(canvas, true);
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker         canvas->clipRect(SkRect::MakeWH(w, h));
153*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawColor(bg);
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker         SkScalar margin = 20;
156*c8dee2aaSAndroid Build Coastguard Worker 
157*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
158*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(fg);
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 9; i < 24; i += 2) {
161*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
162*c8dee2aaSAndroid Build Coastguard Worker             SkShapers::HB::PurgeCaches();
163*c8dee2aaSAndroid Build Coastguard Worker #endif
164*c8dee2aaSAndroid Build Coastguard Worker             SkTextBlobBuilderRunHandler builder(gText, { margin, margin });
165*c8dee2aaSAndroid Build Coastguard Worker             SkFont srcFont(nullptr, SkIntToScalar(i));
166*c8dee2aaSAndroid Build Coastguard Worker             srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
167*c8dee2aaSAndroid Build Coastguard Worker             srcFont.setSubpixel(true);
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker             const char* utf8 = gText;
170*c8dee2aaSAndroid Build Coastguard Worker             size_t utf8Bytes = sizeof(gText) - 1;
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker             auto unicode = get_unicode();
173*c8dee2aaSAndroid Build Coastguard Worker             std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
174*c8dee2aaSAndroid Build Coastguard Worker                     fBidiCallback(unicode, utf8, utf8Bytes, 0xfe);
175*c8dee2aaSAndroid Build Coastguard Worker             if (!bidi) {
176*c8dee2aaSAndroid Build Coastguard Worker                 return;
177*c8dee2aaSAndroid Build Coastguard Worker             }
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker             std::unique_ptr<SkShaper::LanguageRunIterator> language(
180*c8dee2aaSAndroid Build Coastguard Worker                     SkShaper::MakeStdLanguageRunIterator(utf8, utf8Bytes));
181*c8dee2aaSAndroid Build Coastguard Worker             if (!language) {
182*c8dee2aaSAndroid Build Coastguard Worker                 return;
183*c8dee2aaSAndroid Build Coastguard Worker             }
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker             SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
186*c8dee2aaSAndroid Build Coastguard Worker             std::unique_ptr<SkShaper::ScriptRunIterator> script =
187*c8dee2aaSAndroid Build Coastguard Worker                     fScriptRunCallback(utf8, utf8Bytes, undeterminedScript);
188*c8dee2aaSAndroid Build Coastguard Worker             if (!script) {
189*c8dee2aaSAndroid Build Coastguard Worker                 return;
190*c8dee2aaSAndroid Build Coastguard Worker             }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker             std::unique_ptr<SkShaper::FontRunIterator> font(
193*c8dee2aaSAndroid Build Coastguard Worker                     SkShaper::MakeFontMgrRunIterator(utf8,
194*c8dee2aaSAndroid Build Coastguard Worker                                                      utf8Bytes,
195*c8dee2aaSAndroid Build Coastguard Worker                                                      srcFont,
196*c8dee2aaSAndroid Build Coastguard Worker                                                      ToolUtils::TestFontMgr(),
197*c8dee2aaSAndroid Build Coastguard Worker                                                      "Arial",
198*c8dee2aaSAndroid Build Coastguard Worker                                                      SkFontStyle::Bold(),
199*c8dee2aaSAndroid Build Coastguard Worker                                                      &*language));
200*c8dee2aaSAndroid Build Coastguard Worker             if (!font) {
201*c8dee2aaSAndroid Build Coastguard Worker                 return;
202*c8dee2aaSAndroid Build Coastguard Worker             }
203*c8dee2aaSAndroid Build Coastguard Worker 
204*c8dee2aaSAndroid Build Coastguard Worker             fShaper->shape(utf8,
205*c8dee2aaSAndroid Build Coastguard Worker                            utf8Bytes,
206*c8dee2aaSAndroid Build Coastguard Worker                            *font,
207*c8dee2aaSAndroid Build Coastguard Worker                            *bidi,
208*c8dee2aaSAndroid Build Coastguard Worker                            *script,
209*c8dee2aaSAndroid Build Coastguard Worker                            *language,
210*c8dee2aaSAndroid Build Coastguard Worker                            nullptr,
211*c8dee2aaSAndroid Build Coastguard Worker                            0,
212*c8dee2aaSAndroid Build Coastguard Worker                            w - margin,
213*c8dee2aaSAndroid Build Coastguard Worker                            &builder);
214*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawTextBlob(builder.makeBlob(), 0, 0, paint);
215*c8dee2aaSAndroid Build Coastguard Worker 
216*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(0, builder.endPoint().y());
217*c8dee2aaSAndroid Build Coastguard Worker         }
218*c8dee2aaSAndroid Build Coastguard Worker     }
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker     SkSize fSize;
221*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkShaper> fShaper;
222*c8dee2aaSAndroid Build Coastguard Worker     MakeBidiIteratorCallback fBidiCallback;
223*c8dee2aaSAndroid Build Coastguard Worker     MakeScriptRunCallback fScriptRunCallback;
224*c8dee2aaSAndroid Build Coastguard Worker };
225*c8dee2aaSAndroid Build Coastguard Worker 
226*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE(return new TextBoxSlide(SkShapers::Primitive::PrimitiveText,
227*c8dee2aaSAndroid Build Coastguard Worker                                   make_trivial_bidi,
228*c8dee2aaSAndroid Build Coastguard Worker                                   make_trivial_script_runner,
229*c8dee2aaSAndroid Build Coastguard Worker                                   "primitive"););
230*c8dee2aaSAndroid Build Coastguard Worker 
231*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_CORETEXT_AVAILABLE)
232*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE(return new TextBoxSlide(SkShapers::CT::CoreText,
233*c8dee2aaSAndroid Build Coastguard Worker                                   make_trivial_bidi,
234*c8dee2aaSAndroid Build Coastguard Worker                                   make_trivial_script_runner,
235*c8dee2aaSAndroid Build Coastguard Worker                                   "coretext"););
236*c8dee2aaSAndroid Build Coastguard Worker #endif
237*c8dee2aaSAndroid Build Coastguard Worker 
238*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
239*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE(return new TextBoxSlide(
__anoncc9255cf0202() 240*c8dee2aaSAndroid Build Coastguard Worker                          []() {
241*c8dee2aaSAndroid Build Coastguard Worker                              return SkShapers::HB::ShaperDrivenWrapper(get_unicode(),
242*c8dee2aaSAndroid Build Coastguard Worker                                                                        SkFontMgr::RefEmpty());
243*c8dee2aaSAndroid Build Coastguard Worker                          },
244*c8dee2aaSAndroid Build Coastguard Worker                          make_unicode_bidi,
245*c8dee2aaSAndroid Build Coastguard Worker                          make_harfbuzz_script_runner,
246*c8dee2aaSAndroid Build Coastguard Worker                          "harfbuzz"););
247*c8dee2aaSAndroid Build Coastguard Worker #endif
248*c8dee2aaSAndroid Build Coastguard Worker 
249*c8dee2aaSAndroid Build Coastguard Worker class ShaperSlide : public Slide {
250*c8dee2aaSAndroid Build Coastguard Worker public:
ShaperSlide()251*c8dee2aaSAndroid Build Coastguard Worker     ShaperSlide() { fName = "shaper"; }
252*c8dee2aaSAndroid Build Coastguard Worker 
draw(SkCanvas * canvas)253*c8dee2aaSAndroid Build Coastguard Worker     void draw(SkCanvas* canvas) override {
254*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(10, 30);
255*c8dee2aaSAndroid Build Coastguard Worker 
256*c8dee2aaSAndroid Build Coastguard Worker         const char text[] = "world";
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker         for (SkScalar size = 30; size <= 30; size += 10) {
259*c8dee2aaSAndroid Build Coastguard Worker             this->drawTest(canvas,
260*c8dee2aaSAndroid Build Coastguard Worker                            text,
261*c8dee2aaSAndroid Build Coastguard Worker                            size,
262*c8dee2aaSAndroid Build Coastguard Worker                            SkShapers::Primitive::PrimitiveText(),
263*c8dee2aaSAndroid Build Coastguard Worker                            make_trivial_bidi,
264*c8dee2aaSAndroid Build Coastguard Worker                            make_trivial_script_runner);
265*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(0, size + 5);
266*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_CORETEXT_AVAILABLE)
267*c8dee2aaSAndroid Build Coastguard Worker             this->drawTest(canvas,
268*c8dee2aaSAndroid Build Coastguard Worker                            text,
269*c8dee2aaSAndroid Build Coastguard Worker                            size,
270*c8dee2aaSAndroid Build Coastguard Worker                            SkShapers::CT::CoreText(),
271*c8dee2aaSAndroid Build Coastguard Worker                            make_trivial_bidi,
272*c8dee2aaSAndroid Build Coastguard Worker                            make_trivial_script_runner);
273*c8dee2aaSAndroid Build Coastguard Worker #endif
274*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(0, size + 5);
275*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
276*c8dee2aaSAndroid Build Coastguard Worker             auto unicode = get_unicode();
277*c8dee2aaSAndroid Build Coastguard Worker             this->drawTest(
278*c8dee2aaSAndroid Build Coastguard Worker                     canvas,
279*c8dee2aaSAndroid Build Coastguard Worker                     text,
280*c8dee2aaSAndroid Build Coastguard Worker                     size,
281*c8dee2aaSAndroid Build Coastguard Worker                     SkShapers::HB::ShaperDrivenWrapper(unicode, SkFontMgr::RefEmpty()),
282*c8dee2aaSAndroid Build Coastguard Worker                     make_unicode_bidi,
283*c8dee2aaSAndroid Build Coastguard Worker                     make_harfbuzz_script_runner);
284*c8dee2aaSAndroid Build Coastguard Worker #endif
285*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(0, size*2);
286*c8dee2aaSAndroid Build Coastguard Worker         }
287*c8dee2aaSAndroid Build Coastguard Worker     }
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker private:
drawTest(SkCanvas * canvas,const char str[],SkScalar size,std::unique_ptr<SkShaper> shaper,MakeBidiIteratorCallback bidiCallback,MakeScriptRunCallback scriptRunCallback)290*c8dee2aaSAndroid Build Coastguard Worker     void drawTest(SkCanvas* canvas,
291*c8dee2aaSAndroid Build Coastguard Worker                   const char str[],
292*c8dee2aaSAndroid Build Coastguard Worker                   SkScalar size,
293*c8dee2aaSAndroid Build Coastguard Worker                   std::unique_ptr<SkShaper> shaper,
294*c8dee2aaSAndroid Build Coastguard Worker                   MakeBidiIteratorCallback bidiCallback,
295*c8dee2aaSAndroid Build Coastguard Worker                   MakeScriptRunCallback scriptRunCallback) {
296*c8dee2aaSAndroid Build Coastguard Worker         if (!shaper) return;
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker         SkTextBlobBuilderRunHandler builder(str, {0, 0});
299*c8dee2aaSAndroid Build Coastguard Worker         SkFont srcFont;
300*c8dee2aaSAndroid Build Coastguard Worker         srcFont.setSize(size);
301*c8dee2aaSAndroid Build Coastguard Worker         srcFont.setEdging(SkFont::Edging::kSubpixelAntiAlias);
302*c8dee2aaSAndroid Build Coastguard Worker         srcFont.setSubpixel(true);
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker         size_t len = strlen(str);
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker         auto unicode = get_unicode();
307*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
308*c8dee2aaSAndroid Build Coastguard Worker                 bidiCallback(unicode, str, len, 0xfe);
309*c8dee2aaSAndroid Build Coastguard Worker         if (!bidi) {
310*c8dee2aaSAndroid Build Coastguard Worker             return;
311*c8dee2aaSAndroid Build Coastguard Worker         }
312*c8dee2aaSAndroid Build Coastguard Worker 
313*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkShaper::LanguageRunIterator> language(
314*c8dee2aaSAndroid Build Coastguard Worker                 SkShaper::MakeStdLanguageRunIterator(str, len));
315*c8dee2aaSAndroid Build Coastguard Worker         if (!language) {
316*c8dee2aaSAndroid Build Coastguard Worker             return;
317*c8dee2aaSAndroid Build Coastguard Worker         }
318*c8dee2aaSAndroid Build Coastguard Worker 
319*c8dee2aaSAndroid Build Coastguard Worker         SkFourByteTag undeterminedScript = SkSetFourByteTag('Z','y','y','y');
320*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkShaper::ScriptRunIterator> script(
321*c8dee2aaSAndroid Build Coastguard Worker                 scriptRunCallback(str, len, undeterminedScript));
322*c8dee2aaSAndroid Build Coastguard Worker         if (!script) {
323*c8dee2aaSAndroid Build Coastguard Worker             return;
324*c8dee2aaSAndroid Build Coastguard Worker         }
325*c8dee2aaSAndroid Build Coastguard Worker 
326*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<SkShaper::FontRunIterator> font(
327*c8dee2aaSAndroid Build Coastguard Worker                 SkShaper::MakeFontMgrRunIterator(str,
328*c8dee2aaSAndroid Build Coastguard Worker                                                  len,
329*c8dee2aaSAndroid Build Coastguard Worker                                                  srcFont,
330*c8dee2aaSAndroid Build Coastguard Worker                                                  ToolUtils::TestFontMgr(),
331*c8dee2aaSAndroid Build Coastguard Worker                                                  "Arial",
332*c8dee2aaSAndroid Build Coastguard Worker                                                  SkFontStyle::Bold(),
333*c8dee2aaSAndroid Build Coastguard Worker                                                  &*language));
334*c8dee2aaSAndroid Build Coastguard Worker         if (!font) {
335*c8dee2aaSAndroid Build Coastguard Worker             return;
336*c8dee2aaSAndroid Build Coastguard Worker         }
337*c8dee2aaSAndroid Build Coastguard Worker 
338*c8dee2aaSAndroid Build Coastguard Worker         shaper->shape(str, len, *font, *bidi, *script, *language, nullptr, 0, 2000, &builder);
339*c8dee2aaSAndroid Build Coastguard Worker 
340*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawTextBlob(builder.makeBlob(), 0, 0, SkPaint());
341*c8dee2aaSAndroid Build Coastguard Worker     }
342*c8dee2aaSAndroid Build Coastguard Worker };
343*c8dee2aaSAndroid Build Coastguard Worker 
344*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new ShaperSlide; );
345