1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFontStyle.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSurfaceProps.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypeface.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void getGlyphPositions(const SkPaint& paint, const uint16_t glyphs[],
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                             int count, SkScalar x, SkScalar y, SkPoint pos[]) {
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoSTMalloc<128, SkScalar> widthStorage(count);
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar* widths = widthStorage.get();
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.getTextWidths(glyphs, count * sizeof(uint16_t), widths);
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < count; ++i) {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        pos[i].set(x, y);
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        x += widths[i];
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void applyKerning(SkPoint pos[], const int32_t adjustments[], int count,
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         const SkPaint& paint) {
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar scale = paint.getTextSize() / paint.getTypeface()->getUnitsPerEm();
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar globalAdj = 0;
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < count - 1; ++i) {
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        globalAdj += adjustments[i] * scale;
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        pos[i + 1].fX += globalAdj;
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void drawKernText(SkCanvas* canvas, const void* text, size_t len,
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         SkScalar x, SkScalar y, const SkPaint& paint) {
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTypeface* face = paint.getTypeface();
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!face) {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawText(text, len, x, y, paint);
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoSTMalloc<128, uint16_t> glyphStorage(len);
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t* glyphs = glyphStorage.get();
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int glyphCount = paint.textToGlyphs(text, len, glyphs);
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (glyphCount < 1) {
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t* adjustments = adjustmentStorage.get();
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawText(text, len, x, y, paint);
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint glyphPaint(paint);
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint* pos = posStorage.get();
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos);
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    applyKerning(pos, adjustments, glyphCount, glyphPaint);
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint);
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic constexpr SkFontStyle gStyles[] = {
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontStyle::Normal(),
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontStyle::Bold(),
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontStyle::Italic(),
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontStyle::BoldItalic(),
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int gStylesCount = SK_ARRAY_COUNT(gStyles);
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass TypefaceStylesGM : public skiagm::GM {
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTypeface> fFaces[gStylesCount];
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fApplyKerning;
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TypefaceStylesGM(bool applyKerning)
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fApplyKerning(applyKerning) {
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        memset(fFaces, 0, sizeof(fFaces));
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onOnceBeforeDraw() override {
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < gStylesCount; i++) {
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fFaces[i] = SkTypeface::MakeFromName(nullptr, gStyles[i]);
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString name("typefacestyles");
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fApplyKerning) {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            name.append("_kerning");
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name.append(sk_tool_utils::platform_font_manager());
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return name;
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(640, 480);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setAntiAlias(true);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setTextSize(SkIntToScalar(30));
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons";
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const size_t textLen = strlen(text);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar x = SkIntToScalar(10);
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar dy = paint.getFontMetrics(nullptr);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar y = dy;
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fApplyKerning) {
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setSubpixelText(true);
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setLinearText(true);
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < gStylesCount; i++) {
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setTypeface(fFaces[i]);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawText(text, textLen, x, y, paint);
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fApplyKerning) {
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                drawKernText(canvas, text, textLen, x + 240, y, paint);
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            y += dy;
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef skiagm::GM INHERITED;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM( return new TypefaceStylesGM(false); )
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM( return new TypefaceStylesGM(true); )
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////////
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                       char character = 'A') {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        struct AliasType {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool antiAlias;
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool subpixelAntitalias;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool inLayer;
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } constexpr aliasTypes[] {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_BUILD_FOR_IOS
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // This gm crashes on iOS when drawing an embedded bitmap when requesting aliased rendering.
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // The crash looks like
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //   libTrueTypeScaler.dylib`<redacted> + 80
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //   stop reason = EXC_BAD_ACCESS (code=EXC_ARM_DA_ALIGN, address=...)
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //   ->  0x330b19d0 <+80>: strd   r2, r3, [r5, #36]
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //       0x330b19d4 <+84>: movs   r3, #0x0
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //       0x330b19d6 <+86>: add    r2, sp, #0x28
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            //       0x330b19d8 <+88>: ldr    r0, [r4, #0x4]
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Disable testing embedded bitmaps on iOS for now.
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // See https://bug.skia.org/5530 .
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { false, false, false },  // aliased
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true,  false, false },  // anti-aliased
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true,  true , false },  // subpixel anti-aliased
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true,  false, true  },  // anti-aliased in layer (flat pixel geometry)
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true,  true , true  },  // subpixel anti-aliased in layer (flat pixel geometry)
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // The hintgasp.ttf is designed for the following sizes to be different.
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_DOGRAY                                      0x0002   0<=ppem<=10
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_SYMMETRIC_SMOOTHING                         0x0008   0<=ppem<=10
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_GRIDFIT                                     0x0001  11<=ppem<=12
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_SYMMETRIC_GRIDFIT                           0x0004  11<=ppem<=12
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_DOGRAY|GASP_GRIDFIT                         0x0003  13<=ppem<=14
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // GASP_SYMMETRIC_SMOOTHING|GASP_SYMMETRIC_GRIDFIT  0x000C  13<=ppem<=14
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // (neither)                                        0x0000  15<=ppem
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Odd sizes have embedded bitmaps.
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        constexpr SkScalar textSizes[] = { 9, 10, 11, 12, 13, 14, 15, 16 };
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        constexpr SkPaint::Hinting hintingTypes[] = { SkPaint::kNo_Hinting,
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                      SkPaint::kSlight_Hinting,
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                      SkPaint::kNormal_Hinting,
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                      SkPaint::kFull_Hinting };
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        struct SubpixelType {
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool requested;
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkVector offset;
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } constexpr subpixelTypes[] = {
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { false, { 0.00, 0.00 } },
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true , { 0.00, 0.00 } },
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true , { 0.25, 0.00 } },
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { true , { 0.25, 0.25 } },
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        constexpr bool rotateABitTypes[] = { false, true };
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setTypeface(face);
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setEmbeddedBitmapText(true);
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar x = 0;
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar xMax = x;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar xBase = 0;
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar y = 0;  // The baseline of the previous output
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (const SubpixelType subpixel : subpixelTypes) {
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            y = 0;
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setSubpixelText(subpixel.requested);
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (const AliasType& alias : aliasTypes) {
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setAntiAlias(alias.antiAlias);
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setLCDRenderText(alias.subpixelAntitalias);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkAutoCanvasRestore acr(canvas, false);
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (alias.inLayer) {
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->saveLayer(nullptr, &paint);
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (const SkScalar& textSize : textSizes) {
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    x = xBase + 5;
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    paint.setTextSize(textSize);
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar dy = SkScalarCeilToScalar(paint.getFontMetrics(nullptr));
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    y += dy;
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (const SkPaint::Hinting& hinting : hintingTypes) {
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        paint.setHinting(hinting);
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        for (const bool& rotateABit : rotateABitTypes) {
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkAutoCanvasRestore acr(canvas, true);
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            if (rotateABit) {
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                canvas->rotate(2, x + subpixel.offset.x(),
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                  y + subpixel.offset.y());
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            }
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawText(&character, 1,
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             x + subpixel.offset.x(),
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                             y + subpixel.offset.y(), paint);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkScalar dx = SkScalarCeilToScalar(
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    paint.measureText(&character, 1)) + 5;
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            x += dx;
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            xMax = SkTMax(x, xMax);
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                y += 10;
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            xBase = xMax;
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_SIMPLE_GM_BG_NAME(typefacerendering, canvas, 640, 680, SK_ColorWHITE,
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkStringPrintf("typefacerendering%s",
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     sk_tool_utils::platform_font_manager())) {
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/hintgasp.ttf")) {
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw_typeface_rendering_gm(canvas, std::move(face));
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Type1 fonts don't currently work in Skia on Windows.
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_BUILD_FOR_WIN
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_SIMPLE_GM_BG_NAME(typefacerendering_pfa, canvas, 640, 680, SK_ColorWHITE,
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkStringPrintf("typefacerendering_pfa%s",
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     sk_tool_utils::platform_font_manager())) {
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/Roboto2-Regular.pfa")) {
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // This subsetted typeface doesn't have the character 'A'.
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw_typeface_rendering_gm(canvas, std::move(face), 'O');
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_SIMPLE_GM_BG_NAME(typefacerendering_pfb, canvas, 640, 680, SK_ColorWHITE,
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkStringPrintf("typefacerendering_pfb%s",
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     sk_tool_utils::platform_font_manager())) {
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/Roboto2-Regular.pfb")) {
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        draw_typeface_rendering_gm(canvas, std::move(face), 'O');
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
286