1 /*
2 * Copyright 2022 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "gm/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkFontMetrics.h"
13 #include "include/core/SkFontMgr.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkScalar.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkStream.h"
19 #include "include/core/SkString.h"
20 #include "include/core/SkTypeface.h"
21 #include "include/core/SkTypes.h"
22 #include "tools/Resources.h"
23 #include "tools/ToolUtils.h"
24 #include "tools/fonts/FontToolUtils.h"
25
26 #if defined(SK_TYPEFACE_FACTORY_FONTATIONS)
27 #include "include/ports/SkTypeface_fontations.h"
28 #endif
29
30 #include <string.h>
31
32 namespace skiagm {
33
34 // Copied from https://github.com/googlefonts/color-fonts#colrv1-test-font glyph descriptions
35 // markdown file.
36 namespace ColrV1TestDefinitions {
37 const uint32_t color_circles_palette[] = {0xf0e00, 0xf0e01};
38 };
39
40 namespace {
41 const char kColrCpalTestFontPath[] = "fonts/test_glyphs-glyf_colr_1.ttf";
42
43 constexpr SkFontArguments::Palette::Override kColorOverridesAll[] = {
44 // A gradient of dark to light purple for the circle palette test glyph.
45 // Randomly ordered with `shuf`.
46 // Add a repeat (later overrides override earlier overrides).
47 // Add three out of bounds entries (font has 12 palette entries).
48 // clang-format off
49 { 6, 0xffffff00},
50 { 2, 0xff76078f},
51 { 4, 0xffb404c4},
52 { 1, 0xff510970},
53 { 6, 0xfffa00ff},
54 { 8, 0xff888888},
55 {10, 0xff888888},
56 { 9, 0xff888888},
57 { 7, 0xff888888},
58 {11, 0xff888888},
59 { 0, 0xff310b55},
60 { 3, 0xff9606aa},
61 { 5, 0xffd802e2},
62 {13, 0xff00ffff},
63 {12, 0xff00ffff},
64 {static_cast<uint16_t>(-1), 0xff00ff00},
65 // clang-format on
66 };
67
68 constexpr SkFontArguments::Palette::Override kColorOverridesOne[] = {
69 {2, 0xff02dfe2},
70 };
71
72 constexpr SkFontArguments::Palette kLightPaletteOverride{2, nullptr, 0};
73 constexpr SkFontArguments::Palette kDarkPaletteOverride{1, nullptr, 0};
74 constexpr SkFontArguments::Palette kOnePaletteOverride{
75 0, kColorOverridesOne, std::size(kColorOverridesOne)};
76 constexpr SkFontArguments::Palette kAllPaletteOverride{
77 0, kColorOverridesAll, std::size(kColorOverridesAll)};
78
MakeTypefaceFromResource(const char * resource,const SkFontArguments & args)79 sk_sp<SkTypeface> MakeTypefaceFromResource(const char* resource, const SkFontArguments& args) {
80 return ToolUtils::TestFontMgr()->makeFromStream(GetResourceAsStream(resource), args);
81 }
82
83 } // namespace
84
85 class FontPaletteGM : public GM {
86 public:
FontPaletteGM(const char * test_name,const SkFontArguments::Palette & paletteOverride)87 FontPaletteGM(const char* test_name, const SkFontArguments::Palette& paletteOverride)
88 : fName(test_name), fPalette(paletteOverride) {}
89
90 protected:
91 sk_sp<SkTypeface> fTypefaceDefault;
92 sk_sp<SkTypeface> fTypefaceFromStream;
93 sk_sp<SkTypeface> fTypefaceCloned;
94
onOnceBeforeDraw()95 void onOnceBeforeDraw() override {
96 SkFontArguments paletteArguments;
97 paletteArguments.setPalette(fPalette);
98
99 fTypefaceDefault = MakeTypefaceFromResource(kColrCpalTestFontPath, SkFontArguments());
100 fTypefaceCloned =
101 fTypefaceDefault ? fTypefaceDefault->makeClone(paletteArguments) : nullptr;
102
103 fTypefaceFromStream = MakeTypefaceFromResource(kColrCpalTestFontPath, paletteArguments);
104 }
105
getName() const106 SkString getName() const override {
107 SkString gm_name = SkStringPrintf("font_palette_%s", fName.c_str());
108 return gm_name;
109 }
110
getISize()111 SkISize getISize() override { return SkISize::Make(1000, 400); }
112
onDraw(SkCanvas * canvas,SkString * errorMsg)113 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
114 canvas->drawColor(SK_ColorWHITE);
115 SkPaint paint;
116
117 canvas->translate(10, 20);
118
119 if (!fTypefaceCloned || !fTypefaceFromStream) {
120 *errorMsg = "Did not recognize COLR v1 test font format.";
121 return DrawResult::kSkip;
122 }
123
124 SkFontMetrics metrics;
125 SkScalar y = 0;
126 SkScalar textSize = 200;
127 for (auto& typeface : {fTypefaceFromStream, fTypefaceCloned}) {
128 SkFont defaultFont(fTypefaceDefault);
129 SkFont paletteFont(typeface);
130 defaultFont.setSize(textSize);
131 paletteFont.setSize(textSize);
132
133 defaultFont.getMetrics(&metrics);
134 y += -metrics.fAscent;
135 // Set a recognizable foreground color which is not to be overriden.
136 paint.setColor(SK_ColorGRAY);
137 // Draw the default palette on the left, for COLRv0 and COLRv1.
138 canvas->drawSimpleText(
139 ColrV1TestDefinitions::color_circles_palette,
140 std::size(ColrV1TestDefinitions::color_circles_palette) * sizeof(uint32_t),
141 SkTextEncoding::kUTF32,
142 0,
143 y,
144 defaultFont,
145 paint);
146 // Draw the overriden palette on the right.
147 canvas->drawSimpleText(
148 ColrV1TestDefinitions::color_circles_palette,
149 std::size(ColrV1TestDefinitions::color_circles_palette) * sizeof(uint32_t),
150 SkTextEncoding::kUTF32,
151 440,
152 y,
153 paletteFont,
154 paint);
155 y += metrics.fDescent + metrics.fLeading;
156 }
157 return DrawResult::kOk;
158 }
159
160 private:
161 using INHERITED = GM;
162 SkString fName;
163 SkFontArguments::Palette fPalette;
164 };
165
166 DEF_GM(return new FontPaletteGM("default", SkFontArguments::Palette()));
167 DEF_GM(return new FontPaletteGM("light", kLightPaletteOverride));
168 DEF_GM(return new FontPaletteGM("dark", kDarkPaletteOverride));
169 DEF_GM(return new FontPaletteGM("one", kOnePaletteOverride));
170 DEF_GM(return new FontPaletteGM("all", kAllPaletteOverride));
171
172 } // namespace skiagm
173