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>
This commit is contained in:
Dominik Röttsches 2022-02-17 12:37:49 +02:00 committed by SkCQ
parent 76699a4495
commit 01be94d7f1
18 changed files with 404 additions and 80 deletions

View File

@ -34,6 +34,8 @@ Milestone 99
https://review.skia.org/481416
* Added a new variant of SkImageFilters::RuntimeShader that supports multiple child nodes.
https://review.skia.org/489536
* Add the ability to specifiy palette overrides in SkFontArguments. Implemented
for the FreeType-backed SkFontMgrs.
* * *

148
gm/palette.cpp Normal file
View File

@ -0,0 +1,148 @@
/*
* 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

View File

@ -279,6 +279,7 @@ gm_sources = [
"$_gm/overdrawcolorfilter.cpp",
"$_gm/overstroke.cpp",
"$_gm/p3.cpp",
"$_gm/palette.cpp",
"$_gm/particles.cpp",
"$_gm/patch.cpp",
"$_gm/path_stroke_with_zero_length.cpp",

View File

@ -8,6 +8,7 @@
#ifndef SkFontArguments_DEFINED
#define SkFontArguments_DEFINED
#include "include/core/SkColor.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"
@ -22,7 +23,27 @@ struct SkFontArguments {
int coordinateCount;
};
SkFontArguments() : fCollectionIndex(0), fVariationDesignPosition{nullptr, 0} {}
/** Specify a palette to use and overrides for palette entries.
*
* `overrides` is a list of pairs of palette entry index and color.
* The overriden palette entries will use the associated color.
* Override pairs with palette entry indices out of range will not be applied.
* Later override entries override earlier ones.
*/
struct Palette {
struct Override {
int index;
SkColor color;
};
int index;
const Override* overrides;
int overrideCount;
};
SkFontArguments()
: fCollectionIndex(0)
, fVariationDesignPosition{nullptr, 0}
, fPalette{0, nullptr, 0} {}
/** Specify the index of the desired font.
*
@ -54,9 +75,20 @@ struct SkFontArguments {
VariationPosition getVariationDesignPosition() const {
return fVariationDesignPosition;
}
SkFontArguments& setPalette(Palette palette) {
fPalette.index = palette.index;
fPalette.overrides = palette.overrides;
fPalette.overrideCount = palette.overrideCount;
return *this;
}
Palette getPalette() const { return fPalette; }
private:
int fCollectionIndex;
VariationPosition fVariationDesignPosition;
Palette fPalette;
};
#endif

View File

@ -22,6 +22,8 @@ enum {
kItalic = 0x13, // scalar (0 is Roman, 1 is fully Italic)
// Related to font data. Can also be used with a requested font.
kPaletteIndex = 0xF8, // int
kPaletteEntryOverrides = 0xF9, // int count, (int, u32)[count]
kFontVariation = 0xFA, // int count, (u32, scalar)[count]
// Related to font data.
@ -80,6 +82,15 @@ bool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) {
size_t index;
using CollectionIndexType = decltype(result->fCollectionIndex);
size_t paletteIndex;
using PaletteIndexType = decltype(result->fPaletteIndex);
size_t paletteEntryOverrideCount;
using PaletteEntryOverrideCountType = decltype(result->fPaletteEntryOverrideCount);
size_t paletteEntryOverrideIndex;
using PaletteEntryOverrideIndexType = decltype(result->fPaletteEntryOverrides[0].index);
SkScalar weight = SkFontStyle::kNormal_Weight;
SkScalar width = SkFontStyle::kNormal_Width;
SkScalar slant = 0;
@ -131,6 +142,32 @@ bool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) {
if (!SkTFitsIn<CollectionIndexType>(index)) { return false; }
result->fCollectionIndex = SkTo<CollectionIndexType>(index);
break;
case kPaletteIndex:
if (!stream->readPackedUInt(&paletteIndex)) { return false; }
if (!SkTFitsIn<PaletteIndexType>(paletteIndex)) { return false; }
result->fPaletteIndex = SkTo<PaletteIndexType>(paletteIndex);
break;
case kPaletteEntryOverrides:
if (!stream->readPackedUInt(&paletteEntryOverrideCount)) { return false; }
if (!SkTFitsIn<PaletteEntryOverrideCountType>(paletteEntryOverrideCount)) {
return false;
}
result->fPaletteEntryOverrideCount =
SkTo<PaletteEntryOverrideCountType>(paletteEntryOverrideCount);
result->fPaletteEntryOverrides.reset(paletteEntryOverrideCount);
for (size_t i = 0; i < paletteEntryOverrideCount; ++i) {
if (!stream->readPackedUInt(&paletteEntryOverrideIndex)) { return false; }
if (!SkTFitsIn<PaletteEntryOverrideIndexType>(paletteEntryOverrideIndex)) {
return false;
}
result->fPaletteEntryOverrides[i].index =
SkTo<PaletteEntryOverrideIndexType>(paletteEntryOverrideIndex);
if (!stream->readU32(&result->fPaletteEntryOverrides[i].color)) {
return false;
}
}
break;
default:
SkDEBUGFAIL("Unknown id used by a font descriptor");
return false;
@ -172,6 +209,9 @@ void SkFontDescriptor::serialize(SkWStream* stream) const {
if (fCollectionIndex) {
write_uint(stream, fCollectionIndex, kFontIndex);
}
if (fPaletteIndex) {
write_uint(stream, fPaletteIndex, kPaletteIndex);
}
if (fCoordinateCount) {
write_uint(stream, fCoordinateCount, kFontVariation);
for (int i = 0; i < fCoordinateCount; ++i) {
@ -179,6 +219,13 @@ void SkFontDescriptor::serialize(SkWStream* stream) const {
stream->writeScalar(fVariation[i].value);
}
}
if (fPaletteEntryOverrideCount) {
write_uint(stream, fPaletteEntryOverrideCount, kPaletteEntryOverrides);
for (int i = 0; i < fPaletteEntryOverrideCount; ++i) {
stream->writePackedUInt(fPaletteEntryOverrides[i].index);
stream->write32(fPaletteEntryOverrides[i].color);
}
}
stream->writePackedUInt(kSentinel);

View File

@ -18,31 +18,40 @@
class SkFontData {
public:
/** Makes a copy of the data in 'axis'. */
SkFontData(std::unique_ptr<SkStreamAsset> stream, int index, const SkFixed* axis, int axisCount)
: fStream(std::move(stream)), fIndex(index), fAxisCount(axisCount), fAxis(axisCount)
{
for (int i = 0; i < axisCount; ++i) {
fAxis[i] = axis[i];
}
}
SkFontData(std::unique_ptr<SkStreamAsset> stream, SkFontArguments args)
: fStream(std::move(stream)), fIndex(args.getCollectionIndex())
, fAxisCount(args.getVariationDesignPosition().coordinateCount)
, fAxis(args.getVariationDesignPosition().coordinateCount)
SkFontData(std::unique_ptr<SkStreamAsset> stream, int index, int paletteIndex,
const SkFixed* axis, int axisCount,
const SkFontArguments::Palette::Override* paletteOverrides, int paletteOverrideCount)
: fStream(std::move(stream))
, fIndex(index)
, fPaletteIndex(paletteIndex)
, fAxisCount(axisCount)
, fPaletteOverrideCount(paletteOverrideCount)
, fAxis(fAxisCount)
, fPaletteOverrides(fPaletteOverrideCount)
{
for (int i = 0; i < fAxisCount; ++i) {
fAxis[i] = SkFloatToFixed(args.getVariationDesignPosition().coordinates[i].value);
fAxis[i] = axis[i];
}
for (int i = 0; i < fPaletteOverrideCount; ++i) {
fPaletteOverrides[i] = paletteOverrides[i];
}
}
SkFontData(const SkFontData& that)
: fStream(that.fStream->duplicate())
, fIndex(that.fIndex)
, fPaletteIndex(that.fPaletteIndex)
, fAxisCount(that.fAxisCount)
, fPaletteOverrideCount(that.fPaletteOverrideCount)
, fAxis(fAxisCount)
, fPaletteOverrides(fPaletteOverrideCount)
{
for (int i = 0; i < fAxisCount; ++i) {
fAxis[i] = that.fAxis[i];
}
for (int i = 0; i < fPaletteOverrideCount; ++i) {
fPaletteOverrides[i] = that.fPaletteOverrides[i];
}
}
bool hasStream() const { return fStream != nullptr; }
std::unique_ptr<SkStreamAsset> detachStream() { return std::move(fStream); }
@ -51,12 +60,20 @@ public:
int getIndex() const { return fIndex; }
int getAxisCount() const { return fAxisCount; }
const SkFixed* getAxis() const { return fAxis.get(); }
int getPaletteIndex() const { return fPaletteIndex; }
int getPaletteOverrideCount() const { return fPaletteOverrideCount; }
const SkFontArguments::Palette::Override* getPaletteOverrides() const {
return fPaletteOverrides.get();
}
private:
std::unique_ptr<SkStreamAsset> fStream;
int fIndex;
int fPaletteIndex;
int fAxisCount;
int fPaletteOverrideCount;
SkAutoSTMalloc<4, SkFixed> fAxis;
SkAutoSTMalloc<4, SkFontArguments::Palette::Override> fPaletteOverrides;
};
class SkFontDescriptor : SkNoncopyable {
@ -81,18 +98,28 @@ public:
bool hasStream() const { return bool(fStream); }
std::unique_ptr<SkStreamAsset> dupStream() const { return fStream->duplicate(); }
int getCollectionIndex() const { return fCollectionIndex; }
int getPaletteIndex() const { return fPaletteIndex; }
int getVariationCoordinateCount() const { return fCoordinateCount; }
const SkFontArguments::VariationPosition::Coordinate* getVariation() const {
return fVariation.get();
}
int getPaletteEntryOverrideCount() const { return fPaletteEntryOverrideCount; }
const SkFontArguments::Palette::Override* getPaletteEntryOverrides() {
return fPaletteEntryOverrides.get();
}
std::unique_ptr<SkStreamAsset> detachStream() { return std::move(fStream); }
void setStream(std::unique_ptr<SkStreamAsset> stream) { fStream = std::move(stream); }
void setCollectionIndex(int collectionIndex) { fCollectionIndex = collectionIndex; }
void setPaleteIndex(int paletteIndex) { fPaletteIndex = paletteIndex; }
SkFontArguments::VariationPosition::Coordinate* setVariationCoordinates(int coordinateCount) {
fCoordinateCount = coordinateCount;
return fVariation.reset(coordinateCount);
}
SkFontArguments::Palette::Override* setPaletteEntryOverrides(int paletteEntryOverrideCount) {
fPaletteEntryOverrideCount = paletteEntryOverrideCount;
return fPaletteEntryOverrides.reset(paletteEntryOverrideCount);
}
static SkFontStyle::Width SkFontStyleWidthForWidthAxisValue(SkScalar width);
@ -107,6 +134,9 @@ private:
using Coordinates = SkAutoSTMalloc<4, SkFontArguments::VariationPosition::Coordinate>;
int fCoordinateCount = 0;
Coordinates fVariation;
int fPaletteIndex = 0;
int fPaletteEntryOverrideCount = 0;
SkAutoTMalloc<SkFontArguments::Palette::Override> fPaletteEntryOverrides;
};
#endif // SkFontDescriptor_DEFINED

