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