Apply palette request to DirectWrite fonts
Bug: skia:12984 Change-Id: Ic0c3774c38c19efb224bf4462ce1397c21c95b78 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/512576 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
1380d2c02c
commit
e5d89539fb
@ -206,24 +206,32 @@ void SkFontDescriptor::serialize(SkWStream* stream) const {
|
||||
write_scalar(stream, fStyle.slant() == SkFontStyle::kUpright_Slant ? 0 : 14, kSlant);
|
||||
write_scalar(stream, fStyle.slant() == SkFontStyle::kItalic_Slant ? 1 : 0, kItalic);
|
||||
|
||||
if (fCollectionIndex) {
|
||||
if (fCollectionIndex > 0) {
|
||||
write_uint(stream, fCollectionIndex, kFontIndex);
|
||||
}
|
||||
if (fPaletteIndex) {
|
||||
if (fPaletteIndex > 0) {
|
||||
write_uint(stream, fPaletteIndex, kPaletteIndex);
|
||||
}
|
||||
if (fCoordinateCount) {
|
||||
if (fCoordinateCount > 0) {
|
||||
write_uint(stream, fCoordinateCount, kFontVariation);
|
||||
for (int i = 0; i < fCoordinateCount; ++i) {
|
||||
stream->write32(fVariation[i].axis);
|
||||
stream->writeScalar(fVariation[i].value);
|
||||
}
|
||||
}
|
||||
if (fPaletteEntryOverrideCount) {
|
||||
write_uint(stream, fPaletteEntryOverrideCount, kPaletteEntryOverrides);
|
||||
if (fPaletteEntryOverrideCount > 0) {
|
||||
int nonNegativePaletteOverrideIndexes = 0;
|
||||
for (int i = 0; i < fPaletteEntryOverrideCount; ++i) {
|
||||
stream->writePackedUInt(fPaletteEntryOverrides[i].index);
|
||||
stream->write32(fPaletteEntryOverrides[i].color);
|
||||
if (0 <= fPaletteEntryOverrides[i].index) {
|
||||
++nonNegativePaletteOverrideIndexes;
|
||||
}
|
||||
}
|
||||
write_uint(stream, nonNegativePaletteOverrideIndexes, kPaletteEntryOverrides);
|
||||
for (int i = 0; i < fPaletteEntryOverrideCount; ++i) {
|
||||
if (0 <= fPaletteEntryOverrides[i].index) {
|
||||
stream->writePackedUInt(fPaletteEntryOverrides[i].index);
|
||||
stream->write32(fPaletteEntryOverrides[i].color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,7 +531,8 @@ sk_sp<SkTypeface> SkFontMgr_DirectWrite::makeTypefaceFromDWriteFont(
|
||||
ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
|
||||
sk_sp<SkTypeface> face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
|
||||
if (nullptr == face) {
|
||||
face = DWriteFontTypeface::Make(fFactory.get(), fontFace, font, fontFamily, nullptr);
|
||||
face = DWriteFontTypeface::Make(fFactory.get(), fontFace, font, fontFamily, nullptr,
|
||||
SkFontArguments::Palette{0, nullptr, 0});
|
||||
if (face) {
|
||||
fTFCache.add(face);
|
||||
}
|
||||
@ -1113,7 +1114,8 @@ sk_sp<SkTypeface> SkFontMgr_DirectWrite::onMakeFromStreamArgs(std::unique_ptr<Sk
|
||||
sk_make_sp<DWriteFontTypeface::Loaders>(
|
||||
fFactory.get(),
|
||||
autoUnregisterFontFileLoader.detatch(),
|
||||
autoUnregisterFontCollectionLoader.detatch()));
|
||||
autoUnregisterFontCollectionLoader.detatch()),
|
||||
args.getPalette());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,21 +1067,22 @@ void SkScalerContext_DW::drawColorGlyphImage(const SkGlyph& glyph, SkCanvas& can
|
||||
}
|
||||
canvas.concat(fSkXform);
|
||||
|
||||
DWriteFontTypeface* typeface = this->getDWriteTypeface();
|
||||
size_t paletteEntryCount = typeface->fPaletteEntryCount;
|
||||
SkColor* palette = typeface->fPalette.get();
|
||||
BOOL hasNextRun = FALSE;
|
||||
while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
|
||||
const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
|
||||
HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run");
|
||||
|
||||
SkColor color;
|
||||
if (colorGlyph->paletteIndex != 0xffff) {
|
||||
color = SkColorSetARGB(sk_float_round2int(colorGlyph->runColor.a * 255),
|
||||
sk_float_round2int(colorGlyph->runColor.r * 255),
|
||||
sk_float_round2int(colorGlyph->runColor.g * 255),
|
||||
sk_float_round2int(colorGlyph->runColor.b * 255));
|
||||
} else {
|
||||
// If all components of runColor are 0 or (equivalently) paletteIndex is 0xFFFF then
|
||||
// the 'foreground color' is used.
|
||||
if (colorGlyph->paletteIndex == 0xffff) {
|
||||
color = fRec.fForegroundColor;
|
||||
} else if (colorGlyph->paletteIndex < paletteEntryCount) {
|
||||
color = palette[colorGlyph->paletteIndex];
|
||||
} else {
|
||||
SK_TRACEHR(DWRITE_E_NOCOLOR, "Invalid palette index.");
|
||||
color = SK_ColorBLACK;
|
||||
}
|
||||
paint.setColor(color);
|
||||
|
||||
|
@ -33,6 +33,96 @@
|
||||
#include "src/utils/win/SkDWrite.h"
|
||||
#include "src/utils/win/SkDWriteFontFileStream.h"
|
||||
|
||||
HRESULT DWriteFontTypeface::initializePalette() {
|
||||
if (!fIsColorFont) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!SkTFitsIn<UINT32>(fRequestedPalette.index)) {
|
||||
HRM(DWRITE_E_NOCOLOR, "Requested palette index out of UINT32 range.");
|
||||
}
|
||||
UINT32 dwPaletteCount = fDWriteFontFace2->GetColorPaletteCount();
|
||||
UINT32 requestedPaletteIndex = fRequestedPalette.index;
|
||||
if (!(requestedPaletteIndex < dwPaletteCount)) {
|
||||
HRM(DWRITE_E_NOCOLOR, "Requested palette index out of range.");
|
||||
}
|
||||
|
||||
UINT32 dwPaletteEntryCount = fDWriteFontFace2->GetPaletteEntryCount();
|
||||
SkAutoSTMalloc<8, DWRITE_COLOR_F> dwPaletteEntry(dwPaletteEntryCount);
|
||||
HRM(fDWriteFontFace2->GetPaletteEntries(requestedPaletteIndex,
|
||||
0, dwPaletteEntryCount,
|
||||
dwPaletteEntry),
|
||||
"Could not retrieve palette entries.");
|
||||
|
||||
fPalette.reset(new SkColor[dwPaletteEntryCount]);
|
||||
for (UINT32 i = 0; i < dwPaletteEntryCount; ++i) {
|
||||
fPalette[i] = SkColorSetARGB(sk_float_round2int(dwPaletteEntry[i].a * 255),
|
||||
sk_float_round2int(dwPaletteEntry[i].r * 255),
|
||||
sk_float_round2int(dwPaletteEntry[i].g * 255),
|
||||
sk_float_round2int(dwPaletteEntry[i].b * 255));
|
||||
}
|
||||
|
||||
for (int i = 0; i < fRequestedPalette.overrideCount; ++i) {
|
||||
const SkFontArguments::Palette::Override& paletteOverride = fRequestedPalette.overrides[i];
|
||||
if (!SkTFitsIn<UINT32>(paletteOverride.index) ||
|
||||
!((UINT32)paletteOverride.index < dwPaletteEntryCount))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fPalette[paletteOverride.index] = paletteOverride.color;
|
||||
}
|
||||
fPaletteEntryCount = dwPaletteEntryCount;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWriteFontTypeface::DWriteFontTypeface(const SkFontStyle& style,
|
||||
IDWriteFactory* factory,
|
||||
IDWriteFontFace* fontFace,
|
||||
IDWriteFont* font,
|
||||
IDWriteFontFamily* fontFamily,
|
||||
sk_sp<Loaders> loaders,
|
||||
const SkFontArguments::Palette& palette)
|
||||
: SkTypeface(style, false)
|
||||
, fFactory(SkRefComPtr(factory))
|
||||
, fDWriteFontFamily(SkRefComPtr(fontFamily))
|
||||
, fDWriteFont(SkRefComPtr(font))
|
||||
, fDWriteFontFace(SkRefComPtr(fontFace))
|
||||
, fRequestedPaletteEntryOverrides(palette.overrideCount
|
||||
? (SkFontArguments::Palette::Override*)memcpy(
|
||||
new SkFontArguments::Palette::Override[palette.overrideCount],
|
||||
palette.overrides,
|
||||
palette.overrideCount * sizeof(palette.overrides[0]))
|
||||
: nullptr)
|
||||
, fRequestedPalette{palette.index,
|
||||
fRequestedPaletteEntryOverrides.get(), palette.overrideCount }
|
||||
, fPaletteEntryCount(0)
|
||||
, fLoaders(std::move(loaders))
|
||||
{
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
|
||||
// IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
|
||||
// http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace1.get());
|
||||
}
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
|
||||
}
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace4))) {
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace4.get());
|
||||
}
|
||||
if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
|
||||
SkASSERT_RELEASE(nullptr == fFactory2.get());
|
||||
}
|
||||
|
||||
if (fDWriteFontFace1 && fDWriteFontFace1->IsMonospacedFont()) {
|
||||
this->setIsFixedPitch(true);
|
||||
}
|
||||
|
||||
fIsColorFont = fFactory2 && fDWriteFontFace2 && fDWriteFontFace2->IsColorFont();
|
||||
this->initializePalette();
|
||||
}
|
||||
|
||||
|
||||
DWriteFontTypeface::Loaders::~Loaders() {
|
||||
// Don't return if any fail, just keep going to free up as much as possible.
|
||||
HRESULT hr;
|
||||
@ -85,6 +175,12 @@ void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
|
||||
|
||||
desc->setFamilyName(utf8FamilyName.c_str());
|
||||
desc->setStyle(this->fontStyle());
|
||||
|
||||
desc->setPaleteIndex(fRequestedPalette.index);
|
||||
sk_careful_memcpy(desc->setPaletteEntryOverrides(fRequestedPalette.overrideCount),
|
||||
fRequestedPalette.overrides,
|
||||
fRequestedPalette.overrideCount * sizeof(fRequestedPalette.overrides[0]));
|
||||
|
||||
*isLocalStream = SkToBool(fLoaders);
|
||||
}
|
||||
|
||||
@ -357,11 +453,26 @@ sk_sp<SkTypeface> DWriteFontTypeface::onMakeClone(const SkFontArguments& args) c
|
||||
newFontFace.get(),
|
||||
fDWriteFont.get(),
|
||||
fDWriteFontFamily.get(),
|
||||
fLoaders);
|
||||
fLoaders,
|
||||
args.getPalette());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// If the palette args have changed, a new font will need to be created.
|
||||
if (args.getPalette().index != fRequestedPalette.index ||
|
||||
args.getPalette().overrideCount != fRequestedPalette.overrideCount ||
|
||||
memcmp(args.getPalette().overrides, fRequestedPalette.overrides,
|
||||
fRequestedPalette.overrideCount * sizeof(fRequestedPalette.overrides[0])))
|
||||
{
|
||||
return DWriteFontTypeface::Make(fFactory.get(),
|
||||
fDWriteFontFace.get(),
|
||||
fDWriteFont.get(),
|
||||
fDWriteFontFamily.get(),
|
||||
fLoaders,
|
||||
args.getPalette());
|
||||
}
|
||||
|
||||
return sk_ref_sp(this);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef SkTypeface_win_dw_DEFINED
|
||||
#define SkTypeface_win_dw_DEFINED
|
||||
|
||||
#include "include/core/SkFontArguments.h"
|
||||
#include "include/core/SkTypeface.h"
|
||||
#include "src/core/SkAdvancedTypefaceMetrics.h"
|
||||
#include "src/core/SkLeanWindows.h"
|
||||
@ -64,35 +65,9 @@ private:
|
||||
IDWriteFontFace* fontFace,
|
||||
IDWriteFont* font,
|
||||
IDWriteFontFamily* fontFamily,
|
||||
sk_sp<Loaders> loaders)
|
||||
: SkTypeface(style, false)
|
||||
, fFactory(SkRefComPtr(factory))
|
||||
, fDWriteFontFamily(SkRefComPtr(fontFamily))
|
||||
, fDWriteFont(SkRefComPtr(font))
|
||||
, fDWriteFontFace(SkRefComPtr(fontFace))
|
||||
, fLoaders(std::move(loaders))
|
||||
{
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
|
||||
// IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
|
||||
// http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace1.get());
|
||||
}
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
|
||||
}
|
||||
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace4))) {
|
||||
SkASSERT_RELEASE(nullptr == fDWriteFontFace4.get());
|
||||
}
|
||||
if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
|
||||
SkASSERT_RELEASE(nullptr == fFactory2.get());
|
||||
}
|
||||
|
||||
if (fDWriteFontFace1 && fDWriteFontFace1->IsMonospacedFont()) {
|
||||
this->setIsFixedPitch(true);
|
||||
}
|
||||
|
||||
fIsColorFont = fFactory2 && fDWriteFontFace2 && fDWriteFontFace2->IsColorFont();
|
||||
}
|
||||
sk_sp<Loaders> loaders,
|
||||
const SkFontArguments::Palette&);
|
||||
HRESULT initializePalette();
|
||||
|
||||
public:
|
||||
SkTScopedComPtr<IDWriteFactory> fFactory;
|
||||
@ -105,15 +80,22 @@ public:
|
||||
SkTScopedComPtr<IDWriteFontFace4> fDWriteFontFace4;
|
||||
bool fIsColorFont;
|
||||
|
||||
std::unique_ptr<SkFontArguments::Palette::Override> fRequestedPaletteEntryOverrides;
|
||||
SkFontArguments::Palette fRequestedPalette;
|
||||
|
||||
size_t fPaletteEntryCount;
|
||||
std::unique_ptr<SkColor[]> fPalette;
|
||||
|
||||
static sk_sp<DWriteFontTypeface> Make(
|
||||
IDWriteFactory* factory,
|
||||
IDWriteFontFace* fontFace,
|
||||
IDWriteFont* font,
|
||||
IDWriteFontFamily* fontFamily,
|
||||
sk_sp<Loaders> loaders)
|
||||
sk_sp<Loaders> loaders,
|
||||
const SkFontArguments::Palette& palette)
|
||||
{
|
||||
return sk_sp<DWriteFontTypeface>(new DWriteFontTypeface(
|
||||
get_style(font), factory, fontFace, font, fontFamily, std::move(loaders)));
|
||||
get_style(font), factory, fontFace, font, fontFamily, std::move(loaders), palette));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
Loading…
Reference in New Issue
Block a user