SampleChineseFling.cpp 7.5 KB

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