blob: 76222e91a0cc87e673a7101bfa972a136642d789 [file] [log] [blame]
Robert Phillips4c72b262017-08-15 13:28:42 -04001/*
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
Jim Van Verth87d18ce2018-01-22 12:45:47 -050018#if SK_SUPPORT_GPU
19#include "GrContext.h"
20#endif
21
Robert Phillips4c72b262017-08-15 13:28:42 -040022static 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
Robert Phillips4c72b262017-08-15 13:28:42 -040032static sk_sp<SkTypeface> chinese_typeface() {
33#ifdef SK_BUILD_FOR_ANDROID
Hal Canary53e5e7d2017-12-08 14:25:14 -050034 return MakeResourceAsTypeface("fonts/NotoSansCJK-Regular.ttc");
Mike Klein8f11d4d2018-01-24 12:42:55 -050035#elif defined(SK_BUILD_FOR_WIN)
Robert Phillips4c72b262017-08-15 13:28:42 -040036 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
48class ChineseFlingView : public SampleView {
49public:
Jim Van Verthc3269ae2017-09-28 15:04:00 -040050 ChineseFlingView() : fBlobs(kNumBlobs) {}
Robert Phillips4c72b262017-08-15 13:28:42 -040051
52protected:
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
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
Jim Van Verthc3269ae2017-09-28 15:04:00 -040072 // draw a consistent run of the 'words' - one word per line
73 int index = fIndex;
Robert Phillips4c72b262017-08-15 13:28:42 -040074 for (SkScalar y = 0.0f; y < 1024.0f; ) {
Robert Phillips4c72b262017-08-15 13:28:42 -040075
76 y += -fMetrics.fAscent;
77 canvas->drawTextBlob(fBlobs[index], 0, y, paint);
78
79 y += fMetrics.fDescent + fMetrics.fLeading;
Jim Van Verthc3269ae2017-09-28 15:04:00 -040080 ++index;
81 index %= fBlobs.count();
Robert Phillips4c72b262017-08-15 13:28:42 -040082 }
Jim Van Verthc3269ae2017-09-28 15:04:00 -040083 // now "fling" a random amount
84 fIndex += fRand.nextRangeU(5, 20);
85 fIndex %= fBlobs.count();
Robert Phillips4c72b262017-08-15 13:28:42 -040086 }
87
88private:
Jim Van Verthc3269ae2017-09-28 15:04:00 -040089 static constexpr auto kNumBlobs = 200;
90 static constexpr auto kWordLength = 16;
91
Robert Phillips4c72b262017-08-15 13:28:42 -040092 void init() {
93 fTypeface = chinese_typeface();
94
95 SkPaint paint;
96 make_paint(&paint, fTypeface);
97
98 paint.getFontMetrics(&fMetrics);
99
Jim Van Verthc3269ae2017-09-28 15:04:00 -0400100 SkUnichar glyphs[kWordLength];
101 for (int32_t i = 0; i < kNumBlobs; ++i) {
102 this->createRandomWord(glyphs);
Robert Phillips4c72b262017-08-15 13:28:42 -0400103
104 SkTextBlobBuilder builder;
Jim Van Verthc3269ae2017-09-28 15:04:00 -0400105 sk_tool_utils::add_to_text_blob_w_len(&builder, (const char*) glyphs, kWordLength*4,
106 paint, 0, 0);
Robert Phillips4c72b262017-08-15 13:28:42 -0400107
108 fBlobs.emplace_back(builder.make());
109 }
Jim Van Verthc3269ae2017-09-28 15:04:00 -0400110
111 fIndex = 0;
112 }
113
114 // Construct a random kWordLength character 'word' drawing from the full Chinese set
115 void createRandomWord(SkUnichar glyphs[kWordLength]) {
116 for (int i = 0; i < kWordLength; ++i) {
117 glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
118 }
Robert Phillips4c72b262017-08-15 13:28:42 -0400119 }
120
121 bool fInitialized = false;
122 sk_sp<SkTypeface> fTypeface;
123 SkPaint::FontMetrics fMetrics;
124 SkTArray<sk_sp<SkTextBlob>> fBlobs;
125 SkRandom fRand;
Jim Van Verthc3269ae2017-09-28 15:04:00 -0400126 int fIndex;
Robert Phillips4c72b262017-08-15 13:28:42 -0400127
128 typedef SkView INHERITED;
129};
130
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500131class ChineseZoomView : public SampleView {
132public:
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500133 ChineseZoomView() : fBlobs(kNumBlobs), fScale(15.0f), fTranslate(0.0f) {}
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500134
135protected:
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
155 void onDrawContent(SkCanvas* canvas) override {
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500156 bool afterFirstFrame = fInitialized;
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500157 if (!fInitialized) {
158 this->init();
159 fInitialized = true;
160 }
161
162 canvas->clear(0xFFDDDDDD);
163
164 SkPaint paint;
165 paint.setAntiAlias(true);
166 paint.setColor(0xDE000000);
167 paint.setTypeface(fTypeface);
168 paint.setTextSize(11);
169 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
170
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500171 if (afterFirstFrame) {
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500172#if SK_SUPPORT_GPU
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500173 GrContext* grContext = canvas->getGrContext();
174 if (grContext) {
175 sk_sp<SkImage> image =
176 grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 0);
177 canvas->drawImageRect(image,
178 SkRect::MakeXYWH(10.0f, 10.0f, 512.0f, 512.0), &paint);
179 image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 1);
180 canvas->drawImageRect(image,
181 SkRect::MakeXYWH(522.0f, 10.0f, 512.f, 512.0f), &paint);
182 image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 2);
183 canvas->drawImageRect(image,
184 SkRect::MakeXYWH(10.0f, 522.0f, 512.0f, 512.0f), &paint);
185 image = grContext->getFontAtlasImage_ForTesting(GrMaskFormat::kA8_GrMaskFormat, 3);
186 canvas->drawImageRect(image,
187 SkRect::MakeXYWH(522.0f, 522.0f, 512.0f, 512.0f), &paint);
188 }
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500189#endif
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500190 }
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500191
192 canvas->scale(fScale, fScale);
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500193 canvas->translate(0, fTranslate);
194 fTranslate -= 0.5f;
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500195
196 // draw a consistent run of the 'words' - one word per line
197 SkScalar y = 0;
198 for (int index = 0; index < kNumBlobs; ++index) {
199 y += -fMetrics.fAscent;
200 canvas->drawTextBlob(fBlobs[index], 0, y, paint);
201
202 y += 3*(fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading);
203 }
204 }
205
206private:
207 static constexpr auto kNumBlobs = 8;
208 static constexpr auto kParagraphLength = 175;
209
210 void init() {
211 fTypeface = chinese_typeface();
212
213 SkPaint paint;
214 paint.setAntiAlias(true);
215 paint.setColor(0xDE000000);
216 paint.setTypeface(fTypeface);
217 paint.setTextSize(11);
218 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
219
220 paint.getFontMetrics(&fMetrics);
221
222 SkUnichar glyphs[45];
223 for (int32_t i = 0; i < kNumBlobs; ++i) {
224 SkTextBlobBuilder builder;
225 auto paragraphLength = kParagraphLength;
226 SkScalar y = 0;
227 while (paragraphLength - 45 > 0) {
228 auto currentLineLength = SkTMin(45, paragraphLength - 45);
229 this->createRandomLine(glyphs, currentLineLength);
230
231 sk_tool_utils::add_to_text_blob_w_len(&builder, (const char*) glyphs,
232 currentLineLength*4, paint, 0, y);
233 y += fMetrics.fDescent - fMetrics.fAscent + fMetrics.fLeading;
234 paragraphLength -= 45;
235 }
236 fBlobs.emplace_back(builder.make());
237 }
238
239 fIndex = 0;
240 }
241
242 // Construct a random kWordLength character 'word' drawing from the full Chinese set
243 void createRandomLine(SkUnichar glyphs[45], int lineLength) {
244 for (auto i = 0; i < lineLength; ++i) {
245 glyphs[i] = fRand.nextRangeU(0x4F00, 0x9FA0);
246 }
247 }
248
249 bool fInitialized = false;
250 sk_sp<SkTypeface> fTypeface;
251 SkPaint::FontMetrics fMetrics;
252 SkTArray<sk_sp<SkTextBlob>> fBlobs;
253 SkRandom fRand;
254 SkScalar fScale;
Jim Van Verthcad0acf2018-02-16 18:41:41 -0500255 SkScalar fTranslate;
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500256 int fIndex;
257
258 typedef SkView INHERITED;
259};
260
Robert Phillips4c72b262017-08-15 13:28:42 -0400261//////////////////////////////////////////////////////////////////////////////
262
Jim Van Verth87d18ce2018-01-22 12:45:47 -0500263static SkView* FlingFactory() { return new ChineseFlingView; }
264static SkViewRegister regFling(FlingFactory);
265
266static SkView* ZoomFactory() { return new ChineseZoomView; }
267static SkViewRegister regZoom(ZoomFactory);