diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp index 5194e1f7b7..a7cbd97d26 100644 --- a/src/ports/SkFontMgr_android.cpp +++ b/src/ports/SkFontMgr_android.cpp @@ -98,6 +98,22 @@ public: return skstd::make_unique(this->makeStream(), fIndex, fAxes.begin(), fAxes.count()); } + sk_sp onMakeClone(const SkFontArguments& args) const override { + std::unique_ptr data = this->cloneFontData(args); + if (!data) { + return nullptr; + } + return sk_make_sp(fPathName, + fFile, + fIndex, + data->getAxis(), + data->getAxisCount(), + this->fontStyle(), + this->isFixedPitch(), + fFamilyName, + fLang, + fVariantStyle); + } const SkString fPathName; int fIndex; diff --git a/tests/FontMgrAndroidParserTest.cpp b/tests/FontMgrAndroidParserTest.cpp index 6af6637ca1..432d69ec75 100644 --- a/tests/FontMgrAndroidParserTest.cpp +++ b/tests/FontMgrAndroidParserTest.cpp @@ -6,6 +6,7 @@ */ #include "Resources.h" +#include "SkCanvas.h" #include "SkCommandLineFlags.h" #include "SkFixed.h" #include "SkFontMgr_android.h" @@ -245,3 +246,98 @@ DEF_TEST(FontMgrAndroidLegacyMakeTypeface, reporter) { sk_sp t(fm->legacyMakeTypeface("non-existent-font", SkFontStyle())); REPORTER_ASSERT(reporter, nullptr == t); } + +static bool bitmap_compare(const SkBitmap& ref, const SkBitmap& test) { + for (int y = 0; y < test.height(); ++y) { + for (int x = 0; x < test.width(); ++x) { + SkColor testColor = test.getColor(x, y); + SkColor refColor = ref.getColor(x, y); + if (refColor != testColor) { + return false; + } + } + } + return true; +} + +DEF_TEST(FontMgrAndroidSystemVariableTypeface, reporter) { + constexpr char fontsXmlFilename[] = "fonts/fonts.xml"; + SkString basePath = GetResourcePath("fonts/"); + SkString fontsXml = GetResourcePath(fontsXmlFilename); + + if (!sk_exists(fontsXml.c_str())) { + ERRORF(reporter, "file missing: %s\n", fontsXmlFilename); + return; + } + + SkFontMgr_Android_CustomFonts custom; + custom.fSystemFontUse = SkFontMgr_Android_CustomFonts::kOnlyCustom; + custom.fBasePath = basePath.c_str(); + custom.fFontsXml = fontsXml.c_str(); + custom.fFallbackFontsXml = nullptr; + custom.fIsolated = false; + + sk_sp fontMgr(SkFontMgr_New_Android(&custom)); + // "sans-serif" in "fonts/fonts.xml" is "fonts/Distortable.ttf" + sk_sp typeface(fontMgr->legacyMakeTypeface("sans-serif", SkFontStyle())); + + SkBitmap bitmapStream; + bitmapStream.allocN32Pixels(64, 64); + SkCanvas canvasStream(bitmapStream); + canvasStream.drawColor(SK_ColorWHITE); + + SkBitmap bitmapClone; + bitmapClone.allocN32Pixels(64, 64); + SkCanvas canvasClone(bitmapClone); + canvasStream.drawColor(SK_ColorWHITE); + + SkPaint paintStream; + paintStream.setColor(SK_ColorGRAY); + paintStream.setTextSize(SkIntToScalar(20)); + paintStream.setAntiAlias(true); + paintStream.setLCDRenderText(true); + + SkPaint paintClone; + paintClone.setColor(SK_ColorGRAY); + paintClone.setTextSize(SkIntToScalar(20)); + paintClone.setAntiAlias(true); + paintClone.setLCDRenderText(true); + + std::unique_ptr distortableStream( + GetResourceAsStream("fonts/Distortable.ttf")); + if (!distortableStream) { + return; + } + + const char* text = "abc"; + const size_t textLen = strlen(text); + SkPoint point = SkPoint::Make(20.0f, 20.0f); + SkFourByteTag tag = SkSetFourByteTag('w', 'g', 'h', 't'); + + for (int i = 0; i < 10; ++i) { + SkScalar styleValue = + SkDoubleToScalar(0.5 + i * ((2.0 - 0.5) / 10)); + SkFontArguments::VariationPosition::Coordinate + coordinates[] = {{tag, styleValue}}; + SkFontArguments::VariationPosition + position = {coordinates, SK_ARRAY_COUNT(coordinates)}; + + paintStream.setTypeface(sk_sp( + fontMgr->makeFromStream(distortableStream->duplicate(), + SkFontArguments().setVariationDesignPosition(position)))); + + paintClone.setTypeface(sk_sp( + typeface->makeClone(SkFontArguments().setVariationDesignPosition(position)))); + + canvasStream.drawColor(SK_ColorWHITE); + canvasStream.drawText(text, textLen, point.fX, point.fY, paintStream); + + canvasClone.drawColor(SK_ColorWHITE); + canvasClone.drawText(text, textLen, point.fX, point.fY, paintClone); + + bool success = bitmap_compare(bitmapStream, bitmapClone); + REPORTER_ASSERT(reporter, success); + } +} + +