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