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