View File

@ -222,6 +222,9 @@ sk_sp<SkTypeface> SkTypeface::MakeDeserialize(SkStream* stream) {
SkFontArguments args;
args.setCollectionIndex(desc.getCollectionIndex());
args.setVariationDesignPosition({desc.getVariation(), desc.getVariationCoordinateCount()});
args.setPalette({desc.getPaletteIndex(),
desc.getPaletteEntryOverrides(),
desc.getPaletteEntryOverrideCount()});
sk_sp<SkFontMgr> defaultFm = SkFontMgr::RefDefault();
sk_sp<SkTypeface> typeface = defaultFm->makeFromStream(desc.detachStream(), args);
if (typeface) {

View File

@ -188,6 +188,8 @@ public:
SkUniqueFTFace fFace;
FT_StreamRec fFTStream;
std::unique_ptr<SkStreamAsset> fSkStream;
FT_UShort fFTPaletteEntryCount = 0;
std::unique_ptr<SkColor[]> fSkPalette;
static std::unique_ptr<FaceRec> Make(const SkTypeface_FreeType* typeface);
~FaceRec();
@ -195,6 +197,7 @@ public:
private:
FaceRec(std::unique_ptr<SkStreamAsset> stream);
void setupAxes(const SkFontData& data);
void setupPalette(const SkFontData& data);
// Private to ref_ft_library and unref_ft_library
static int gFTCount;
@ -303,6 +306,44 @@ void SkTypeface_FreeType::FaceRec::setupAxes(const SkFontData& data) {
}
}
void SkTypeface_FreeType::FaceRec::setupPalette(const SkFontData& data) {
#ifdef FT_COLOR_H
FT_Palette_Data paletteData;
if (FT_Palette_Data_Get(fFace.get(), &paletteData)) {
return;
}
if (paletteData.num_palettes < data.getPaletteIndex() ) {
return;
}
FT_Color* ftPalette = nullptr;
if (FT_Palette_Select(fFace.get(), data.getPaletteIndex(), &ftPalette)) {
return;
}
fFTPaletteEntryCount = paletteData.num_palette_entries;
for (int i = 0; i < data.getPaletteOverrideCount(); ++i) {
const SkFontArguments::Palette::Override& paletteOverride = data.getPaletteOverrides()[i];
if (paletteOverride.index > fFTPaletteEntryCount) {
continue;
}
const SkColor& skColor = paletteOverride.color;
FT_Color& ftColor = ftPalette[i];
ftColor.blue = SkColorGetB(skColor);
ftColor.green = SkColorGetG(skColor);
ftColor.red = SkColorGetR(skColor);
ftColor.alpha = SkColorGetA(skColor);
}
fSkPalette.reset(new SkColor[fFTPaletteEntryCount]);
for (int i = 0; i < fFTPaletteEntryCount; ++i) {
fSkPalette[i] = SkColorSetARGB(ftPalette[i].alpha,
ftPalette[i].red,
ftPalette[i].green,
ftPalette[i].blue);
}
#endif
}
// Will return nullptr on failure
// Caller must lock f_t_mutex() before calling this function.
std::unique_ptr<SkTypeface_FreeType::FaceRec>
@ -340,6 +381,7 @@ SkTypeface_FreeType::FaceRec::Make(const SkTypeface_FreeType* typeface) {
SkASSERT(rec->fFace);
rec->setupAxes(*data);
rec->setupPalette(*data);
// FreeType will set the charmap to the "most unicode" cmap if it exists.
// If there are no unicode cmaps, the charmap is set to nullptr.
@ -663,9 +705,17 @@ std::unique_ptr<SkFontData> SkTypeface_FreeType::cloneFontData(const SkFontArgum
SkAutoSTMalloc<4, SkFixed> axisValues(axisCount);
Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(), axisValues, name,
currentAxisCount == axisCount ? currentPosition.get() : nullptr);
int ttcIndex;
std::unique_ptr<SkStreamAsset> stream = this->openStream(&ttcIndex);
return std::make_unique<SkFontData>(std::move(stream), ttcIndex, axisValues.get(), axisCount);
return std::make_unique<SkFontData>(std::move(stream),
ttcIndex,
args.getPalette().index,
axisValues.get(),
axisCount,
args.getPalette().overrides,
args.getPalette().overrideCount);
}
void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const {
@ -945,10 +995,6 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface_FreeType> ty
fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY());
fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
#ifdef FT_COLOR_H
FT_Palette_Select(fFaceRec->fFace.get(), 0, nullptr);
#endif
fFTSize = ftSize.release();
fFace = fFaceRec->fFace.get();
fDoLinearMetrics = linearMetrics;
@ -1333,7 +1379,9 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
SkFixedToScalar(glyph.getSubYFixed()));
bitmapMatrix = &subpixelBitmapMatrix;
}
generateGlyphImage(fFace, glyph, *bitmapMatrix);
SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
generateGlyphImage(fFace, palette, glyph, *bitmapMatrix);
}
sk_sp<SkDrawable> SkScalerContext_FreeType::generateDrawable(const SkGlyph& glyph) {
@ -1360,7 +1408,8 @@ sk_sp<SkDrawable> SkScalerContext_FreeType::generateDrawable(const SkGlyph& glyp
}
emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID());
return generateGlyphDrawable(fFace, glyph);
SkSpan<SkColor> palette(fFaceRec->fSkPalette.get(), fFaceRec->fFTPaletteEntryCount);
return generateGlyphDrawable(fFace, palette, glyph);
}
bool SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) {
@ -1822,6 +1871,16 @@ std::unique_ptr<SkFontData> SkTypeface_FreeType::makeFontData() const {
return this->onMakeFontData();
}
void SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(const SkFontData& fontData,
SkFontDescriptor* desc) {
desc->setPaleteIndex(fontData.getPaletteIndex());
int paletteOverrideCount = fontData.getPaletteOverrideCount();
auto overrides = desc->setPaletteEntryOverrides(paletteOverrideCount);
for (int i = 0; i < paletteOverrideCount; ++i) {
overrides[i] = fontData.getPaletteOverrides()[i];
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

View File

@ -1239,41 +1239,15 @@ bool colrv1_start_glyph_bounds(SkMatrix *ctm,
#ifdef FT_COLOR_H
bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
FT_Face face,
SkSpan<SkColor> palette,
const SkGlyph& glyph) {
SkPaint paint;
paint.setAntiAlias(true);
FT_Palette_Data palette_data;
FT_Error err = FT_Palette_Data_Get(face, &palette_data);
if (err) {
SK_TRACEFTR(err, "Could not get palette data from %s fontFace.",
face->family_name);
return false;
}
SkAutoTArray<SkColor> originalPalette;
FT_Color* ftPalette;
err = FT_Palette_Select(face, 0, &ftPalette);
if (err) {
SK_TRACEFTR(err, "Could not get palette colors from %s fontFace.",
face->family_name);
return false;
}
originalPalette.reset(palette_data.num_palette_entries);
for (int i = 0; i < palette_data.num_palette_entries; ++i) {
originalPalette[i] = SkColorSetARGB(ftPalette[i].alpha,
ftPalette[i].red,
ftPalette[i].green,
ftPalette[i].blue);
}
SkSpan<SkColor> paletteSpan(originalPalette.data(),
palette_data.num_palette_entries);
// Only attempt to draw a COLRv1 glyph if FreeType is new enough to have the COLRv1 support.
#ifdef TT_SUPPORT_COLRV1
VisitedSet visited_set;
if (colrv1_start_glyph(canvas, paletteSpan,
if (colrv1_start_glyph(canvas, palette,
fRec.fForegroundColor,
face, glyph.getGlyphID(),
FT_COLOR_INCLUDE_ROOT_TRANSFORM,
@ -1295,7 +1269,7 @@ bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
if (layerColorIndex == 0xFFFF) {
paint.setColor(fRec.fForegroundColor);
} else {
paint.setColor(paletteSpan[layerColorIndex]);
paint.setColor(palette[layerColorIndex]);
}
SkPath path;
if (this->generateFacePath(face, layerGlyphIndex, &path)) {
@ -1308,6 +1282,7 @@ bool SkScalerContext_FreeType_Base::drawColorGlyph(SkCanvas* canvas,
void SkScalerContext_FreeType_Base::generateGlyphImage(
FT_Face face,
SkSpan<SkColor> customPalette,
const SkGlyph& glyph,
const SkMatrix& bitmapTransform)
{
@ -1352,7 +1327,7 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(
SkFixedToScalar(glyph.getSubYFixed()));
}
bool haveLayers = this->drawColorGlyph(&canvas, face, glyph);
bool haveLayers = this->drawColorGlyph(&canvas, face, customPalette, glyph);
if (!haveLayers) {
SkDebugf("Could not get layers (neither v0, nor v1) from %s fontFace.",
@ -1788,13 +1763,13 @@ bool SkScalerContext_FreeType_Base::computeColrV1GlyphBoundingBox(FT_Face face,
#endif
}
sk_sp<SkDrawable> SkScalerContext_FreeType_Base::generateGlyphDrawable(FT_Face face,
const SkGlyph& glyph) {
sk_sp<SkDrawable> SkScalerContext_FreeType_Base::generateGlyphDrawable(
FT_Face face, SkSpan<SkColor> palette, const SkGlyph& glyph) {
#ifdef FT_COLOR_H
if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && glyph.isColor()) {
SkPictureRecorder recorder;
SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::Make(glyph.mask().fBounds));
if (!this->drawColorGlyph(recordingCanvas, face, glyph)) {
if (!this->drawColorGlyph(recordingCanvas, face, palette, glyph)) {
return nullptr;
}
return recorder.finishRecordingAsDrawable();

View File

@ -47,11 +47,14 @@ protected:
: INHERITED(std::move(typeface), effects, desc)
{}
bool drawColorGlyph(SkCanvas*, FT_Face, const SkGlyph&);
void generateGlyphImage(FT_Face face, const SkGlyph& glyph, const SkMatrix& bitmapTransform);
bool drawColorGlyph(SkCanvas*, FT_Face, SkSpan<SkColor> palette, const SkGlyph&);
void generateGlyphImage(FT_Face face,
SkSpan<SkColor> palette,
const SkGlyph& glyph,
const SkMatrix& bitmapTransform);
bool generateGlyphPath(FT_Face face, SkPath* path);
bool generateFacePath(FT_Face face, SkGlyphID glyphID, SkPath* path);
sk_sp<SkDrawable> generateGlyphDrawable(FT_Face face, const SkGlyph&);
sk_sp<SkDrawable> generateGlyphDrawable(FT_Face face, SkSpan<SkColor> palette, const SkGlyph&);
// Computes a bounding box for a COLRv1 glyph id in FT_BBox 26.6 format and FreeType's y-up
// coordinate space.
@ -93,7 +96,6 @@ public:
const SkString& name,
const SkFontArguments::VariationPosition::Coordinate* currentPosition = nullptr);
static bool GetAxes(FT_Face face, AxisDefinitions* axes);
private:
FT_Face openFace(SkStreamAsset* stream, int ttcIndex, FT_Stream ftStream) const;
FT_Library fLibrary;
@ -103,9 +105,7 @@ public:
/** Fetch units/EM from "head" table if needed (ie for bitmap fonts) */
static int GetUnitsPerEm(FT_Face face);
/**
* Return the font data, or nullptr on failure.
*/
/** Return the font data, or nullptr on failure. */
std::unique_ptr<SkFontData> makeFontData() const;
class FaceRec;
FaceRec* getFaceRec() const;
@ -141,6 +141,8 @@ protected:
sk_sp<SkData> onCopyTableData(SkFontTableTag) const override;
virtual std::unique_ptr<SkFontData> onMakeFontData() const = 0;
/** Utility to fill out the SkFontDescriptor palette information from the SkFontData. */
static void FontDataPaletteToDescriptorPalette(const SkFontData&, SkFontDescriptor*);
private:
mutable SkOnce fFTFaceOnce;

View File

@ -39,7 +39,7 @@ std::unique_ptr<SkFontData> SkTypeface_FCI::onMakeFontData() const {
const SkFontConfigInterface::FontIdentity& id = this->getIdentity();
return std::make_unique<SkFontData>(std::unique_ptr<SkStreamAsset>(fFCI->openStream(id)),
id.fTTCIndex, nullptr, 0);
id.fTTCIndex, 0, nullptr, 0, nullptr, 0);
}
void SkTypeface_FCI::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocalStream) const {
@ -47,6 +47,9 @@ void SkTypeface_FCI::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocalSt
this->getFamilyName(&name);
desc->setFamilyName(name.c_str());
desc->setStyle(this->fontStyle());
if (fFontData) {
SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(*fFontData, desc);
}
*isLocalStream = SkToBool(fFontData);
}
@ -239,7 +242,8 @@ protected:
return nullptr;
}
auto fontData = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
auto fontData = std::make_unique<SkFontData>(std::move(stream), ttcIndex, 0,
nullptr, 0, nullptr, 0);
return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name),
style, isFixedPitch));
}
@ -271,8 +275,11 @@ protected:
auto fontData = std::make_unique<SkFontData>(std::move(stream),
args.getCollectionIndex(),
args.getPalette().index,
axisValues.get(),
axisDefinitions.count());
axisDefinitions.count(),
args.getPalette().overrides,
args.getPalette().overrideCount);
return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name),
style, isFixedPitch));
}

View File

@ -94,8 +94,8 @@ public:
return this->makeStream();
}
std::unique_ptr<SkFontData> onMakeFontData() const override {
return std::make_unique<SkFontData>(this->makeStream(), fIndex,
fAxes.begin(), fAxes.count());
return std::make_unique<SkFontData>(
this->makeStream(), fIndex, 0, fAxes.begin(), fAxes.count(), nullptr, 0);
}
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
std::unique_ptr<SkFontData> data = this->cloneFontData(args);
@ -138,6 +138,7 @@ public:
SkASSERT(desc);
SkASSERT(serialize);
desc->setFamilyName(fFamilyName.c_str());
SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(*fData, desc);
*serialize = true;
}
@ -448,7 +449,8 @@ protected:
if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
return nullptr;
}
auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, 0,
nullptr, 0, nullptr, 0);
return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
style, isFixedPitch, name));
}
@ -470,8 +472,10 @@ protected:
Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
axisValues, name);
auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
axisValues.get(), axisDefinitions.count());
auto data = std::make_unique<SkFontData>(
std::move(stream), args.getCollectionIndex(), args.getPalette().index,
axisValues.get(), axisDefinitions.count(),
args.getPalette().overrides, args.getPalette().overrideCount);
return sk_sp<SkTypeface>(new SkTypeface_AndroidStream(std::move(data),
style, isFixedPitch, name));
}

