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