| /* |
| * Copyright 2023 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gm/gm.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkFont.h" |
| #include "include/core/SkRefCnt.h" |
| #include "include/core/SkStream.h" |
| #include "include/core/SkString.h" |
| #include "include/core/SkTypeface.h" |
| #include "include/ports/SkTypeface_fontations.h" |
| #include "tools/Resources.h" |
| |
| |
| namespace skiagm { |
| |
| namespace { |
| const SkScalar kTextSizes[] = {12, 18, 30, 120}; |
| const char kReportFontName[] = "fonts/Roboto-Regular.ttf"; |
| const SkScalar kDumpFontSize = 20.0f; |
| |
| // TODO(drott): Test these dumps is in a unit test instead of dumping them to GM surface. |
| void dumpToCanvas(SkCanvas* canvas, SkString text, sk_sp<SkTypeface> reportTypeface) { |
| canvas->drawSimpleText(text.c_str(), |
| text.size() - 1, |
| SkTextEncoding::kUTF8, |
| 0, |
| 0, |
| SkFont(reportTypeface, kDumpFontSize), |
| SkPaint()); |
| } |
| |
| void dumpLocalizedStrings(SkCanvas* canvas, |
| sk_sp<SkTypeface> typeface, |
| sk_sp<SkTypeface> reportTypeface) { |
| auto family_names = typeface->createFamilyNameIterator(); |
| SkTypeface::LocalizedString famName; |
| SkString localizedName; |
| while (family_names->next(&famName)) { |
| localizedName.printf( |
| "Name: %s Language: %s\n", famName.fString.c_str(), famName.fLanguage.c_str()); |
| dumpToCanvas(canvas, localizedName, reportTypeface); |
| canvas->translate(0, kDumpFontSize * 1.2); |
| } |
| family_names->unref(); |
| } |
| |
| void dumpGlyphCount(SkCanvas* canvas, |
| sk_sp<SkTypeface> typeface, |
| sk_sp<SkTypeface> reportTypeface) { |
| SkString glyphCount; |
| glyphCount.printf("Num glyphs: %d\n", typeface->countGlyphs()); |
| dumpToCanvas(canvas, glyphCount, reportTypeface); |
| } |
| |
| void dumpFamilyAndPostscriptName(SkCanvas* canvas, |
| sk_sp<SkTypeface> typeface, |
| sk_sp<SkTypeface> reportTypeface) { |
| SkString name; |
| typeface->getFamilyName(&name); |
| SkString nameDump; |
| nameDump.printf("Family name: %s\n", name.c_str()); |
| dumpToCanvas(canvas, nameDump, reportTypeface); |
| |
| if (typeface->getPostScriptName(&name)) { |
| canvas->translate(0, kDumpFontSize * 1.2); |
| nameDump.printf("PS Name: %s\n", name.c_str()); |
| dumpToCanvas(canvas, nameDump, reportTypeface); |
| } else { |
| canvas->translate(0, kDumpFontSize * 1.2); |
| nameDump.printf("No Postscript name."); |
| dumpToCanvas(canvas, nameDump, reportTypeface); |
| } |
| } |
| |
| } // namespace |
| |
| class FontationsTypefaceGM : public GM { |
| public: |
| enum class TypefaceConstruction { |
| kMakeWithFontArguments, |
| kCloneWithFontArguments, |
| }; |
| FontationsTypefaceGM(const char* testName, |
| const char* testFontFilename, |
| std::initializer_list<SkFontArguments::VariationPosition::Coordinate> |
| specifiedVariations, |
| TypefaceConstruction construction = TypefaceConstruction::kMakeWithFontArguments) |
| : fTestName(testName) |
| , fTestFontFilename(testFontFilename) |
| , fConstruction(construction) { |
| this->setBGColor(SK_ColorWHITE); |
| fVariationPosition.coordinateCount = specifiedVariations.size(); |
| fCoordinates = std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>( |
| specifiedVariations.size()); |
| for (size_t i = 0; i < specifiedVariations.size(); ++i) { |
| fCoordinates[i] = std::data(specifiedVariations)[i]; |
| } |
| |
| fVariationPosition.coordinates = fCoordinates.get(); |
| } |
| |
| protected: |
| void onOnceBeforeDraw() override { |
| if (fConstruction == TypefaceConstruction::kMakeWithFontArguments) { |
| fTestTypeface = SkTypeface_Make_Fontations( |
| GetResourceAsStream(fTestFontFilename), |
| SkFontArguments().setVariationDesignPosition(fVariationPosition)); |
| } else { |
| fTestTypeface = SkTypeface_Make_Fontations(GetResourceAsStream(fTestFontFilename), |
| SkFontArguments()) |
| ->makeClone(SkFontArguments().setVariationDesignPosition( |
| fVariationPosition)); |
| } |
| fReportTypeface = |
| SkTypeface_Make_Fontations(GetResourceAsStream(kReportFontName), SkFontArguments()); |
| } |
| |
| SkString getName() const override { |
| return SkStringPrintf("typeface_fontations_%s", fTestName.c_str()); |
| } |
| |
| SkISize getISize() override { return SkISize::Make(400, 200); } |
| |
| DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { |
| SkPaint paint; |
| paint.setColor(SK_ColorBLACK); |
| |
| if (!fTestTypeface) { |
| *errorMsg = "Unable to initialize typeface."; |
| return DrawResult::kSkip; |
| } |
| |
| SkFont font(fTestTypeface); |
| const char32_t testText[] = U"abc"; |
| size_t testTextBytesize = std::char_traits<char32_t>::length(testText) * sizeof(char32_t); |
| SkScalar x = 100; |
| SkScalar y = 150; |
| |
| for (SkScalar textSize : kTextSizes) { |
| font.setSize(textSize); |
| y += font.getSpacing(); |
| |
| /* Draw origin marker as a green dot. */ |
| paint.setColor(SK_ColorGREEN); |
| canvas->drawRect(SkRect::MakeXYWH(x, y, 2, 2), paint); |
| paint.setColor(SK_ColorBLACK); |
| |
| canvas->drawSimpleText( |
| testText, testTextBytesize, SkTextEncoding::kUTF32, x, y, font, paint); |
| } |
| |
| canvas->translate(100, 470); |
| dumpGlyphCount(canvas, fTestTypeface, fReportTypeface); |
| canvas->translate(0, kDumpFontSize * 1.2); |
| dumpLocalizedStrings(canvas, fTestTypeface, fReportTypeface); |
| canvas->translate(0, kDumpFontSize * 1.2); |
| dumpFamilyAndPostscriptName(canvas, fTestTypeface, fReportTypeface); |
| |
| return DrawResult::kOk; |
| } |
| |
| private: |
| using INHERITED = GM; |
| |
| const SkString fTestName; |
| const char* fTestFontFilename; |
| sk_sp<SkTypeface> fTestTypeface; |
| sk_sp<SkTypeface> fReportTypeface; |
| SkFontArguments::VariationPosition fVariationPosition; |
| std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoordinates; |
| TypefaceConstruction fConstruction; |
| }; |
| |
| namespace { |
| SkFourByteTag constexpr operator"" _t(const char* tagName, size_t size) { |
| SkASSERT(size == 4); |
| return SkSetFourByteTag(tagName[0], tagName[1], tagName[2], tagName[3]); |
| } |
| } // namespace |
| DEF_GM(return new FontationsTypefaceGM("roboto", "fonts/Roboto-Regular.ttf", {});) |
| DEF_GM(return new FontationsTypefaceGM( |
| "distortable_light", |
| "fonts/Distortable.ttf", |
| {{"wght"_t, 0.5f}})) |
| DEF_GM(return new FontationsTypefaceGM( |
| "distortable_bold", |
| "fonts/Distortable.ttf", |
| {{"wght"_t, 2.0f}}, |
| FontationsTypefaceGM::TypefaceConstruction::kCloneWithFontArguments);) |
| |
| } // namespace skiagm |