textblobmixedsizes.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright 2015 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 "gm/gm.h"
  8. #include "include/core/SkBlurTypes.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkColorSpace.h"
  12. #include "include/core/SkFont.h"
  13. #include "include/core/SkFontTypes.h"
  14. #include "include/core/SkImageInfo.h"
  15. #include "include/core/SkMaskFilter.h"
  16. #include "include/core/SkPaint.h"
  17. #include "include/core/SkRect.h"
  18. #include "include/core/SkRefCnt.h"
  19. #include "include/core/SkScalar.h"
  20. #include "include/core/SkSize.h"
  21. #include "include/core/SkString.h"
  22. #include "include/core/SkSurface.h"
  23. #include "include/core/SkSurfaceProps.h"
  24. #include "include/core/SkTextBlob.h"
  25. #include "include/core/SkTypeface.h"
  26. #include "include/core/SkTypes.h"
  27. #include "include/utils/SkRandom.h"
  28. #include "src/core/SkBlurMask.h"
  29. #include "tools/Resources.h"
  30. #include "tools/ToolUtils.h"
  31. #include <string.h>
  32. class GrContext;
  33. namespace skiagm {
  34. class TextBlobMixedSizes : public GM {
  35. public:
  36. // This gm tests that textblobs of mixed sizes with a large glyph will render properly
  37. TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {}
  38. protected:
  39. void onOnceBeforeDraw() override {
  40. SkTextBlobBuilder builder;
  41. // make textblob. To stress distance fields, we choose sizes appropriately
  42. SkFont font(MakeResourceAsTypeface("fonts/HangingS.ttf"), 262);
  43. font.setSubpixel(true);
  44. font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
  45. const char* text = "Skia";
  46. ToolUtils::add_to_text_blob(&builder, text, font, 0, 0);
  47. // large
  48. SkRect bounds;
  49. font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
  50. SkScalar yOffset = bounds.height();
  51. font.setSize(162);
  52. ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
  53. // Medium
  54. font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
  55. yOffset += bounds.height();
  56. font.setSize(72);
  57. ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
  58. // Small
  59. font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
  60. yOffset += bounds.height();
  61. font.setSize(32);
  62. ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
  63. // micro (will fall out of distance field text even if distance field text is enabled)
  64. font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
  65. yOffset += bounds.height();
  66. font.setSize(14);
  67. ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
  68. // Zero size.
  69. font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
  70. yOffset += bounds.height();
  71. font.setSize(0);
  72. ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
  73. // build
  74. fBlob = builder.make();
  75. }
  76. SkString onShortName() override {
  77. return SkStringPrintf("textblobmixedsizes%s",
  78. fUseDFT ? "_df" : "");
  79. }
  80. SkISize onISize() override {
  81. return SkISize::Make(kWidth, kHeight);
  82. }
  83. void onDraw(SkCanvas* inputCanvas) override {
  84. SkCanvas* canvas = inputCanvas;
  85. sk_sp<SkSurface> surface;
  86. if (fUseDFT) {
  87. // Create a new Canvas to enable DFT
  88. GrContext* ctx = inputCanvas->getGrContext();
  89. SkISize size = onISize();
  90. sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace();
  91. SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(),
  92. kPremul_SkAlphaType, colorSpace);
  93. SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
  94. SkSurfaceProps::kLegacyFontHost_InitType);
  95. surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
  96. canvas = surface.get() ? surface->getCanvas() : inputCanvas;
  97. // init our new canvas with the old canvas's matrix
  98. canvas->setMatrix(inputCanvas->getTotalMatrix());
  99. }
  100. canvas->drawColor(SK_ColorWHITE);
  101. SkRect bounds = fBlob->bounds();
  102. const int kPadX = SkScalarFloorToInt(bounds.width() / 3);
  103. const int kPadY = SkScalarFloorToInt(bounds.height() / 3);
  104. int rowCount = 0;
  105. canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
  106. canvas->save();
  107. SkRandom random;
  108. SkPaint paint;
  109. if (!fUseDFT) {
  110. paint.setColor(SK_ColorWHITE);
  111. }
  112. paint.setAntiAlias(false);
  113. const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8));
  114. // setup blur paint
  115. SkPaint blurPaint(paint);
  116. blurPaint.setColor(SK_ColorBLACK);
  117. blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, kSigma));
  118. for (int i = 0; i < 4; i++) {
  119. canvas->save();
  120. switch (i % 2) {
  121. case 0:
  122. canvas->rotate(random.nextF() * 45.f);
  123. break;
  124. case 1:
  125. canvas->rotate(-random.nextF() * 45.f);
  126. break;
  127. }
  128. if (!fUseDFT) {
  129. canvas->drawTextBlob(fBlob, 0, 0, blurPaint);
  130. }
  131. canvas->drawTextBlob(fBlob, 0, 0, paint);
  132. canvas->restore();
  133. canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0);
  134. ++rowCount;
  135. if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) {
  136. canvas->restore();
  137. canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY);
  138. canvas->save();
  139. rowCount = 0;
  140. }
  141. }
  142. canvas->restore();
  143. // render offscreen buffer
  144. if (surface) {
  145. SkAutoCanvasRestore acr(inputCanvas, true);
  146. // since we prepended this matrix already, we blit using identity
  147. inputCanvas->resetMatrix();
  148. inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
  149. }
  150. }
  151. private:
  152. sk_sp<SkTextBlob> fBlob;
  153. static constexpr int kWidth = 2100;
  154. static constexpr int kHeight = 1900;
  155. bool fUseDFT;
  156. typedef GM INHERITED;
  157. };
  158. //////////////////////////////////////////////////////////////////////////////
  159. DEF_GM( return new TextBlobMixedSizes(false); )
  160. DEF_GM( return new TextBlobMixedSizes(true); )
  161. }