/* * Copyright 2015 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/SkFontArguments.h" #include "include/core/SkFontMgr.h" #include "include/core/SkFontTypes.h" #include "include/core/SkPaint.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/core/SkScalar.h" #include "include/core/SkSize.h" #include "include/core/SkStream.h" #include "include/core/SkString.h" #include "include/core/SkTypeface.h" #include "include/core/SkTypes.h" #include "tools/Resources.h" #include "tools/SkMetaData.h" #include "tools/ToolUtils.h" #include "tools/fonts/FontToolUtils.h" #include #include #include namespace skiagm { class FontScalerDistortableGM : public GM { public: FontScalerDistortableGM() { this->setBGColor(0xFFFFFFFF); } private: SkString getName() const override { return SkString("fontscalerdistortable"); } SkISize getISize() override { return SkISize::Make(550, 700); } bool fDirty = true; bool fOverride = false; ToolUtils::VariationSliders fVariationSliders; bool onGetControls(SkMetaData* controls) override { controls->setBool("Override", fOverride); return fVariationSliders.writeControls(controls); } void onSetControls(const SkMetaData& controls) override { bool oldOverride = fOverride; controls.findBool("Override", &fOverride); if (fOverride != oldOverride) { fDirty = true; } return fVariationSliders.readControls(controls, &fDirty); } struct Info { sk_sp distortable; SkFourByteTag axisTag; SkScalar axisMin; SkScalar axisMax; } fInfo; void onOnceBeforeDraw() override { constexpr SkFourByteTag wght = SkSetFourByteTag('w','g','h','t'); //constexpr SkFourByteTag wdth = SkSetFourByteTag('w','d','t','h'); fInfo = { ToolUtils::CreateTypefaceFromResource("fonts/Distortable.ttf"), wght, 0.5f, 2.0f //SkTypeface::MakeFromFile("/Library/Fonts/Skia.ttf"), wght, 0.48f, 3.2f //ToolUtils::CreateTestTypeface("Skia", SkFontStyle()), wdth, 0.62f, 1.3f //SkTypeface::MakeFromFile("/System/Library/Fonts/SFNS.ttf"), wght, 100.0f, 900.0f //ToolUtils::CreateTestTypeface(".SF NS", SkFontStyle()), wght, 100.0f, 900.0f }; if (!fInfo.distortable) { fInfo.distortable = ToolUtils::DefaultPortableTypeface(); } SkASSERT(fInfo.distortable); fVariationSliders = ToolUtils::VariationSliders(fInfo.distortable.get()); } inline static constexpr int rows = 2; inline static constexpr int cols = 5; sk_sp typeface[rows][cols]; void updateTypefaces() { sk_sp fontMgr = ToolUtils::TestFontMgr(); std::unique_ptr distortableStream( fInfo.distortable ? fInfo.distortable->openStream(nullptr) : nullptr); for (int row = 0; row < rows; ++row) { for (int col = 0; col < cols; ++col) { using Coordinate = SkFontArguments::VariationPosition::Coordinate; SkFontArguments::VariationPosition position; Coordinate coordinates[2]; if (fOverride) { SkSpan user_coordinates = fVariationSliders.getCoordinates(); position = {user_coordinates.data(), static_cast(user_coordinates.size())}; } else { const int coordinateCount = 2; SkScalar styleValue = SkScalarInterp(fInfo.axisMin, fInfo.axisMax, SkScalar(row*cols + col) / (rows*cols)); coordinates[0] = {fInfo.axisTag, styleValue}; coordinates[1] = {fInfo.axisTag, styleValue}; position = {coordinates, static_cast(coordinateCount)}; } typeface[row][col] = [&]() -> sk_sp { if (row == 0 && fInfo.distortable) { return fInfo.distortable->makeClone( SkFontArguments().setVariationDesignPosition(position)); } if (distortableStream) { return fontMgr->makeFromStream(distortableStream->duplicate(), SkFontArguments().setVariationDesignPosition(position)); } return nullptr; }(); } } fDirty = false; } DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { if (fDirty) { this->updateTypefaces(); } SkPaint paint; paint.setAntiAlias(true); SkFont font; font.setEdging(SkFont::Edging::kSubpixelAntiAlias); const char* text = "abc"; const size_t textLen = strlen(text); for (int row = 0; row < rows; ++row) { for (int col = 0; col < cols; ++col) { SkScalar x = SkIntToScalar(10); SkScalar y = SkIntToScalar(20); font.setTypeface(typeface[row][col] ? typeface[row][col] : ToolUtils::DefaultPortableTypeface()); SkAutoCanvasRestore acr(canvas, true); canvas->translate(SkIntToScalar(30 + col * 100), SkIntToScalar(20)); canvas->rotate(SkIntToScalar(col * 5), x, y * 10); { SkPaint p; p.setAntiAlias(true); SkRect r; r.setLTRB(x - 3, 15, x - 1, 280); canvas->drawRect(r, p); } for (int ps = 6; ps <= 22; ps++) { font.setSize(SkIntToScalar(ps)); canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint); y += font.getMetrics(nullptr); } } canvas->translate(0, SkIntToScalar(360)); font.setSubpixel(true); font.setLinearMetrics(true); font.setBaselineSnap(false); } return DrawResult::kOk; } }; ////////////////////////////////////////////////////////////////////////////// DEF_GM( return new FontScalerDistortableGM; ) } // namespace skiagm