1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 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/SkFont.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/ports/SkTypeface_fontations.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
17*c8dee2aaSAndroid Build Coastguard Worker
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker namespace {
22*c8dee2aaSAndroid Build Coastguard Worker const SkScalar kTextSizes[] = {12, 18, 30, 120};
23*c8dee2aaSAndroid Build Coastguard Worker const char kReportFontName[] = "fonts/Roboto-Regular.ttf";
24*c8dee2aaSAndroid Build Coastguard Worker const SkScalar kDumpFontSize = 20.0f;
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker // TODO(drott): Test these dumps is in a unit test instead of dumping them to GM surface.
dumpToCanvas(SkCanvas * canvas,SkString text,sk_sp<SkTypeface> reportTypeface)27*c8dee2aaSAndroid Build Coastguard Worker void dumpToCanvas(SkCanvas* canvas, SkString text, sk_sp<SkTypeface> reportTypeface) {
28*c8dee2aaSAndroid Build Coastguard Worker canvas->drawSimpleText(text.c_str(),
29*c8dee2aaSAndroid Build Coastguard Worker text.size() - 1,
30*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding::kUTF8,
31*c8dee2aaSAndroid Build Coastguard Worker 0,
32*c8dee2aaSAndroid Build Coastguard Worker 0,
33*c8dee2aaSAndroid Build Coastguard Worker SkFont(reportTypeface, kDumpFontSize),
34*c8dee2aaSAndroid Build Coastguard Worker SkPaint());
35*c8dee2aaSAndroid Build Coastguard Worker }
36*c8dee2aaSAndroid Build Coastguard Worker
dumpLocalizedStrings(SkCanvas * canvas,sk_sp<SkTypeface> typeface,sk_sp<SkTypeface> reportTypeface)37*c8dee2aaSAndroid Build Coastguard Worker void dumpLocalizedStrings(SkCanvas* canvas,
38*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> typeface,
39*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> reportTypeface) {
40*c8dee2aaSAndroid Build Coastguard Worker auto family_names = typeface->createFamilyNameIterator();
41*c8dee2aaSAndroid Build Coastguard Worker SkTypeface::LocalizedString famName;
42*c8dee2aaSAndroid Build Coastguard Worker SkString localizedName;
43*c8dee2aaSAndroid Build Coastguard Worker while (family_names->next(&famName)) {
44*c8dee2aaSAndroid Build Coastguard Worker localizedName.printf(
45*c8dee2aaSAndroid Build Coastguard Worker "Name: %s Language: %s\n", famName.fString.c_str(), famName.fLanguage.c_str());
46*c8dee2aaSAndroid Build Coastguard Worker dumpToCanvas(canvas, localizedName, reportTypeface);
47*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kDumpFontSize * 1.2);
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker family_names->unref();
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
dumpGlyphCount(SkCanvas * canvas,sk_sp<SkTypeface> typeface,sk_sp<SkTypeface> reportTypeface)52*c8dee2aaSAndroid Build Coastguard Worker void dumpGlyphCount(SkCanvas* canvas,
53*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> typeface,
54*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> reportTypeface) {
55*c8dee2aaSAndroid Build Coastguard Worker SkString glyphCount;
56*c8dee2aaSAndroid Build Coastguard Worker glyphCount.printf("Num glyphs: %d\n", typeface->countGlyphs());
57*c8dee2aaSAndroid Build Coastguard Worker dumpToCanvas(canvas, glyphCount, reportTypeface);
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker
dumpFamilyAndPostscriptName(SkCanvas * canvas,sk_sp<SkTypeface> typeface,sk_sp<SkTypeface> reportTypeface)60*c8dee2aaSAndroid Build Coastguard Worker void dumpFamilyAndPostscriptName(SkCanvas* canvas,
61*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> typeface,
62*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> reportTypeface) {
63*c8dee2aaSAndroid Build Coastguard Worker SkString name;
64*c8dee2aaSAndroid Build Coastguard Worker typeface->getFamilyName(&name);
65*c8dee2aaSAndroid Build Coastguard Worker SkString nameDump;
66*c8dee2aaSAndroid Build Coastguard Worker nameDump.printf("Family name: %s\n", name.c_str());
67*c8dee2aaSAndroid Build Coastguard Worker dumpToCanvas(canvas, nameDump, reportTypeface);
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker if (typeface->getPostScriptName(&name)) {
70*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kDumpFontSize * 1.2);
71*c8dee2aaSAndroid Build Coastguard Worker nameDump.printf("PS Name: %s\n", name.c_str());
72*c8dee2aaSAndroid Build Coastguard Worker dumpToCanvas(canvas, nameDump, reportTypeface);
73*c8dee2aaSAndroid Build Coastguard Worker } else {
74*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kDumpFontSize * 1.2);
75*c8dee2aaSAndroid Build Coastguard Worker nameDump.printf("No Postscript name.");
76*c8dee2aaSAndroid Build Coastguard Worker dumpToCanvas(canvas, nameDump, reportTypeface);
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker } // namespace
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker class FontationsTypefaceGM : public GM {
83*c8dee2aaSAndroid Build Coastguard Worker public:
84*c8dee2aaSAndroid Build Coastguard Worker enum class TypefaceConstruction {
85*c8dee2aaSAndroid Build Coastguard Worker kMakeWithFontArguments,
86*c8dee2aaSAndroid Build Coastguard Worker kCloneWithFontArguments,
87*c8dee2aaSAndroid Build Coastguard Worker };
FontationsTypefaceGM(const char * testName,const char * testFontFilename,std::initializer_list<SkFontArguments::VariationPosition::Coordinate> specifiedVariations,TypefaceConstruction construction=TypefaceConstruction::kMakeWithFontArguments)88*c8dee2aaSAndroid Build Coastguard Worker FontationsTypefaceGM(const char* testName,
89*c8dee2aaSAndroid Build Coastguard Worker const char* testFontFilename,
90*c8dee2aaSAndroid Build Coastguard Worker std::initializer_list<SkFontArguments::VariationPosition::Coordinate>
91*c8dee2aaSAndroid Build Coastguard Worker specifiedVariations,
92*c8dee2aaSAndroid Build Coastguard Worker TypefaceConstruction construction = TypefaceConstruction::kMakeWithFontArguments)
93*c8dee2aaSAndroid Build Coastguard Worker : fTestName(testName)
94*c8dee2aaSAndroid Build Coastguard Worker , fTestFontFilename(testFontFilename)
95*c8dee2aaSAndroid Build Coastguard Worker , fConstruction(construction) {
96*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(SK_ColorWHITE);
97*c8dee2aaSAndroid Build Coastguard Worker fVariationPosition.coordinateCount = specifiedVariations.size();
98*c8dee2aaSAndroid Build Coastguard Worker fCoordinates = std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>(
99*c8dee2aaSAndroid Build Coastguard Worker specifiedVariations.size());
100*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < specifiedVariations.size(); ++i) {
101*c8dee2aaSAndroid Build Coastguard Worker fCoordinates[i] = std::data(specifiedVariations)[i];
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker fVariationPosition.coordinates = fCoordinates.get();
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker protected:
onOnceBeforeDraw()108*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
109*c8dee2aaSAndroid Build Coastguard Worker if (fConstruction == TypefaceConstruction::kMakeWithFontArguments) {
110*c8dee2aaSAndroid Build Coastguard Worker fTestTypeface = SkTypeface_Make_Fontations(
111*c8dee2aaSAndroid Build Coastguard Worker GetResourceAsStream(fTestFontFilename),
112*c8dee2aaSAndroid Build Coastguard Worker SkFontArguments().setVariationDesignPosition(fVariationPosition));
113*c8dee2aaSAndroid Build Coastguard Worker } else {
114*c8dee2aaSAndroid Build Coastguard Worker fTestTypeface = SkTypeface_Make_Fontations(GetResourceAsStream(fTestFontFilename),
115*c8dee2aaSAndroid Build Coastguard Worker SkFontArguments())
116*c8dee2aaSAndroid Build Coastguard Worker ->makeClone(SkFontArguments().setVariationDesignPosition(
117*c8dee2aaSAndroid Build Coastguard Worker fVariationPosition));
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker fReportTypeface =
120*c8dee2aaSAndroid Build Coastguard Worker SkTypeface_Make_Fontations(GetResourceAsStream(kReportFontName), SkFontArguments());
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker
getName() const123*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
124*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("typeface_fontations_%s", fTestName.c_str());
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker
getISize()127*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(400, 200); }
128*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)129*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
130*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
131*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLACK);
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker if (!fTestTypeface) {
134*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "Unable to initialize typeface.";
135*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker SkFont font(fTestTypeface);
139*c8dee2aaSAndroid Build Coastguard Worker const char32_t testText[] = U"abc";
140*c8dee2aaSAndroid Build Coastguard Worker size_t testTextBytesize = std::char_traits<char32_t>::length(testText) * sizeof(char32_t);
141*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = 100;
142*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = 150;
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar textSize : kTextSizes) {
145*c8dee2aaSAndroid Build Coastguard Worker font.setSize(textSize);
146*c8dee2aaSAndroid Build Coastguard Worker y += font.getSpacing();
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker /* Draw origin marker as a green dot. */
149*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
150*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeXYWH(x, y, 2, 2), paint);
151*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLACK);
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker canvas->drawSimpleText(
154*c8dee2aaSAndroid Build Coastguard Worker testText, testTextBytesize, SkTextEncoding::kUTF32, x, y, font, paint);
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
157*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(100, 470);
158*c8dee2aaSAndroid Build Coastguard Worker dumpGlyphCount(canvas, fTestTypeface, fReportTypeface);
159*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kDumpFontSize * 1.2);
160*c8dee2aaSAndroid Build Coastguard Worker dumpLocalizedStrings(canvas, fTestTypeface, fReportTypeface);
161*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, kDumpFontSize * 1.2);
162*c8dee2aaSAndroid Build Coastguard Worker dumpFamilyAndPostscriptName(canvas, fTestTypeface, fReportTypeface);
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
165*c8dee2aaSAndroid Build Coastguard Worker }
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker private:
168*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker const SkString fTestName;
171*c8dee2aaSAndroid Build Coastguard Worker const char* fTestFontFilename;
172*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fTestTypeface;
173*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fReportTypeface;
174*c8dee2aaSAndroid Build Coastguard Worker SkFontArguments::VariationPosition fVariationPosition;
175*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoordinates;
176*c8dee2aaSAndroid Build Coastguard Worker TypefaceConstruction fConstruction;
177*c8dee2aaSAndroid Build Coastguard Worker };
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker namespace {
operator ""_t(const char * tagName,size_t size)180*c8dee2aaSAndroid Build Coastguard Worker SkFourByteTag constexpr operator"" _t(const char* tagName, size_t size) {
181*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size == 4);
182*c8dee2aaSAndroid Build Coastguard Worker return SkSetFourByteTag(tagName[0], tagName[1], tagName[2], tagName[3]);
183*c8dee2aaSAndroid Build Coastguard Worker }
184*c8dee2aaSAndroid Build Coastguard Worker } // namespace
185*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsTypefaceGM("roboto", "fonts/Roboto-Regular.ttf", {});)
186*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsTypefaceGM(
187*c8dee2aaSAndroid Build Coastguard Worker "distortable_light",
188*c8dee2aaSAndroid Build Coastguard Worker "fonts/Distortable.ttf",
189*c8dee2aaSAndroid Build Coastguard Worker {{"wght"_t, 0.5f}}))
190*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsTypefaceGM(
191*c8dee2aaSAndroid Build Coastguard Worker "distortable_bold",
192*c8dee2aaSAndroid Build Coastguard Worker "fonts/Distortable.ttf",
193*c8dee2aaSAndroid Build Coastguard Worker {{"wght"_t, 2.0f}},
194*c8dee2aaSAndroid Build Coastguard Worker FontationsTypefaceGM::TypefaceConstruction::kCloneWithFontArguments);)
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
197