View File

@ -87,6 +87,11 @@ sk_sp<SkTypeface> SkTypeface_Stream::onMakeClone(const SkFontArguments& args) co
familyName);
}
void SkTypeface_Stream::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
this->SkTypeface_Custom::onGetFontDescriptor(desc, isLocal);
SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(*fData, desc);
}
SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
const SkString familyName, const char path[], int index)
: INHERITED(style, isFixedPitch, sysFont, familyName, index)
@ -120,7 +125,7 @@ std::unique_ptr<SkFontData> SkTypeface_File::onMakeFontData() const {
if (!stream) {
return nullptr;
}
return std::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
return std::make_unique<SkFontData>(std::move(stream), index, 0, nullptr, 0, nullptr, 0);
}
///////////////////////////////////////////////////////////////////////////////
@ -240,8 +245,7 @@ sk_sp<SkTypeface> SkFontMgr_Custom::onMakeFromStreamArgs(std::unique_ptr<SkStrea
SkString name;
Scanner::AxisDefinitions axisDefinitions;
if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
&name, &style, &isFixedPitch, &axisDefinitions))
{
&name, &style, &isFixedPitch, &axisDefinitions)) {
return nullptr;
}
@ -249,8 +253,10 @@ sk_sp<SkTypeface> SkFontMgr_Custom::onMakeFromStreamArgs(std::unique_ptr<SkStrea
SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
axisValues.get(), axisDefinitions.count());
auto data = std::make_unique<SkFontData>(
std::move(stream), args.getCollectionIndex(), args.getPalette().index,
axisValues.get(), axisDefinitions.count(),
args.getPalette().overrides, args.getPalette().overrideCount);
return sk_sp<SkTypeface>(new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name));
}

