blob: 271e89dd432c2c3cabdf398f3f96758b7dfd65b8 [file] [log] [blame]
Brian Salomon5c6ac642017-12-19 11:09:32 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkColorSpace.h"
12#include "include/core/SkFont.h"
13#include "include/core/SkImageInfo.h"
14#include "include/core/SkMatrix.h"
15#include "include/core/SkPaint.h"
16#include "include/core/SkRect.h"
17#include "include/core/SkRefCnt.h"
18#include "include/core/SkScalar.h"
19#include "include/core/SkSize.h"
20#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "include/core/SkSurface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040022#include "include/core/SkSurfaceProps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/core/SkTextBlob.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040024#include "include/core/SkTypes.h"
25#include "include/private/SkTArray.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "tools/ToolUtils.h"
Brian Salomon5c6ac642017-12-19 11:09:32 -050027
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include <initializer_list>
29
Brian Salomon5c6ac642017-12-19 11:09:32 -050030/**
31 * This GM tests reusing the same text blobs with distance fields rendering using various
32 * combinations of perspective and non-perspetive matrices, scissor clips, and different x,y params
33 * passed to the draw.
34 */
35class DFTextBlobPerspGM : public skiagm::GM {
36public:
37 DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); }
38
39protected:
40 SkString onShortName() override {
Mike Kleinbea1f942019-03-08 11:11:55 -060041 return SkString("dftext_blob_persp");
Brian Salomon5c6ac642017-12-19 11:09:32 -050042 }
43
44 SkISize onISize() override { return SkISize::Make(900, 350); }
45
46 void onOnceBeforeDraw() override {
47 for (int i = 0; i < 3; ++i) {
Mike Reedea8900e2018-12-22 17:37:30 -050048 SkFont font;
49 font.setSize(32);
50 font.setEdging(i == 0 ? SkFont::Edging::kAlias :
51 (i == 1 ? SkFont::Edging::kAntiAlias :
52 SkFont::Edging::kSubpixelAntiAlias));
53 font.setSubpixel(true);
Brian Salomon5c6ac642017-12-19 11:09:32 -050054 SkTextBlobBuilder builder;
Mike Kleinea3f0142019-03-20 11:12:10 -050055 ToolUtils::add_to_text_blob(&builder, "SkiaText", font, 0, 0);
Brian Salomon5c6ac642017-12-19 11:09:32 -050056 fBlobs.emplace_back(builder.make());
57 }
58 }
59
Mike Reedea8900e2018-12-22 17:37:30 -050060 void onDraw(SkCanvas* inputCanvas) override {
Robert Phillips16bf7d32020-07-07 10:20:27 -040061 // set up offscreen rendering with distance field text
62 auto ctx = inputCanvas->recordingContext();
Brian Salomon5c6ac642017-12-19 11:09:32 -050063 SkISize size = this->onISize();
64 if (!inputCanvas->getBaseLayerSize().isEmpty()) {
65 size = inputCanvas->getBaseLayerSize();
66 }
67 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType,
68 inputCanvas->imageInfo().refColorSpace());
69 SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
70 SkSurfaceProps::kLegacyFontHost_InitType);
71 auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
72 SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;
73 // init our new canvas with the old canvas's matrix
74 canvas->setMatrix(inputCanvas->getTotalMatrix());
Brian Salomon5c6ac642017-12-19 11:09:32 -050075 SkScalar x = 0, y = 0;
76 SkScalar maxH = 0;
77 for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) {
78 for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) {
79 for (auto& blob : fBlobs) {
80 for (bool clip : {false, true}) {
81 canvas->save();
82 SkScalar w = blob->bounds().width();
83 SkScalar h = blob->bounds().height();
84 if (clip) {
85 auto rect =
86 SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f);
87 canvas->clipRect(rect, false);
88 }
89 this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm);
90 x += w + 20.f;
Brian Osman788b9162020-02-07 10:36:46 -050091 maxH = std::max(h, maxH);
Brian Salomon5c6ac642017-12-19 11:09:32 -050092 canvas->restore();
93 }
94 }
95 x = 0;
96 y += maxH + 20.f;
97 maxH = 0;
98 }
99 }
Brian Salomon5c6ac642017-12-19 11:09:32 -0500100 // render offscreen buffer
101 if (surface) {
102 SkAutoCanvasRestore acr(inputCanvas, true);
103 // since we prepended this matrix already, we blit using identity
104 inputCanvas->resetMatrix();
105 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
106 }
Brian Salomon5c6ac642017-12-19 11:09:32 -0500107 }
108
109private:
110 enum class PerspMode { kNone, kX, kY, kXY };
111
112 enum class TranslateWithMatrix : bool { kNo, kYes };
113
114 void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y,
115 PerspMode perspMode, TranslateWithMatrix translateWithMatrix) {
116 canvas->save();
117 SkMatrix persp = SkMatrix::I();
118 switch (perspMode) {
119 case PerspMode::kNone:
120 break;
121 case PerspMode::kX:
122 persp.setPerspX(0.005f);
123 break;
124 case PerspMode::kY:
125 persp.setPerspY(00.005f);
126 break;
127 case PerspMode::kXY:
128 persp.setPerspX(-0.001f);
129 persp.setPerspY(-0.0015f);
130 break;
131 }
Mike Reed1f607332020-05-21 12:11:27 -0400132 persp = SkMatrix::Concat(persp, SkMatrix::Translate(-x, -y));
133 persp = SkMatrix::Concat(SkMatrix::Translate(x, y), persp);
Brian Salomon5c6ac642017-12-19 11:09:32 -0500134 canvas->concat(persp);
135 if (TranslateWithMatrix::kYes == translateWithMatrix) {
136 canvas->translate(x, y);
137 x = 0;
138 y = 0;
139 }
140 SkPaint paint;
141 paint.setColor(color);
142 canvas->drawTextBlob(blob, x, y, paint);
143 canvas->restore();
144 }
145
Brian Salomon343553a2018-09-05 15:41:23 -0400146 SkTArray<sk_sp<SkTextBlob>> fBlobs;
Brian Salomon5c6ac642017-12-19 11:09:32 -0500147 typedef skiagm::GM INHERITED;
148};
149
150DEF_GM(return new DFTextBlobPerspGM;)