1e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt/*
2e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * Copyright 2015 Google Inc.
3e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt *
4e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * Use of this source code is governed by a BSD-style license that can be
5e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * found in the LICENSE file.
6e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt */
7e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
8e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "gm.h"
933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h"
10e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
11e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "Resources.h"
12e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkBlurMask.h"
13e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkBlurMaskFilter.h"
14e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkCanvas.h"
15e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkGradientShader.h"
16e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkImage.h"
17e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkRandom.h"
18e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkStream.h"
19e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkSurface.h"
20e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkTextBlob.h"
21e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkTypeface.h"
22e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
23e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittnamespace skiagm {
24e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittclass TextBlobMixedSizes : public GM {
25e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittpublic:
26e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    // This gm tests that textblobs of mixed sizes with a large glyph will render properly
27e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {}
28e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
29e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittprotected:
30e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    void onOnceBeforeDraw() override {
31e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkTextBlobBuilder builder;
32e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
33e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // make textblob.  To stress distance fields, we choose sizes appropriately
34e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkPaint paint;
35e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setAntiAlias(true);
36e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setSubpixelText(true);
37e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setLCDRenderText(true);
3853e5e7d4ce9d203fadc36b6349bcbb68862f0d22Hal Canary        paint.setTypeface(MakeResourceAsTypeface("fonts/HangingS.ttf"));
39e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
4033e91f1673123d3f19b372ec0660edd611f706a0joshualitt        const char* text = "Skia";
41e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
42e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // extra large
43e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setTextSize(262);
44e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
45e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, 0);
46e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
47e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // large
48e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkRect bounds;
49e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.measureText(text, strlen(text), &bounds);
50e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkScalar yOffset = bounds.height();
51e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setTextSize(162);
52e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
53e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset);
54e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
55e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // Medium
56e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.measureText(text, strlen(text), &bounds);
57e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        yOffset += bounds.height();
58e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setTextSize(72);
59e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
60e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset);
61e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
62e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // Small
63e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.measureText(text, strlen(text), &bounds);
64e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        yOffset += bounds.height();
65e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setTextSize(32);
66e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
67e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset);
68e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
69e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // micro (will fall out of distance field text even if distance field text is enabled)
70e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.measureText(text, strlen(text), &bounds);
71e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        yOffset += bounds.height();
72e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setTextSize(14);
73e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
74e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset);
75e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
7668c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen        // Zero size.
7768c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen        paint.measureText(text, strlen(text), &bounds);
7868c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen        yOffset += bounds.height();
7968c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen        paint.setTextSize(0);
8068c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen
8168c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen        sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset);
8268c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen
83e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // build
8437283c28aa5bea2204c18956e74f83b238d7a891fmalita        fBlob = builder.make();
85e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
86e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
87e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    SkString onShortName() override {
8858822d6994d33a823a29a4c6fa251ad1ce7267d6Hal Canary        return SkStringPrintf("textblobmixedsizes%s%s",
8958822d6994d33a823a29a4c6fa251ad1ce7267d6Hal Canary                              sk_tool_utils::platform_font_manager(),
9058822d6994d33a823a29a4c6fa251ad1ce7267d6Hal Canary                              fUseDFT ? "_df" : "");
91e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
92e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
93e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    SkISize onISize() override {
94e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        return SkISize::Make(kWidth, kHeight);
95e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
96e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
97e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    void onDraw(SkCanvas* inputCanvas) override {
98e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkCanvas* canvas = inputCanvas;
99e8f3062a36d3682f4019309a32b5b84dc9eddf8creed        sk_sp<SkSurface> surface;
100e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (fUseDFT) {
101e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
102e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // Create a new Canvas to enable DFT
103e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            GrContext* ctx = inputCanvas->getGrContext();
10452ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman            SkISize size = onISize();
105693fdbd6b81a860657612e7604430dd55d6e721bMike Reed            sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace();
10652ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman            SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(),
10752ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman                                                    kPremul_SkAlphaType, colorSpace);
1083a0dbde1cfa84b08c7dd5b597142e9f6179f2d07brianosman            SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
109e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                                 SkSurfaceProps::kLegacyFontHost_InitType);
110e8f3062a36d3682f4019309a32b5b84dc9eddf8creed            surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
111e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas = surface.get() ? surface->getCanvas() : inputCanvas;
112e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // init our new canvas with the old canvas's matrix
113e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->setMatrix(inputCanvas->getTotalMatrix());
114e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
115e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
116e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
117e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
118e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkRect bounds = fBlob->bounds();
119e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
120dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kPadX = SkScalarFloorToInt(bounds.width() / 3);
121dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kPadY = SkScalarFloorToInt(bounds.height() / 3);
122e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
123e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        int rowCount = 0;
124e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
125e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->save();
126e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkRandom random;
127e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
128e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkPaint paint;
129e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (!fUseDFT) {
130e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            paint.setColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
131e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
132e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setAntiAlias(false);
133e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
134dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8));
135e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
136e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // setup blur paint
137e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkPaint blurPaint(paint);
138e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        blurPaint.setColor(sk_tool_utils::color_to_565(SK_ColorBLACK));
139efdfd51b68a300d5c6e28743fe0344ca05d1cec9reed        blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kSigma));
140dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein
141e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        for (int i = 0; i < 4; i++) {
142e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->save();
143e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            switch (i % 2) {
144e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                case 0:
145e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    canvas->rotate(random.nextF() * 45.f);
146e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    break;
147e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                case 1:
148e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    canvas->rotate(-random.nextF() * 45.f);
149e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    break;
150e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
151e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            if (!fUseDFT) {
152e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->drawTextBlob(fBlob, 0, 0, blurPaint);
153e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
154e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->drawTextBlob(fBlob, 0, 0, paint);
155e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->restore();
156e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0);
157e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            ++rowCount;
158e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) {
159e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->restore();
160e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY);
161e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->save();
162e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                rowCount = 0;
163e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
164e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
165e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->restore();
166e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
167e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
168e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // render offscreen buffer
169e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (surface) {
170e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            SkAutoCanvasRestore acr(inputCanvas, true);
171e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // since we prepended this matrix already, we blit using identity
172e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            inputCanvas->resetMatrix();
1739ce9d6772df650ceb0511f275e1a83dffa78ff72reed            inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
174e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
175e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
176e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
177e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
178e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittprivate:
17937283c28aa5bea2204c18956e74f83b238d7a891fmalita    sk_sp<SkTextBlob> fBlob;
180e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
181dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kWidth = 2100;
182dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kHeight = 1900;
183e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
184e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    bool fUseDFT;
185e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
186e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    typedef GM INHERITED;
187e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt};
188e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
189e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt//////////////////////////////////////////////////////////////////////////////
190e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
191385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(false); )
192e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
193385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(true); )
194e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
195e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt}
196