skia2/gm/fontscalerdistortable.cpp
Dominik Röttsches f27608b656 Reland (2): Add ToolUtils helper for generating GM UI sliders for variable fonts
numAxes check changed from != 0 to < 0, G3 build fix by updating bazel
files for skdiff to include SkMetaData, now with file name typo fixed.

Use this new tool in the COLRv1 GM test for creating sliders in the GM
UI if the test font provides variable axes. Preparation for testing
variable COLRv1 fonts while developing this feature in FreeType.

Bug: chromium:1311241
Cq-Include-Trybots: luci.skia.skia.primary:Canary-G3
Change-Id: I2a24fed2c46e1edc85ca45080db5b54a5c15b6bf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/556936
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Dominik Röttsches <drott@google.com>
2022-07-08 15:30:26 +00:00

189 lines
6.4 KiB
C++

/*
* 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 <string.h>
#include <memory>
#include <utility>
namespace skiagm {
class FontScalerDistortableGM : public GM {
public:
FontScalerDistortableGM() {
this->setBGColor(0xFFFFFFFF);
}
private:
SkString onShortName() override {
return SkString("fontscalerdistortable");
}
SkISize onISize() 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<SkTypeface> 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 = {
MakeResourceAsTypeface("fonts/Distortable.ttf"), wght, 0.5f, 2.0f
//SkTypeface::MakeFromFile("/Library/Fonts/Skia.ttf"), wght, 0.48f, 3.2f
//SkTypeface::MakeFromName("Skia", SkFontStyle()), wdth, 0.62f, 1.3f
//SkTypeface::MakeFromFile("/System/Library/Fonts/SFNS.ttf"), wght, 100.0f, 900.0f
//SkTypeface::MakeFromName(".SF NS", SkFontStyle()), wght, 100.0f, 900.0f
};
if (fInfo.distortable) {
fVariationSliders = ToolUtils::VariationSliders(fInfo.distortable.get());
}
}
inline static constexpr int rows = 2;
inline static constexpr int cols = 5;
sk_sp<SkTypeface> typeface[rows][cols];
void updateTypefaces() {
sk_sp<SkFontMgr> fontMgr(SkFontMgr::RefDefault());
std::unique_ptr<SkStreamAsset> 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<const Coordinate> user_coordinates = fVariationSliders.getCoordinates();
position = {user_coordinates.data(), static_cast<int>(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<int>(coordinateCount)};
}
typeface[row][col] = [&]() -> sk_sp<SkTypeface> {
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] : nullptr);
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