2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "include/core/SkBlurTypes.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkFont.h"
14 #include "include/core/SkFontTypes.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkMaskFilter.h"
17 #include "include/core/SkPaint.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkScalar.h"
21 #include "include/core/SkSize.h"
22 #include "include/core/SkString.h"
23 #include "include/core/SkSurface.h"
24 #include "include/core/SkSurfaceProps.h"
25 #include "include/core/SkTextBlob.h"
26 #include "include/core/SkTypeface.h"
27 #include "include/core/SkTypes.h"
28 #include "include/utils/SkRandom.h"
29 #include "src/core/SkBlurMask.h"
30 #include "tools/Resources.h"
31 #include "tools/ToolUtils.h"
36 class TextBlobMixedSizes : public GM {
38 // This gm tests that textblobs of mixed sizes with a large glyph will render properly
39 TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {}
42 void onOnceBeforeDraw() override {
43 SkTextBlobBuilder builder;
45 // make textblob. To stress distance fields, we choose sizes appropriately
46 SkFont font(MakeResourceAsTypeface("fonts/HangingS.ttf"), 262);
47 font.setSubpixel(true);
48 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
50 const char* text = "Skia";
52 ToolUtils::add_to_text_blob(&builder, text, font, 0, 0);
56 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
57 SkScalar yOffset = bounds.height();
60 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
63 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
64 yOffset += bounds.height();
67 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
70 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
71 yOffset += bounds.height();
74 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
76 // micro (will fall out of distance field text even if distance field text is enabled)
77 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
78 yOffset += bounds.height();
81 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
84 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
85 yOffset += bounds.height();
88 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset);
91 fBlob = builder.make();
94 SkString onShortName() override {
95 return SkStringPrintf("textblobmixedsizes%s",
96 fUseDFT ? "_df" : "");
99 SkISize onISize() override {
100 return SkISize::Make(kWidth, kHeight);
103 void onDraw(SkCanvas* inputCanvas) override {
104 SkCanvas* canvas = inputCanvas;
105 sk_sp<SkSurface> surface;
107 // Create a new Canvas to enable DFT
108 auto ctx = inputCanvas->recordingContext();
109 SkISize size = onISize();
110 sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace();
111 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(),
112 kPremul_SkAlphaType, colorSpace);
113 SkSurfaceProps inputProps;
114 inputCanvas->getProps(&inputProps);
115 SkSurfaceProps props(
116 SkSurfaceProps::kUseDeviceIndependentFonts_Flag | inputProps.flags(),
117 inputProps.pixelGeometry());
118 surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
119 canvas = surface ? surface->getCanvas() : inputCanvas;
120 // init our new canvas with the old canvas's matrix
121 canvas->setMatrix(inputCanvas->getTotalMatrix());
123 canvas->drawColor(SK_ColorWHITE);
125 SkRect bounds = fBlob->bounds();
127 const int kPadX = SkScalarFloorToInt(bounds.width() / 3);
128 const int kPadY = SkScalarFloorToInt(bounds.height() / 3);
131 canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
137 paint.setColor(SK_ColorWHITE);
139 paint.setAntiAlias(false);
141 const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8));
144 SkPaint blurPaint(paint);
145 blurPaint.setColor(SK_ColorBLACK);
146 blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, kSigma));
148 for (int i = 0; i < 4; i++) {
152 canvas->rotate(random.nextF() * 45.f);
155 canvas->rotate(-random.nextF() * 45.f);
159 canvas->drawTextBlob(fBlob, 0, 0, blurPaint);
161 canvas->drawTextBlob(fBlob, 0, 0, paint);
163 canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0);
165 if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) {
167 canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY);
174 // render offscreen buffer
176 SkAutoCanvasRestore acr(inputCanvas, true);
177 // since we prepended this matrix already, we blit using identity
178 inputCanvas->resetMatrix();
179 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0);
184 sk_sp<SkTextBlob> fBlob;
186 static constexpr int kWidth = 2100;
187 static constexpr int kHeight = 1900;
191 using INHERITED = GM;
194 //////////////////////////////////////////////////////////////////////////////
196 DEF_GM( return new TextBlobMixedSizes(false); )
197 DEF_GM( return new TextBlobMixedSizes(true); )
198 } // namespace skiagm