1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMetrics.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkUTF.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker #include <string.h>
26*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
27*c8dee2aaSAndroid Build Coastguard Worker
make_hpos_test_blob_utf8(const char * text,const SkFont & font)28*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkTextBlob> make_hpos_test_blob_utf8(const char* text, const SkFont& font) {
29*c8dee2aaSAndroid Build Coastguard Worker constexpr SkTextEncoding enc = SkTextEncoding::kUTF8;
30*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobBuilder builder;
31*c8dee2aaSAndroid Build Coastguard Worker size_t len = strlen(text);
32*c8dee2aaSAndroid Build Coastguard Worker int glyphCount = font.countText(text, len, enc);
33*c8dee2aaSAndroid Build Coastguard Worker const auto& buffer = builder.allocRunPosH(font, glyphCount, 0);
34*c8dee2aaSAndroid Build Coastguard Worker (void)font.textToGlyphs(text, len, enc, buffer.glyphs, glyphCount);
35*c8dee2aaSAndroid Build Coastguard Worker font.getXPos(buffer.glyphs, glyphCount, buffer.pos);
36*c8dee2aaSAndroid Build Coastguard Worker return builder.make();
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker class ScaledEmojiGM : public GM {
42*c8dee2aaSAndroid Build Coastguard Worker public:
ScaledEmojiGM(ToolUtils::EmojiFontFormat format)43*c8dee2aaSAndroid Build Coastguard Worker ScaledEmojiGM(ToolUtils::EmojiFontFormat format) : fFormat(format) {}
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker protected:
46*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiTestSample fEmojiFont;
47*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()48*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { fEmojiFont = ToolUtils::EmojiSample(fFormat); }
49*c8dee2aaSAndroid Build Coastguard Worker
getName() const50*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
51*c8dee2aaSAndroid Build Coastguard Worker return SkString("scaledemoji_") += ToolUtils::NameForFontFormat(fFormat);
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker
getISize()54*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(1200, 1200); }
55*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)56*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
57*c8dee2aaSAndroid Build Coastguard Worker if (!fEmojiFont.typeface) {
58*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = SkStringPrintf("Unable to instantiate emoji test font of format %s.",
59*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::NameForFontFormat(fFormat).c_str());
60*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(SK_ColorGRAY);
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
66*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fEmojiFont.typeface);
67*c8dee2aaSAndroid Build Coastguard Worker font.setEdging(SkFont::Edging::kAlias);
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker const char* text = fEmojiFont.sampleText;
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker // draw text at different point sizes
72*c8dee2aaSAndroid Build Coastguard Worker // Testing GPU bitmap path, SDF path with no scaling,
73*c8dee2aaSAndroid Build Coastguard Worker // SDF path with scaling, path rendering with scaling
74*c8dee2aaSAndroid Build Coastguard Worker SkFontMetrics metrics;
75*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 0;
76*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar textSize : {70, 180, 270, 340}) {
77*c8dee2aaSAndroid Build Coastguard Worker font.setSize(textSize);
78*c8dee2aaSAndroid Build Coastguard Worker font.getMetrics(&metrics);
79*c8dee2aaSAndroid Build Coastguard Worker y += -metrics.fAscent;
80*c8dee2aaSAndroid Build Coastguard Worker canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 10, y, font, paint);
81*c8dee2aaSAndroid Build Coastguard Worker y += metrics.fDescent + metrics.fLeading;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker private:
88*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiFontFormat fFormat;
89*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
90*c8dee2aaSAndroid Build Coastguard Worker };
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker class ScaledEmojiPosGM : public GM {
93*c8dee2aaSAndroid Build Coastguard Worker public:
ScaledEmojiPosGM(ToolUtils::EmojiFontFormat format)94*c8dee2aaSAndroid Build Coastguard Worker ScaledEmojiPosGM(ToolUtils::EmojiFontFormat format) : fFormat(format) {}
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker protected:
97*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiTestSample fEmojiFont;
98*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()99*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { fEmojiFont = ToolUtils::EmojiSample(fFormat); }
100*c8dee2aaSAndroid Build Coastguard Worker
getName() const101*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
102*c8dee2aaSAndroid Build Coastguard Worker return SkString("scaledemojipos_") += ToolUtils::NameForFontFormat(fFormat);
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker
getISize()105*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(1200, 1200); }
106*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)107*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
108*c8dee2aaSAndroid Build Coastguard Worker if (!fEmojiFont.typeface) {
109*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = SkStringPrintf("Unable to instantiate emoji test font of format %s.",
110*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::NameForFontFormat(fFormat).c_str());
111*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(SK_ColorGRAY);
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
117*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fEmojiFont.typeface, 12);
118*c8dee2aaSAndroid Build Coastguard Worker const char* text = fEmojiFont.sampleText;
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker // draw text at different point sizes
121*c8dee2aaSAndroid Build Coastguard Worker // Testing GPU bitmap path, SDF path with no scaling,
122*c8dee2aaSAndroid Build Coastguard Worker // SDF path with scaling, path rendering with scaling
123*c8dee2aaSAndroid Build Coastguard Worker SkFontMetrics metrics;
124*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 0;
125*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar textSize : {70, 180, 270, 340}) {
126*c8dee2aaSAndroid Build Coastguard Worker font.setSize(textSize);
127*c8dee2aaSAndroid Build Coastguard Worker font.getMetrics(&metrics);
128*c8dee2aaSAndroid Build Coastguard Worker y += -metrics.fAscent;
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> blob = make_hpos_test_blob_utf8(text, font);
131*c8dee2aaSAndroid Build Coastguard Worker // Draw with an origin.
132*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(blob, 10, y, paint);
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Worker // Draw with shifted canvas.
135*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
136*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(750, 0);
137*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(blob, 10, y, paint);
138*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker y += metrics.fDescent + metrics.fLeading;
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker private:
147*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiFontFormat fFormat;
148*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
149*c8dee2aaSAndroid Build Coastguard Worker };
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker class ScaledEmojiPerspectiveGM : public GM {
152*c8dee2aaSAndroid Build Coastguard Worker public:
ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat format)153*c8dee2aaSAndroid Build Coastguard Worker ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat format) : fFormat(format) {}
154*c8dee2aaSAndroid Build Coastguard Worker
155*c8dee2aaSAndroid Build Coastguard Worker protected:
156*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiTestSample fEmojiFont;
157*c8dee2aaSAndroid Build Coastguard Worker SkString fStripSpacesSampleText;
158*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()159*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
160*c8dee2aaSAndroid Build Coastguard Worker fEmojiFont = ToolUtils::EmojiSample(fFormat);
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker int count = 0;
163*c8dee2aaSAndroid Build Coastguard Worker const char* ch_ptr = fEmojiFont.sampleText;
164*c8dee2aaSAndroid Build Coastguard Worker const char* ch_end = ch_ptr + strlen(ch_ptr);
165*c8dee2aaSAndroid Build Coastguard Worker while (ch_ptr < ch_end && count < 2) {
166*c8dee2aaSAndroid Build Coastguard Worker SkUnichar ch = SkUTF::NextUTF8(&ch_ptr, ch_end);
167*c8dee2aaSAndroid Build Coastguard Worker if (ch != ' ') {
168*c8dee2aaSAndroid Build Coastguard Worker fStripSpacesSampleText.appendUnichar(ch);
169*c8dee2aaSAndroid Build Coastguard Worker ++count;
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker }
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
getName() const174*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
175*c8dee2aaSAndroid Build Coastguard Worker return SkString("scaledemojiperspective_") += ToolUtils::NameForFontFormat(fFormat);
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker
getISize()178*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(1200, 1200); }
179*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)180*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
181*c8dee2aaSAndroid Build Coastguard Worker if (!fEmojiFont.typeface) {
182*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = SkStringPrintf("Unable to instantiate emoji test font of format %s.",
183*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::NameForFontFormat(fFormat).c_str());
184*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker
187*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(SK_ColorGRAY);
188*c8dee2aaSAndroid Build Coastguard Worker SkMatrix taper;
189*c8dee2aaSAndroid Build Coastguard Worker taper.setPerspY(-0.0025f);
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
192*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fEmojiFont.typeface, 40);
193*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> blob = make_hpos_test_blob_utf8(fStripSpacesSampleText.c_str(), font);
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker // draw text at different point sizes
196*c8dee2aaSAndroid Build Coastguard Worker // Testing GPU bitmap path, SDF path with no scaling,
197*c8dee2aaSAndroid Build Coastguard Worker // SDF path with scaling, path rendering with scaling
198*c8dee2aaSAndroid Build Coastguard Worker SkFontMetrics metrics;
199*c8dee2aaSAndroid Build Coastguard Worker font.getMetrics(&metrics);
200*c8dee2aaSAndroid Build Coastguard Worker for (auto rotate : {0.0, 45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0}) {
201*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
202*c8dee2aaSAndroid Build Coastguard Worker SkMatrix perspective;
203*c8dee2aaSAndroid Build Coastguard Worker perspective.postTranslate(-600, -600);
204*c8dee2aaSAndroid Build Coastguard Worker perspective.postConcat(taper);
205*c8dee2aaSAndroid Build Coastguard Worker perspective.postRotate(rotate);
206*c8dee2aaSAndroid Build Coastguard Worker perspective.postTranslate(600, 600);
207*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(perspective);
208*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 670;
209*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 5; i++) {
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker y += -metrics.fAscent;
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker // Draw with an origin.
214*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(blob, 565, y, paint);
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker y += metrics.fDescent + metrics.fLeading;
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker private:
225*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::EmojiFontFormat fFormat;
226*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
227*c8dee2aaSAndroid Build Coastguard Worker };
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
230*c8dee2aaSAndroid Build Coastguard Worker
231*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiGM(ToolUtils::EmojiFontFormat::Cbdt);)
232*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPosGM(ToolUtils::EmojiFontFormat::Cbdt);)
233*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat::Cbdt);)
234*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiGM(ToolUtils::EmojiFontFormat::Sbix);)
235*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPosGM(ToolUtils::EmojiFontFormat::Sbix);)
236*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat::Sbix);)
237*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiGM(ToolUtils::EmojiFontFormat::ColrV0);)
238*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPosGM(ToolUtils::EmojiFontFormat::ColrV0);)
239*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat::ColrV0);)
240*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiGM(ToolUtils::EmojiFontFormat::Svg);)
241*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPosGM(ToolUtils::EmojiFontFormat::Svg);)
242*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat::Svg);)
243*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiGM(ToolUtils::EmojiFontFormat::Test);)
244*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPosGM(ToolUtils::EmojiFontFormat::Test);)
245*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new ScaledEmojiPerspectiveGM(ToolUtils::EmojiFontFormat::Test);)
246*c8dee2aaSAndroid Build Coastguard Worker
247*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
248