• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/private/SkTArray.h"
26 #include "tools/ToolUtils.h"
27 
28 #include <initializer_list>
29 
30 /**
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  */
35 class DFTextBlobPerspGM : public skiagm::GM {
36 public:
DFTextBlobPerspGM()37     DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); }
38 
39 protected:
onShortName()40     SkString onShortName() override {
41         return SkString("dftext_blob_persp");
42     }
43 
onISize()44     SkISize onISize() override { return SkISize::Make(900, 350); }
45 
onOnceBeforeDraw()46     void onOnceBeforeDraw() override {
47         for (int i = 0; i < 3; ++i) {
48             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);
54             SkTextBlobBuilder builder;
55             ToolUtils::add_to_text_blob(&builder, "SkiaText", font, 0, 0);
56             fBlobs.emplace_back(builder.make());
57         }
58     }
59 
onDraw(SkCanvas * inputCanvas)60     void onDraw(SkCanvas* inputCanvas) override {
61         // set up offscreen rendering with distance field text
62         auto ctx = inputCanvas->recordingContext();
63         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 inputProps;
70         inputCanvas->getProps(&inputProps);
71         SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | inputProps.flags(),
72                              inputProps.pixelGeometry());
73         auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
74         SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas;
75         // init our new canvas with the old canvas's matrix
76         canvas->setMatrix(inputCanvas->getLocalToDeviceAs3x3());
77         SkScalar x = 0, y = 0;
78         SkScalar maxH = 0;
79         for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) {
80             for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) {
81                 for (auto& blob : fBlobs) {
82                     for (bool clip : {false, true}) {
83                         canvas->save();
84                         SkScalar w = blob->bounds().width();
85                         SkScalar h = blob->bounds().height();
86                         if (clip) {
87                             auto rect =
88                                     SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f);
89                             canvas->clipRect(rect, false);
90                         }
91                         this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm);
92                         x += w + 20.f;
93                         maxH = std::max(h, maxH);
94                         canvas->restore();
95                     }
96                 }
97                 x = 0;
98                 y += maxH + 20.f;
99                 maxH = 0;
100             }
101         }
102         // render offscreen buffer
103         if (surface) {
104             SkAutoCanvasRestore acr(inputCanvas, true);
105             // since we prepended this matrix already, we blit using identity
106             inputCanvas->resetMatrix();
107             inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0);
108         }
109     }
110 
111 private:
112     enum class PerspMode { kNone, kX, kY, kXY };
113 
114     enum class TranslateWithMatrix : bool { kNo, kYes };
115 
drawBlob(SkCanvas * canvas,SkTextBlob * blob,SkColor color,SkScalar x,SkScalar y,PerspMode perspMode,TranslateWithMatrix translateWithMatrix)116     void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y,
117                   PerspMode perspMode, TranslateWithMatrix translateWithMatrix) {
118         canvas->save();
119         SkMatrix persp = SkMatrix::I();
120         switch (perspMode) {
121             case PerspMode::kNone:
122                 break;
123             case PerspMode::kX:
124                 persp.setPerspX(0.005f);
125                 break;
126             case PerspMode::kY:
127                 persp.setPerspY(00.005f);
128                 break;
129             case PerspMode::kXY:
130                 persp.setPerspX(-0.001f);
131                 persp.setPerspY(-0.0015f);
132                 break;
133         }
134         persp = SkMatrix::Concat(persp, SkMatrix::Translate(-x, -y));
135         persp = SkMatrix::Concat(SkMatrix::Translate(x, y), persp);
136         canvas->concat(persp);
137         if (TranslateWithMatrix::kYes == translateWithMatrix) {
138             canvas->translate(x, y);
139             x = 0;
140             y = 0;
141         }
142         SkPaint paint;
143         paint.setColor(color);
144         canvas->drawTextBlob(blob, x, y, paint);
145         canvas->restore();
146     }
147 
148     SkTArray<sk_sp<SkTextBlob>> fBlobs;
149     using INHERITED = skiagm::GM;
150 };
151 
152 DEF_GM(return new DFTextBlobPerspGM;)
153