• 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 "Resources.h"
9 #include "SampleCode.h"
10 #include "sk_tool_utils.h"
11 
12 #include "SkCanvas.h"
13 #include "SkFontMgr.h"
14 #include "SkRandom.h"
15 #include "SkTypeface.h"
16 #include "SkTextBlob.h"
17 
18 #if SK_SUPPORT_GPU
19 #include "GrContext.h"
20 #endif
21 
make_paint(SkPaint * paint,sk_sp<SkTypeface> typeface)22 static void make_paint(SkPaint* paint, sk_sp<SkTypeface> typeface) {
23   static const int kTextSize = 56;
24 
25   paint->setAntiAlias(true);
26   paint->setColor(0xDE000000);
27   paint->setTypeface(typeface);
28   paint->setTextSize(kTextSize);
29   paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
30 }
31 
chinese_typeface()32 static sk_sp<SkTypeface> chinese_typeface() {
33 #ifdef SK_BUILD_FOR_ANDROID
34     return MakeResourceAsTypeface("fonts/NotoSansCJK-Regular.ttc");
35 #elif defined(SK_BUILD_FOR_WIN)
36     return SkTypeface::MakeFromName("SimSun", SkFontStyle());
37 #elif defined(SK_BUILD_FOR_MAC)
38     return SkTypeface::MakeFromName("Hiragino Sans GB W3", SkFontStyle());
39 #elif defined(SK_BUILD_FOR_IOS)
40     return SkTypeface::MakeFromName("Hiragino Sans GB W3", SkFontStyle());
41 #elif defined(SK_BUILD_FOR_UNIX)
42     return SkTypeface::MakeFromName("Noto Sans CJK SC", SkFontStyle());
43 #else
44     return nullptr;
45 #endif
46 }
47 
48 class ChineseFlingView : public SampleView {
49 public:
ChineseFlingView()50     ChineseFlingView() : fBlobs(kNumBlobs) {}
51 
52 protected:
onQuery(SkEvent * evt)53     bool onQuery(SkEvent* evt) override {
54         if (SampleCode::TitleQ(*evt)) {
55             SampleCode::TitleR(evt, "chinese-fling");
56             return true;
57         }
58         return this->INHERITED::onQuery(evt);
59     }
60 
onDrawContent(SkCanvas * canvas)61     void onDrawContent(SkCanvas* canvas) override {
62         if (!fInitialized) {
63             this->init();
64             fInitialized = true;
65         }
66 
67         canvas->clear(0xFFDDDDDD);
68 
69         SkPaint paint;
70         make_paint(&paint, fTypeface);
71 
72         // draw a consistent run of the 'words' - one word per line
73         int index = fIndex;
74         for (SkScalar y = 0.0f; y < 1024.0f; ) {
75 
76             y += -fMetrics.fAscent;
77             canvas->drawTextBlob(fBlobs[index], 0, y, paint);
78 
79             y += fMetrics.fDescent + fMetrics.fLeading;
80             ++index;
81             index %= fBlobs.count();
82         }
83         // now "fling" a random amount
84         fIndex += fRand.nextRangeU(5, 20);
85         fIndex %= fBlobs.count();
86     }
87 
88 private:
89     static constexpr auto kNumBlobs = 200;
90     static constexpr auto kWordLength = 16;
91 
init()92     void init() {
93         fTypeface = chinese_typeface();
94 
95         SkPaint paint;
96         make_paint(&paint, fTypeface);
97 
98         paint.getFontMetrics(&fMetrics);
99 
100         SkUnichar glyphs[kWordLength];
101         for (int32_t i = 0; i < kNumBlobs; ++i) {
102             this->createRandomWord(glyphs);
103 
104             SkTextBlobBuilder builder;
105             sk_tool_utils::add_to_text_blob_w_len(&builder, (const char*) glyphs, kWordLength*4,
106                                                   paint, 0, 0);
107 
108             fBlobs.emplace_back(builder.make());
109         }
110 
111         fIndex = 0;
112     }
113 
114     // Construct a random kWordLength character 'word' drawing from the full Chinese set
createRandomWord(SkUnichar glyphs[kWordLength])115     void createRandomWord(SkUnichar glyphs[kWordLength]) {
116         for (int i = 0; i < kWordLength; ++i) {
117             glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
118         }
119     }
120 
121     bool                        fInitialized = false;
122     sk_sp<SkTypeface>           fTypeface;
123     SkPaint::FontMetrics        fMetrics;
124     SkTArray<sk_sp<SkTextBlob>> fBlobs;
125     SkRandom                    fRand;
126     int                         fIndex;
127 
128     typedef SkView INHERITED;
129 };
130 
131 class ChineseZoomView : public SampleView {
132 public:
ChineseZoomView()133     ChineseZoomView() : fBlobs(kNumBlobs), fScale(1.0f) {}
134 
135 protected:
onQuery(SkEvent * evt)136     bool onQuery(SkEvent* evt) override {
137         if (SampleCode::TitleQ(*evt)) {
138             SampleCode::TitleR(evt, "chinese-zoom");
139             return true;
140         }
141         SkUnichar uni;
142         if (SampleCode::CharQ(*evt, &uni)) {
143             if ('>' == uni) {
144                 fScale += 0.125f;
145                 return true;
146             }
147             if ('<' == uni) {
148                 fScale -= 0.125f;
149                 return true;
150             }
151         }
152         return this->INHERITED::onQuery(evt);
153     }
154 
onDrawContent(SkCanvas * canvas)155     void onDrawContent(SkCanvas* canvas) override {
156         if (!fInitialized) {
157             this->init();
158             fInitialized = true;
159         }
160 
161         canvas->clear(0xFFDDDDDD);
162 
163         SkPaint paint;
164         paint.setAntiAlias(true);
165         paint.setColor(0xDE000000);
166         paint.setTypeface(fTypeface);
167         paint.setTextSize(11);
168         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
169 
170 #if SK_SUPPORT_GPU
171         GrContext* grContext = canvas->getGrContext();
172         if (grContext) {
173             sk_sp<SkImage> image =
174             grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 0);
175             canvas->drawImageRect(image,
176                                   SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0), &paint);
177             image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 1);
178             canvas->drawImageRect(image,
179                                   SkRect::MakeXYWH(1024.0f, 10.0f, 512.f, 512.0f), &paint);
180             image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 2);
181             canvas->drawImageRect(image,
182                                   SkRect::MakeXYWH(512.0f, 522.0f, 512.0f, 512.0f), &paint);
183             image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 3);
184             canvas->drawImageRect(image,
185                                   SkRect::MakeXYWH(1024.0f, 522.0f, 512.0f, 512.0f), &paint);
186         }
187 #endif
188 
189         canvas->scale(fScale, fScale);
190 
191         // draw a consistent run of the 'words' - one word per line
192         SkScalar y = 0;
193         for (int index = 0; index < kNumBlobs; ++index) {
194             y += -fMetrics.fAscent;
195             canvas->drawTextBlob(fBlobs[index], 0, y, paint);
196 
197             y += 3*(fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading);
198         }
199     }
200 
201 private:
202     static constexpr auto kNumBlobs = 8;
203     static constexpr auto kParagraphLength = 175;
204 
init()205     void init() {
206         fTypeface = chinese_typeface();
207 
208         SkPaint paint;
209         paint.setAntiAlias(true);
210         paint.setColor(0xDE000000);
211         paint.setTypeface(fTypeface);
212         paint.setTextSize(11);
213         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
214 
215         paint.getFontMetrics(&fMetrics);
216 
217         SkUnichar glyphs[45];
218         for (int32_t i = 0; i < kNumBlobs; ++i) {
219             SkTextBlobBuilder builder;
220             auto paragraphLength = kParagraphLength;
221             SkScalar y = 0;
222             while (paragraphLength - 45 > 0) {
223                 auto currentLineLength = SkTMin(45, paragraphLength - 45);
224                 this->createRandomLine(glyphs, currentLineLength);
225 
226                 sk_tool_utils::add_to_text_blob_w_len(&builder, (const char*) glyphs,
227                                                       currentLineLength*4, paint, 0, y);
228                 y += fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading;
229                 paragraphLength -= 45;
230             }
231             fBlobs.emplace_back(builder.make());
232         }
233 
234         fIndex = 0;
235     }
236 
237     // Construct a random kWordLength character 'word' drawing from the full Chinese set
createRandomLine(SkUnichar glyphs[45],int lineLength)238     void createRandomLine(SkUnichar glyphs[45], int lineLength) {
239         for (auto i = 0; i < lineLength; ++i) {
240             glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
241         }
242     }
243 
244     bool                        fInitialized = false;
245     sk_sp<SkTypeface>           fTypeface;
246     SkPaint::FontMetrics        fMetrics;
247     SkTArray<sk_sp<SkTextBlob>> fBlobs;
248     SkRandom                    fRand;
249     SkScalar                    fScale;
250     int                         fIndex;
251 
252     typedef SkView INHERITED;
253 };
254 
255 //////////////////////////////////////////////////////////////////////////////
256 
FlingFactory()257 static SkView* FlingFactory() { return new ChineseFlingView; }
258 static SkViewRegister regFling(FlingFactory);
259 
ZoomFactory()260 static SkView* ZoomFactory() { return new ChineseZoomView; }
261 static SkViewRegister regZoom(ZoomFactory);
262