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