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