skia2/gm/palette.cpp
Dominik Röttsches 01be94d7f1 Support font palette overrides through SkFontArguments
Co-authored with Ben Wagner, bungeman@google.com.

Similar to how we allow configuration of variable font configurations,
provide additional SkFontArguments to select a base palette and a set
of potentially sparse color overrides.

This is required for implementing CSS font-palette.

Modify the more_samples-glyf_colr_1.ttf to have two additional palettes,
and two additional test glyphs, one that draws with COLRv0 logic, one
that draws with COLRv1 logic and has a foreground palette index dot
in the middle. See [1] & [2] for the additions to the test font.

Add a GM which tests this on the SkFontMgr_custom using makeClone() and
makeFromStreamArgs(). The test displays the two glyphs in default
palette on the left, then with palette overrides (as in the title of the
test) on the right. The first row uses a typeface created with
makeFromStreamArgs(), the second uses one created with makeClone().

[1] https://github.com/googlefonts/color-fonts/pull/91
[2] https://github.com/googlefonts/color-fonts/pull/92

Bug: skia:12730, chromium:1170794
Cq-Include-Trybots: luci.skia.skia.primary:Test-Android-Clang-GalaxyS20-GPU-MaliG77-arm64-Release-All-Android_NativeFonts,Test-Debian10-Clang-GCE-CPU-AVX2-x86_64-Debug-All-NativeFonts
Change-Id: Ia1334f069240edc78fd4791969914e8a6f4fbaf9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/479616
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
2022-02-17 13:19:53 +00:00

149 lines
5.0 KiB
C++

/*
* Copyright 2022 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/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
#include <string.h>
namespace skiagm {
namespace {
const char kColrCpalTestFontPath[] = "fonts/more_samples-glyf_colr_1.ttf";
constexpr SkFontArguments::Palette::Override kColorOverridesAll[] = {
// A gradient of dark to light purple for the circle palette test glyph.
{0, 0xff310b55},
{1, 0xff510970},
{2, 0xff76078f},
{3, 0xff9606aa},
{4, 0xffb404c4},
{5, 0xffd802e2},
{6, 0xfffa00ff},
{7, 0xff888888},
{8, 0xff888888},
{9, 0xff888888},
{10, 0xff888888},
{11, 0xff888888}};
constexpr SkFontArguments::Palette::Override kColorOverridesOne[] = {
{2, 0xff02dfe2},
};
constexpr SkFontArguments::Palette kLightPaletteOverride{2, nullptr, 0};
constexpr SkFontArguments::Palette kDarkPaletteOverride{1, nullptr, 0};
constexpr SkFontArguments::Palette kOnePaletteOverride{
0, kColorOverridesOne, SK_ARRAY_COUNT(kColorOverridesOne)};
constexpr SkFontArguments::Palette kAllPaletteOverride{
0, kColorOverridesAll, SK_ARRAY_COUNT(kColorOverridesAll)};
constexpr uint16_t kTestGlyphs[] = {56, 57};
} // namespace
class FontPaletteGM : public GM {
public:
FontPaletteGM(const char* test_name,
const SkFontArguments::Palette& paletteOverride)
: fName(test_name), fPalette(paletteOverride) {}
protected:
sk_sp<SkTypeface> fTypefaceDefault;
sk_sp<SkTypeface> fTypefaceFromStream;
sk_sp<SkTypeface> fTypefaceCloned;
void onOnceBeforeDraw() override {
SkFontArguments paletteArguments;
paletteArguments.setPalette(fPalette);
fTypefaceDefault = MakeResourceAsTypeface(kColrCpalTestFontPath);
fTypefaceCloned =
fTypefaceDefault ? fTypefaceDefault->makeClone(paletteArguments) : nullptr;
fTypefaceFromStream = SkFontMgr::RefDefault()->makeFromStream(
GetResourceAsStream(kColrCpalTestFontPath), paletteArguments);
}
SkString onShortName() override {
SkString gm_name = SkStringPrintf("font_palette_%s", fName.c_str());
return gm_name;
}
SkISize onISize() override { return SkISize::Make(1000, 400); }
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
canvas->drawColor(SK_ColorWHITE);
SkPaint paint;
canvas->translate(10, 20);
if (!fTypefaceCloned || !fTypefaceFromStream) {
*errorMsg = "Did not recognize COLR v1 test font format.";
return DrawResult::kSkip;
}
SkFontMetrics metrics;
SkScalar y = 0;
SkScalar textSize = 200;
for (auto& typeface : { fTypefaceFromStream, fTypefaceCloned} ) {
SkFont defaultFont(fTypefaceDefault);
SkFont paletteFont(typeface);
defaultFont.setSize(textSize);
paletteFont.setSize(textSize);
defaultFont.getMetrics(&metrics);
y += -metrics.fAscent;
// Set a recognizable foreground color which is not to be overriden.
paint.setColor(SK_ColorGRAY);
// Draw the default palette on the left, for COLRv0 and COLRv1.
canvas->drawSimpleText(kTestGlyphs,
SK_ARRAY_COUNT(kTestGlyphs) * sizeof(uint16_t),
SkTextEncoding::kGlyphID,
0,
y,
defaultFont,
paint);
// Draw the overriden palette on the right.
canvas->drawSimpleText(kTestGlyphs,
SK_ARRAY_COUNT(kTestGlyphs) * sizeof(uint16_t),
SkTextEncoding::kGlyphID,
440,
y,
paletteFont,
paint);
y += metrics.fDescent + metrics.fLeading;
}
return DrawResult::kOk;
}
private:
using INHERITED = GM;
SkString fName;
SkFontArguments::Palette fPalette;
};
DEF_GM(return new FontPaletteGM("default", SkFontArguments::Palette()));
DEF_GM(return new FontPaletteGM("light", kLightPaletteOverride));
DEF_GM(return new FontPaletteGM("dark", kDarkPaletteOverride));
DEF_GM(return new FontPaletteGM("one", kOnePaletteOverride));
DEF_GM(return new FontPaletteGM("all", kAllPaletteOverride));
} // namespace skiagm