1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 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/SkFontMetrics.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/Slide.h"
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker using MaskFormat = skgpu::MaskFormat;
24*c8dee2aaSAndroid Build Coastguard Worker #endif
25*c8dee2aaSAndroid Build Coastguard Worker
chinese_typeface()26*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkTypeface> chinese_typeface() {
27*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
28*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreateTypefaceFromResource("fonts/NotoSansCJK-Regular.ttc");
29*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_WIN)
30*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreateTestTypeface("SimSun", SkFontStyle());
31*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_MAC)
32*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreateTestTypeface("Hiragino Sans GB W3", SkFontStyle());
33*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_IOS)
34*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreateTestTypeface("Hiragino Sans GB W3", SkFontStyle());
35*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_UNIX)
36*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::CreateTestTypeface("Noto Sans CJK SC", SkFontStyle());
37*c8dee2aaSAndroid Build Coastguard Worker #else
38*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
39*c8dee2aaSAndroid Build Coastguard Worker #endif
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker class ChineseFlingSlide : public Slide {
43*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumBlobs = 200;
44*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kWordLength = 16;
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fTypeface;
47*c8dee2aaSAndroid Build Coastguard Worker SkFontMetrics fMetrics;
48*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> fBlobs[kNumBlobs];
49*c8dee2aaSAndroid Build Coastguard Worker SkRandom fRand;
50*c8dee2aaSAndroid Build Coastguard Worker int fIndex = 0;
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker public:
ChineseFlingSlide()53*c8dee2aaSAndroid Build Coastguard Worker ChineseFlingSlide() { fName = "chinese-fling"; }
54*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)55*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) override {
56*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(0xFFDDDDDD);
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
59*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xDE000000);
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker // draw a consistent run of the 'words' - one word per line
62*c8dee2aaSAndroid Build Coastguard Worker int index = fIndex;
63*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar y = 0.0f; y < 1024.0f; ) {
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker y += -fMetrics.fAscent;
66*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(fBlobs[index], 0, y, paint);
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker y += fMetrics.fDescent + fMetrics.fLeading;
69*c8dee2aaSAndroid Build Coastguard Worker ++index;
70*c8dee2aaSAndroid Build Coastguard Worker index %= kNumBlobs;
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker // now "fling" a random amount
73*c8dee2aaSAndroid Build Coastguard Worker fIndex += fRand.nextRangeU(5, 20);
74*c8dee2aaSAndroid Build Coastguard Worker fIndex %= kNumBlobs;
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker
load(SkScalar w,SkScalar h)77*c8dee2aaSAndroid Build Coastguard Worker void load(SkScalar w, SkScalar h) override {
78*c8dee2aaSAndroid Build Coastguard Worker fTypeface = chinese_typeface();
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fTypeface, 56);
81*c8dee2aaSAndroid Build Coastguard Worker font.getMetrics(&fMetrics);
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker SkUnichar glyphs[kWordLength];
84*c8dee2aaSAndroid Build Coastguard Worker for (int32_t i = 0; i < kNumBlobs; ++i) {
85*c8dee2aaSAndroid Build Coastguard Worker this->createRandomWord(glyphs);
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobBuilder builder;
88*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::add_to_text_blob_w_len(&builder,
89*c8dee2aaSAndroid Build Coastguard Worker (const char*)glyphs,
90*c8dee2aaSAndroid Build Coastguard Worker kWordLength * 4,
91*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding::kUTF32,
92*c8dee2aaSAndroid Build Coastguard Worker font,
93*c8dee2aaSAndroid Build Coastguard Worker 0,
94*c8dee2aaSAndroid Build Coastguard Worker 0);
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker fBlobs[i] = builder.make();
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker // Construct a random kWordLength character 'word' drawing from the full Chinese set
createRandomWord(SkUnichar glyphs[kWordLength])101*c8dee2aaSAndroid Build Coastguard Worker void createRandomWord(SkUnichar glyphs[kWordLength]) {
102*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kWordLength; ++i) {
103*c8dee2aaSAndroid Build Coastguard Worker glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker };
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker class ChineseZoomSlide : public Slide {
109*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kNumBlobs = 8;
110*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kParagraphLength = 175;
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker bool fAfterFirstFrame = false;
113*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fTypeface;
114*c8dee2aaSAndroid Build Coastguard Worker SkFontMetrics fMetrics;
115*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> fBlobs[kNumBlobs];
116*c8dee2aaSAndroid Build Coastguard Worker SkRandom fRand;
117*c8dee2aaSAndroid Build Coastguard Worker SkScalar fScale = 15;
118*c8dee2aaSAndroid Build Coastguard Worker SkScalar fTranslate = 0;
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker public:
ChineseZoomSlide()121*c8dee2aaSAndroid Build Coastguard Worker ChineseZoomSlide() { fName = "chinese-zoom"; }
122*c8dee2aaSAndroid Build Coastguard Worker
onChar(SkUnichar uni)123*c8dee2aaSAndroid Build Coastguard Worker bool onChar(SkUnichar uni) override {
124*c8dee2aaSAndroid Build Coastguard Worker if ('>' == uni) {
125*c8dee2aaSAndroid Build Coastguard Worker fScale += 0.125f;
126*c8dee2aaSAndroid Build Coastguard Worker return true;
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker if ('<' == uni) {
129*c8dee2aaSAndroid Build Coastguard Worker fScale -= 0.125f;
130*c8dee2aaSAndroid Build Coastguard Worker return true;
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker return false;
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)135*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) override {
136*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(0xFFDDDDDD);
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
139*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
140*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xDE000000);
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker if (fAfterFirstFrame) {
143*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
144*c8dee2aaSAndroid Build Coastguard Worker auto direct = GrAsDirectContext(canvas->recordingContext());
145*c8dee2aaSAndroid Build Coastguard Worker if (direct) {
146*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8,
147*c8dee2aaSAndroid Build Coastguard Worker 0);
148*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(image,
149*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(10.0f, 10.0f, 512.0f, 512.0),
150*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &paint);
151*c8dee2aaSAndroid Build Coastguard Worker image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8, 1);
152*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(image,
153*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(522.0f, 10.0f, 512.f, 512.0f),
154*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &paint);
155*c8dee2aaSAndroid Build Coastguard Worker image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8, 2);
156*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(image,
157*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(10.0f, 522.0f, 512.0f, 512.0f),
158*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &paint);
159*c8dee2aaSAndroid Build Coastguard Worker image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8, 3);
160*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(image,
161*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeXYWH(522.0f, 522.0f, 512.0f, 512.0f),
162*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), &paint);
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker #endif
165*c8dee2aaSAndroid Build Coastguard Worker }
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(fScale, fScale);
168*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, fTranslate);
169*c8dee2aaSAndroid Build Coastguard Worker fTranslate -= 0.5f;
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker // draw a consistent run of the 'words' - one word per line
172*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 0;
173*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < kNumBlobs; ++index) {
174*c8dee2aaSAndroid Build Coastguard Worker y += -fMetrics.fAscent;
175*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(fBlobs[index], 0, y, paint);
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker y += 3*(fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading);
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker if (!fAfterFirstFrame) {
180*c8dee2aaSAndroid Build Coastguard Worker fAfterFirstFrame = true;
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker
load(SkScalar w,SkScalar h)184*c8dee2aaSAndroid Build Coastguard Worker void load(SkScalar w, SkScalar h) override {
185*c8dee2aaSAndroid Build Coastguard Worker fTypeface = chinese_typeface();
186*c8dee2aaSAndroid Build Coastguard Worker
187*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fTypeface, 11);
188*c8dee2aaSAndroid Build Coastguard Worker font.getMetrics(&fMetrics);
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
191*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xDE000000);
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker SkUnichar glyphs[45];
194*c8dee2aaSAndroid Build Coastguard Worker for (int32_t i = 0; i < kNumBlobs; ++i) {
195*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobBuilder builder;
196*c8dee2aaSAndroid Build Coastguard Worker auto paragraphLength = kParagraphLength;
197*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 0;
198*c8dee2aaSAndroid Build Coastguard Worker while (paragraphLength - 45 > 0) {
199*c8dee2aaSAndroid Build Coastguard Worker auto currentLineLength = std::min(45, paragraphLength - 45);
200*c8dee2aaSAndroid Build Coastguard Worker this->createRandomLine(glyphs, currentLineLength);
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::add_to_text_blob_w_len(&builder,
203*c8dee2aaSAndroid Build Coastguard Worker (const char*)glyphs,
204*c8dee2aaSAndroid Build Coastguard Worker currentLineLength * 4,
205*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding::kUTF32,
206*c8dee2aaSAndroid Build Coastguard Worker font,
207*c8dee2aaSAndroid Build Coastguard Worker 0,
208*c8dee2aaSAndroid Build Coastguard Worker y);
209*c8dee2aaSAndroid Build Coastguard Worker y += fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading;
210*c8dee2aaSAndroid Build Coastguard Worker paragraphLength -= 45;
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker fBlobs[i] = builder.make();
213*c8dee2aaSAndroid Build Coastguard Worker }
214*c8dee2aaSAndroid Build Coastguard Worker }
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker // Construct a random kWordLength character 'word' drawing from the full Chinese set
createRandomLine(SkUnichar glyphs[45],int lineLength)217*c8dee2aaSAndroid Build Coastguard Worker void createRandomLine(SkUnichar glyphs[45], int lineLength) {
218*c8dee2aaSAndroid Build Coastguard Worker for (auto i = 0; i < lineLength; ++i) {
219*c8dee2aaSAndroid Build Coastguard Worker glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker };
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new ChineseFlingSlide(); )
227*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new ChineseZoomSlide(); )
228