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);
3813b9c95295f4c5732e34574789e721a6bc08f7b4bungeman        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 {
88e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkString name("textblobmixedsizes");
89e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (fUseDFT) {
90e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            name.appendf("_df");
91e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
92e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        return name;
93e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
94e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
95e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    SkISize onISize() override {
96e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        return SkISize::Make(kWidth, kHeight);
97e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
98e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
99e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    void onDraw(SkCanvas* inputCanvas) override {
100e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkCanvas* canvas = inputCanvas;
101e8f3062a36d3682f4019309a32b5b84dc9eddf8creed        sk_sp<SkSurface> surface;
102e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (fUseDFT) {
103e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
104e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // Create a new Canvas to enable DFT
105e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            GrContext* ctx = inputCanvas->getGrContext();
10652ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman            SkISize size = onISize();
107693fdbd6b81a860657612e7604430dd55d6e721bMike Reed            sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace();
10852ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman            SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(),
10952ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman                                                    kPremul_SkAlphaType, colorSpace);
1103a0dbde1cfa84b08c7dd5b597142e9f6179f2d07brianosman            SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
111e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                                 SkSurfaceProps::kLegacyFontHost_InitType);
112e8f3062a36d3682f4019309a32b5b84dc9eddf8creed            surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
113e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas = surface.get() ? surface->getCanvas() : inputCanvas;
114e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // init our new canvas with the old canvas's matrix
115e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->setMatrix(inputCanvas->getTotalMatrix());
116e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
117e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
118e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
119e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
120e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkRect bounds = fBlob->bounds();
121e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
122dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kPadX = SkScalarFloorToInt(bounds.width() / 3);
123dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const int kPadY = SkScalarFloorToInt(bounds.height() / 3);
124e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
125e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        int rowCount = 0;
126e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
127e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->save();
128e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkRandom random;
129e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
130e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkPaint paint;
131e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (!fUseDFT) {
132e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            paint.setColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
133e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
134e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        paint.setAntiAlias(false);
135e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
136dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8));
137e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
138e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // setup blur paint
139e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        SkPaint blurPaint(paint);
140e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        blurPaint.setColor(sk_tool_utils::color_to_565(SK_ColorBLACK));
141efdfd51b68a300d5c6e28743fe0344ca05d1cec9reed        blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kSigma));
142dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein
143e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        for (int i = 0; i < 4; i++) {
144e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->save();
145e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            switch (i % 2) {
146e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                case 0:
147e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    canvas->rotate(random.nextF() * 45.f);
148e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    break;
149e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                case 1:
150e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    canvas->rotate(-random.nextF() * 45.f);
151e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                    break;
152e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
153e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            if (!fUseDFT) {
154e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->drawTextBlob(fBlob, 0, 0, blurPaint);
155e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
156e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->drawTextBlob(fBlob, 0, 0, paint);
157e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->restore();
158e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0);
159e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            ++rowCount;
160e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) {
161e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->restore();
162e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY);
163e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                canvas->save();
164e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt                rowCount = 0;
165e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            }
166e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
167e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        canvas->restore();
168e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
169e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
170e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        // render offscreen buffer
171e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        if (surface) {
172e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            SkAutoCanvasRestore acr(inputCanvas, true);
173e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            // since we prepended this matrix already, we blit using identity
174e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt            inputCanvas->resetMatrix();
1759ce9d6772df650ceb0511f275e1a83dffa78ff72reed            inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
176e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt        }
177e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
178e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    }
179e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
180e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittprivate:
18137283c28aa5bea2204c18956e74f83b238d7a891fmalita    sk_sp<SkTextBlob> fBlob;
182e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
183dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kWidth = 2100;
184dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein    static constexpr int kHeight = 1900;
185e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
186e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    bool fUseDFT;
187e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
188e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt    typedef GM INHERITED;
189e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt};
190e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
191e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt//////////////////////////////////////////////////////////////////////////////
192e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt
193385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(false); )
194e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU
195385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(true); )
196e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif
197e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt}
198