dftext_blob_persp.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 "gm/gm.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkColorSpace.h"
  11. #include "include/core/SkFont.h"
  12. #include "include/core/SkImageInfo.h"
  13. #include "include/core/SkMatrix.h"
  14. #include "include/core/SkPaint.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/core/SkRefCnt.h"
  17. #include "include/core/SkScalar.h"
  18. #include "include/core/SkSize.h"
  19. #include "include/core/SkString.h"
  20. #include "include/core/SkSurface.h"
  21. #include "include/core/SkSurfaceProps.h"
  22. #include "include/core/SkTextBlob.h"
  23. #include "include/core/SkTypes.h"
  24. #include "include/private/SkTArray.h"
  25. #include "tools/ToolUtils.h"
  26. #include <initializer_list>
  27. class GrContext;
  28. /**
  29. * This GM tests reusing the same text blobs with distance fields rendering using various
  30. * combinations of perspective and non-perspetive matrices, scissor clips, and different x,y params
  31. * passed to the draw.
  32. */
  33. class DFTextBlobPerspGM : public skiagm::GM {
  34. public:
  35. DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); }
  36. protected:
  37. SkString onShortName() override {
  38. return SkString("dftext_blob_persp");
  39. }
  40. SkISize onISize() override { return SkISize::Make(900, 350); }
  41. void onOnceBeforeDraw() override {
  42. for (int i = 0; i < 3; ++i) {
  43. SkFont font;
  44. font.setSize(32);
  45. font.setEdging(i == 0 ? SkFont::Edging::kAlias :
  46. (i == 1 ? SkFont::Edging::kAntiAlias :
  47. SkFont::Edging::kSubpixelAntiAlias));
  48. font.setSubpixel(true);
  49. SkTextBlobBuilder builder;
  50. ToolUtils::add_to_text_blob(&builder, "SkiaText", font, 0, 0);
  51. fBlobs.emplace_back(builder.make());
  52. }
  53. }
  54. void onDraw(SkCanvas* inputCanvas) override {
  55. // set up offscreen rendering with distance field text
  56. GrContext* ctx = inputCanvas->getGrContext();
  57. SkISize size = this->onISize();
  58. if (!inputCanvas->getBaseLayerSize().isEmpty()) {
  59. size = inputCanvas->getBaseLayerSize();
  60. }
  61. SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType,
  62. inputCanvas->imageInfo().refColorSpace());
  63. SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
  64. SkSurfaceProps::kLegacyFontHost_InitType);
  65. auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
  66. SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;
  67. // init our new canvas with the old canvas's matrix
  68. canvas->setMatrix(inputCanvas->getTotalMatrix());
  69. SkScalar x = 0, y = 0;
  70. SkScalar maxH = 0;
  71. for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) {
  72. for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) {
  73. for (auto& blob : fBlobs) {
  74. for (bool clip : {false, true}) {
  75. canvas->save();
  76. SkScalar w = blob->bounds().width();
  77. SkScalar h = blob->bounds().height();
  78. if (clip) {
  79. auto rect =
  80. SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f);
  81. canvas->clipRect(rect, false);
  82. }
  83. this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm);
  84. x += w + 20.f;
  85. maxH = SkTMax(h, maxH);
  86. canvas->restore();
  87. }
  88. }
  89. x = 0;
  90. y += maxH + 20.f;
  91. maxH = 0;
  92. }
  93. }
  94. // render offscreen buffer
  95. if (surface) {
  96. SkAutoCanvasRestore acr(inputCanvas, true);
  97. // since we prepended this matrix already, we blit using identity
  98. inputCanvas->resetMatrix();
  99. inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
  100. }
  101. }
  102. private:
  103. enum class PerspMode { kNone, kX, kY, kXY };
  104. enum class TranslateWithMatrix : bool { kNo, kYes };
  105. void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y,
  106. PerspMode perspMode, TranslateWithMatrix translateWithMatrix) {
  107. canvas->save();
  108. SkMatrix persp = SkMatrix::I();
  109. switch (perspMode) {
  110. case PerspMode::kNone:
  111. break;
  112. case PerspMode::kX:
  113. persp.setPerspX(0.005f);
  114. break;
  115. case PerspMode::kY:
  116. persp.setPerspY(00.005f);
  117. break;
  118. case PerspMode::kXY:
  119. persp.setPerspX(-0.001f);
  120. persp.setPerspY(-0.0015f);
  121. break;
  122. }
  123. persp = SkMatrix::Concat(persp, SkMatrix::MakeTrans(-x, -y));
  124. persp = SkMatrix::Concat(SkMatrix::MakeTrans(x, y), persp);
  125. canvas->concat(persp);
  126. if (TranslateWithMatrix::kYes == translateWithMatrix) {
  127. canvas->translate(x, y);
  128. x = 0;
  129. y = 0;
  130. }
  131. SkPaint paint;
  132. paint.setColor(color);
  133. canvas->drawTextBlob(blob, x, y, paint);
  134. canvas->restore();
  135. }
  136. SkTArray<sk_sp<SkTextBlob>> fBlobs;
  137. typedef skiagm::GM INHERITED;
  138. };
  139. DEF_GM(return new DFTextBlobPerspGM;)