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