View File

@ -68,6 +68,7 @@ protected:
std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
std::unique_ptr<SkFontData> onMakeFontData() const override;
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override;
void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
private:
const std::unique_ptr<const SkFontData> fData;

View File

@ -99,7 +99,8 @@ static void load_font_from_data(const SkTypeface_FreeType::Scanner& scanner,
addTo = new SkFontStyleSet_Custom(realname);
families->push_back().reset(addTo);
}
auto data = std::make_unique<SkFontData>(stream->duplicate(), faceIndex, nullptr, 0);
auto data = std::make_unique<SkFontData>(stream->duplicate(), faceIndex, 0,
nullptr, 0, nullptr, 0);
addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
style, isFixedPitch,
true, realname));

View File

@ -410,6 +410,7 @@ public:
}
void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
SkTypeface_FreeType::FontDataPaletteToDescriptorPalette(*fData, desc);
*serialize = true;
}
@ -541,7 +542,7 @@ public:
return nullptr;
}
// TODO: FC_VARIABLE and FC_FONT_VARIATIONS
return std::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
return std::make_unique<SkFontData>(std::move(stream), index, 0, nullptr, 0, nullptr, 0);
}
~SkTypeface_fontconfig() override {
@ -966,7 +967,8 @@ protected:
return nullptr;
}
auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
auto data = std::make_unique<SkFontData>(std::move(stream), ttcIndex, 0,
nullptr, 0, nullptr, 0);
return sk_sp<SkTypeface>(new SkTypeface_stream(std::move(data), std::move(name),
style, isFixedWidth));
}
@ -988,8 +990,10 @@ protected:
Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
axisValues, name);
auto data = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
axisValues.get(), axisDefinitions.count());
auto data = std::make_unique<SkFontData>(
std::move(stream), args.getCollectionIndex(), args.getPalette().index,
axisValues.get(), axisDefinitions.count(),
args.getPalette().overrides, args.getPalette().overrideCount);
return sk_sp<SkTypeface>(new SkTypeface_stream(std::move(data), std::move(name),
style, isFixedPitch));
}

View File

@ -217,8 +217,10 @@ sk_sp<SkTypeface> CreateTypefaceFromSkStream(std::unique_ptr<SkStreamAsset> stre
SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
auto fontData = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
axisValues.get(), axisDefinitions.count());
auto fontData = std::make_unique<SkFontData>(
std::move(stream), args.getCollectionIndex(), args.getPalette().index,
axisValues.get(), axisDefinitions.count(),
args.getPalette().overrides, args.getPalette().overrideCount);
return sk_make_sp<SkTypeface_Fuchsia>(std::move(fontData), style, isFixedPitch, name, id);
}