Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 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" |
Kevin Lubick | be579dc | 2023-10-05 11:11:20 -0400 | [diff] [blame] | 18 | #include "include/core/SkStream.h" |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 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" |
Kevin Lubick | 1e97119 | 2023-11-10 16:14:44 -0500 | [diff] [blame] | 24 | #include "tools/fonts/FontToolUtils.h" |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 25 | |
Dominik Röttsches | 0443e02 | 2024-01-10 19:49:19 +0200 | [diff] [blame] | 26 | #if defined(SK_TYPEFACE_FACTORY_FONTATIONS) |
| 27 | #include "include/ports/SkTypeface_fontations.h" |
| 28 | #endif |
| 29 | |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 30 | #include <string.h> |
| 31 | |
| 32 | namespace skiagm { |
| 33 | |
Dominik Röttsches | 131a828 | 2022-08-10 18:42:54 +0300 | [diff] [blame] | 34 | // Copied from https://github.com/googlefonts/color-fonts#colrv1-test-font glyph descriptions markdown file. |
| 35 | namespace ColrV1TestDefinitions { |
| 36 | const uint32_t color_circles_palette[] = {0xf0e00, 0xf0e01}; |
| 37 | }; |
| 38 | |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 39 | namespace { |
Dominik Röttsches | 131a828 | 2022-08-10 18:42:54 +0300 | [diff] [blame] | 40 | const char kColrCpalTestFontPath[] = "fonts/test_glyphs-glyf_colr_1.ttf"; |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 41 | |
| 42 | constexpr SkFontArguments::Palette::Override kColorOverridesAll[] = { |
| 43 | // A gradient of dark to light purple for the circle palette test glyph. |
Ben Wagner | 0ec715d | 2022-02-17 23:08:13 -0500 | [diff] [blame] | 44 | // Randomly ordered with `shuf`. |
| 45 | // Add a repeat (later overrides override earlier overrides). |
| 46 | // Add three out of bounds entries (font has 12 palette entries). |
| 47 | { 6, 0xffffff00}, |
| 48 | { 2, 0xff76078f}, |
| 49 | { 4, 0xffb404c4}, |
| 50 | { 1, 0xff510970}, |
| 51 | { 6, 0xfffa00ff}, |
| 52 | { 8, 0xff888888}, |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 53 | {10, 0xff888888}, |
Ben Wagner | 0ec715d | 2022-02-17 23:08:13 -0500 | [diff] [blame] | 54 | { 9, 0xff888888}, |
| 55 | { 7, 0xff888888}, |
| 56 | {11, 0xff888888}, |
| 57 | { 0, 0xff310b55}, |
| 58 | { 3, 0xff9606aa}, |
| 59 | { 5, 0xffd802e2}, |
| 60 | {13, 0xff00ffff}, |
| 61 | {12, 0xff00ffff}, |
Dominik Röttsches | 7e6e257 | 2023-12-21 12:42:51 +0200 | [diff] [blame] | 62 | {static_cast<uint16_t>(-1), 0xff00ff00}, |
Ben Wagner | 0ec715d | 2022-02-17 23:08:13 -0500 | [diff] [blame] | 63 | }; |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 64 | |
| 65 | constexpr SkFontArguments::Palette::Override kColorOverridesOne[] = { |
| 66 | {2, 0xff02dfe2}, |
| 67 | }; |
| 68 | |
| 69 | constexpr SkFontArguments::Palette kLightPaletteOverride{2, nullptr, 0}; |
| 70 | constexpr SkFontArguments::Palette kDarkPaletteOverride{1, nullptr, 0}; |
| 71 | constexpr SkFontArguments::Palette kOnePaletteOverride{ |
Herb Derby | c37b386 | 2022-06-21 09:49:17 -0400 | [diff] [blame] | 72 | 0, kColorOverridesOne, std::size(kColorOverridesOne)}; |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 73 | constexpr SkFontArguments::Palette kAllPaletteOverride{ |
Herb Derby | c37b386 | 2022-06-21 09:49:17 -0400 | [diff] [blame] | 74 | 0, kColorOverridesAll, std::size(kColorOverridesAll)}; |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 75 | |
Dominik Röttsches | 0443e02 | 2024-01-10 19:49:19 +0200 | [diff] [blame] | 76 | |
| 77 | |
| 78 | enum TypefaceBackend { UseDefault, UseFontations }; |
| 79 | |
| 80 | // TODO(b/318667611): Move the explicit instantation to font manager for Fontations. |
| 81 | #if defined(SK_TYPEFACE_FACTORY_FONTATIONS) |
| 82 | constexpr auto kBackend = TypefaceBackend::UseFontations; |
| 83 | #else |
| 84 | constexpr auto kBackend = TypefaceBackend::UseDefault; |
| 85 | #endif |
| 86 | |
| 87 | template <TypefaceBackend variant> |
| 88 | sk_sp<SkTypeface> MakeTypefaceFromResource(const char* resource, const SkFontArguments& args); |
| 89 | |
| 90 | #if defined(SK_TYPEFACE_FACTORY_FONTATIONS) |
| 91 | template <> |
| 92 | sk_sp<SkTypeface> MakeTypefaceFromResource<UseFontations>(const char* resource, |
| 93 | const SkFontArguments& args) { |
| 94 | std::unique_ptr<SkStreamAsset> resourceStream(GetResourceAsStream(resource, false)); |
| 95 | return SkTypeface_Make_Fontations(std::move(resourceStream), args); |
| 96 | } |
| 97 | #else |
| 98 | template <> |
| 99 | sk_sp<SkTypeface> MakeTypefaceFromResource<UseDefault>(const char* resource, |
| 100 | const SkFontArguments& args) { |
| 101 | return ToolUtils::TestFontMgr()->makeFromStream(GetResourceAsStream(resource), args); |
| 102 | } |
| 103 | #endif |
| 104 | |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 105 | } // namespace |
| 106 | |
| 107 | class FontPaletteGM : public GM { |
| 108 | public: |
| 109 | FontPaletteGM(const char* test_name, |
| 110 | const SkFontArguments::Palette& paletteOverride) |
| 111 | : fName(test_name), fPalette(paletteOverride) {} |
| 112 | |
| 113 | protected: |
| 114 | sk_sp<SkTypeface> fTypefaceDefault; |
| 115 | sk_sp<SkTypeface> fTypefaceFromStream; |
| 116 | sk_sp<SkTypeface> fTypefaceCloned; |
| 117 | |
| 118 | void onOnceBeforeDraw() override { |
| 119 | SkFontArguments paletteArguments; |
| 120 | paletteArguments.setPalette(fPalette); |
| 121 | |
Dominik Röttsches | 0443e02 | 2024-01-10 19:49:19 +0200 | [diff] [blame] | 122 | fTypefaceDefault = |
| 123 | MakeTypefaceFromResource<kBackend>(kColrCpalTestFontPath, SkFontArguments()); |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 124 | fTypefaceCloned = |
| 125 | fTypefaceDefault ? fTypefaceDefault->makeClone(paletteArguments) : nullptr; |
| 126 | |
Dominik Röttsches | 0443e02 | 2024-01-10 19:49:19 +0200 | [diff] [blame] | 127 | fTypefaceFromStream = |
| 128 | MakeTypefaceFromResource<kBackend>(kColrCpalTestFontPath, paletteArguments); |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 129 | } |
| 130 | |
Leandro Lovisolo | 24fa211 | 2023-08-15 19:05:17 +0000 | [diff] [blame] | 131 | SkString getName() const override { |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 132 | SkString gm_name = SkStringPrintf("font_palette_%s", fName.c_str()); |
| 133 | return gm_name; |
| 134 | } |
| 135 | |
Leandro Lovisolo | 8f02388 | 2023-08-15 21:13:52 +0000 | [diff] [blame] | 136 | SkISize getISize() override { return SkISize::Make(1000, 400); } |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 137 | |
| 138 | DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { |
| 139 | canvas->drawColor(SK_ColorWHITE); |
| 140 | SkPaint paint; |
| 141 | |
| 142 | canvas->translate(10, 20); |
| 143 | |
| 144 | if (!fTypefaceCloned || !fTypefaceFromStream) { |
| 145 | *errorMsg = "Did not recognize COLR v1 test font format."; |
| 146 | return DrawResult::kSkip; |
| 147 | } |
| 148 | |
| 149 | SkFontMetrics metrics; |
| 150 | SkScalar y = 0; |
| 151 | SkScalar textSize = 200; |
| 152 | for (auto& typeface : { fTypefaceFromStream, fTypefaceCloned} ) { |
| 153 | SkFont defaultFont(fTypefaceDefault); |
| 154 | SkFont paletteFont(typeface); |
| 155 | defaultFont.setSize(textSize); |
| 156 | paletteFont.setSize(textSize); |
| 157 | |
| 158 | defaultFont.getMetrics(&metrics); |
| 159 | y += -metrics.fAscent; |
| 160 | // Set a recognizable foreground color which is not to be overriden. |
| 161 | paint.setColor(SK_ColorGRAY); |
| 162 | // Draw the default palette on the left, for COLRv0 and COLRv1. |
Dominik Röttsches | 131a828 | 2022-08-10 18:42:54 +0300 | [diff] [blame] | 163 | canvas->drawSimpleText( |
| 164 | ColrV1TestDefinitions::color_circles_palette, |
| 165 | std::size(ColrV1TestDefinitions::color_circles_palette) * sizeof(uint32_t), |
| 166 | SkTextEncoding::kUTF32, |
| 167 | 0, |
| 168 | y, |
| 169 | defaultFont, |
| 170 | paint); |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 171 | // Draw the overriden palette on the right. |
Dominik Röttsches | 131a828 | 2022-08-10 18:42:54 +0300 | [diff] [blame] | 172 | canvas->drawSimpleText( |
| 173 | ColrV1TestDefinitions::color_circles_palette, |
| 174 | std::size(ColrV1TestDefinitions::color_circles_palette) * sizeof(uint32_t), |
| 175 | SkTextEncoding::kUTF32, |
| 176 | 440, |
| 177 | y, |
| 178 | paletteFont, |
| 179 | paint); |
Dominik Röttsches | 01be94d | 2022-02-17 12:37:49 +0200 | [diff] [blame] | 180 | y += metrics.fDescent + metrics.fLeading; |
| 181 | } |
| 182 | return DrawResult::kOk; |
| 183 | } |
| 184 | |
| 185 | private: |
| 186 | using INHERITED = GM; |
| 187 | SkString fName; |
| 188 | SkFontArguments::Palette fPalette; |
| 189 | }; |
| 190 | |
| 191 | DEF_GM(return new FontPaletteGM("default", SkFontArguments::Palette())); |
| 192 | DEF_GM(return new FontPaletteGM("light", kLightPaletteOverride)); |
| 193 | DEF_GM(return new FontPaletteGM("dark", kDarkPaletteOverride)); |
| 194 | DEF_GM(return new FontPaletteGM("one", kOnePaletteOverride)); |
| 195 | DEF_GM(return new FontPaletteGM("all", kAllPaletteOverride)); |
| 196 | |
| 197 | } // namespace skiagm |