Bug 1791780 - Support custom color font palettes in the COLR-font rendering code. r=gfx-reviewers,lsalzman

This creates the gfx support needed to use alternate palettes, though not yet connected
to the CSS rules/properties to define and access them.

Differential Revision: https://phabricator.services.mozilla.com/D157958
This commit is contained in:
Jonathan Kew 2022-10-07 23:00:45 +00:00
parent c2d6d7271f
commit d811a2820d
11 changed files with 242 additions and 67 deletions

View File

@ -43,6 +43,9 @@ static int FuzzingRunCOLRv1(const uint8_t* data, size_t size) {
RefPtr sf = new MockScaledFont(uf, hb_data_font);
Float f2p = kPixelSize / hb_face_get_upem(hb_data_face);
UniquePtr<nsTArray<sRGBColor>> colorPalette =
COLRFonts::SetupColorPalette(hb_data_face, nullptr, nullptr, "dummy"_ns);
for (unsigned i = 0; i <= glyph_count; ++i) {
if (COLRFonts::GetColrTableVersion(colr) == 1) {
Rect bounds =
@ -51,15 +54,16 @@ static int FuzzingRunCOLRv1(const uint8_t* data, size_t size) {
if (paintGraph) {
dt->PushClipRect(bounds);
COLRFonts::PaintGlyphGraph(colr, hb_data_font, paintGraph, dt, nullptr,
sf, DrawOptions(), sRGBColor(), Point(), i,
f2p);
sf, DrawOptions(), Point(), sRGBColor(),
colorPalette.get(), i, f2p);
dt->PopClip();
}
}
const auto* layers = COLRFonts::GetGlyphLayers(colr, i);
if (layers) {
COLRFonts::PaintGlyphLayers(colr, hb_data_face, layers, dt, nullptr, sf,
DrawOptions(), sRGBColor(), Point());
DrawOptions(), Point(), sRGBColor(),
colorPalette.get());
}
}

View File

@ -146,7 +146,7 @@ struct PaintState {
const COLRHeader* v0;
const COLRv1Header* v1;
} mHeader;
const hb_color_t* mPalette;
const sRGBColor* mPalette;
DrawTarget* mDrawTarget;
ScaledFont* mScaledFont;
const int* mCoords;
@ -174,16 +174,13 @@ struct PaintState {
DeviceColor PaintState::GetColor(uint16_t aPaletteIndex, float aAlpha) const {
sRGBColor color;
if (aPaletteIndex < mNumColors) {
const hb_color_t& c = mPalette[uint16_t(aPaletteIndex)];
color = sRGBColor(
hb_color_get_red(c) / 255.0, hb_color_get_green(c) / 255.0,
hb_color_get_blue(c) / 255.0, hb_color_get_alpha(c) / 255.0 * aAlpha);
color = mPalette[uint16_t(aPaletteIndex)];
} else if (aPaletteIndex == 0xffff) {
color = mCurrentColor;
color.a *= aAlpha;
} else { // Palette index out of range! Return transparent black.
color = sRGBColor();
}
color.a *= aAlpha;
return ToDeviceColor(color);
}
@ -2380,8 +2377,8 @@ const COLRFonts::GlyphLayers* COLRFonts::GetGlyphLayers(hb_blob_t* aCOLR,
bool COLRFonts::PaintGlyphLayers(
hb_blob_t* aCOLR, hb_face_t* aFace, const GlyphLayers* aLayers,
DrawTarget* aDrawTarget, layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont, DrawOptions aDrawOptions,
const sRGBColor& aCurrentColor, const Point& aPoint) {
ScaledFont* aScaledFont, DrawOptions aDrawOptions, const Point& aPoint,
const sRGBColor& aCurrentColor, const nsTArray<sRGBColor>* aColors) {
const auto* glyphRecord = reinterpret_cast<const BaseGlyphRecord*>(aLayers);
// Default to opaque rendering (non-webrender applies alpha with a layer)
float alpha = 1.0;
@ -2406,19 +2403,11 @@ bool COLRFonts::PaintGlyphLayers(
alpha = aCurrentColor.a;
}
// Get the default palette (TODO: hook up CSS font-palette support)
unsigned int colorCount = 0;
AutoTArray<hb_color_t, 64> colors;
colors.SetLength(hb_ot_color_palette_get_colors(aFace, /* paletteIndex */ 0,
0, &colorCount, nullptr));
colorCount = colors.Length();
hb_ot_color_palette_get_colors(aFace, 0, 0, &colorCount, colors.Elements());
unsigned int length;
const COLRHeader* colr =
reinterpret_cast<const COLRHeader*>(hb_blob_get_data(aCOLR, &length));
PaintState state{{colr},
colors.Elements(),
aColors->Elements(),
aDrawTarget,
aScaledFont,
nullptr, // variations not needed
@ -2426,7 +2415,7 @@ bool COLRFonts::PaintGlyphLayers(
length,
aCurrentColor,
0.0, // fontUnitsToPixels not needed
uint16_t(colors.Length()),
uint16_t(aColors->Length()),
0,
nullptr};
return glyphRecord->Paint(state, alpha, aPoint);
@ -2457,29 +2446,21 @@ const COLRFonts::GlyphPaintGraph* COLRFonts::GetGlyphPaintGraph(
bool COLRFonts::PaintGlyphGraph(
hb_blob_t* aCOLR, hb_font_t* aFont, const GlyphPaintGraph* aPaintGraph,
DrawTarget* aDrawTarget, layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont, DrawOptions aDrawOptions,
const sRGBColor& aCurrentColor, const Point& aPoint, uint32_t aGlyphId,
float aFontUnitsToPixels) {
ScaledFont* aScaledFont, DrawOptions aDrawOptions, const Point& aPoint,
const sRGBColor& aCurrentColor, const nsTArray<sRGBColor>* aColors,
uint32_t aGlyphId, float aFontUnitsToPixels) {
if (aTextDrawer) {
// Currently we always punt to a blob for COLRv1 glyphs.
aTextDrawer->FoundUnsupportedFeature();
return true;
}
unsigned int colorCount = 0;
AutoTArray<hb_color_t, 64> colors;
hb_face_t* face = hb_font_get_face(aFont);
colors.SetLength(hb_ot_color_palette_get_colors(face, /* paletteIndex */ 0, 0,
&colorCount, nullptr));
colorCount = colors.Length();
hb_ot_color_palette_get_colors(face, 0, 0, &colorCount, colors.Elements());
unsigned int coordCount;
const int* coords = hb_font_get_var_coords_normalized(aFont, &coordCount);
AutoTArray<uint32_t, 32> visitedOffsets;
PaintState state{{nullptr},
colors.Elements(),
aColors->Elements(),
aDrawTarget,
aScaledFont,
coords,
@ -2487,7 +2468,7 @@ bool COLRFonts::PaintGlyphGraph(
hb_blob_get_length(aCOLR),
aCurrentColor,
aFontUnitsToPixels,
uint16_t(colors.Length()),
uint16_t(aColors->Length()),
uint16_t(coordCount),
&visitedOffsets};
state.mHeader.v1 =
@ -2548,4 +2529,98 @@ uint16_t COLRFonts::GetColrTableVersion(hb_blob_t* aCOLR) {
return colr->version;
}
UniquePtr<nsTArray<sRGBColor>> COLRFonts::SetupColorPalette(
hb_face_t* aFace, const FontPaletteValueSet* aPaletteValueSet,
nsAtom* aFontPalette, const nsACString& aFamilyName) {
// Find the base color palette to use, if there are multiple available;
// default to first in the font, if nothing matches what is requested.
unsigned int paletteIndex = 0;
unsigned int count = hb_ot_color_palette_get_count(aFace);
MOZ_ASSERT(count > 0, "No palettes? Font should have been rejected!");
const FontPaletteValueSet::PaletteValues* fpv = nullptr;
if (aFontPalette && aFontPalette != nsGkAtoms::normal &&
(count > 1 || aPaletteValueSet)) {
auto findPalette = [&](hb_ot_color_palette_flags_t flag) -> unsigned int {
MOZ_ASSERT(flag != HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
for (unsigned int i = 0; i < count; ++i) {
if (hb_ot_color_palette_get_flags(aFace, i) & flag) {
return i;
}
}
return 0;
};
if (aFontPalette == nsGkAtoms::light) {
paletteIndex =
findPalette(HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND);
} else if (aFontPalette == nsGkAtoms::dark) {
paletteIndex =
findPalette(HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND);
} else {
if (aPaletteValueSet) {
if ((fpv = aPaletteValueSet->Lookup(aFontPalette, aFamilyName))) {
if (fpv->mBasePalette >= 0 && fpv->mBasePalette < int32_t(count)) {
paletteIndex = fpv->mBasePalette;
} else if (fpv->mBasePalette ==
FontPaletteValueSet::PaletteValues::kLight) {
paletteIndex = findPalette(
HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND);
} else if (fpv->mBasePalette ==
FontPaletteValueSet::PaletteValues::kDark) {
paletteIndex = findPalette(
HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND);
}
}
}
}
}
// Collect the palette colors and convert them to sRGBColor values.
count =
hb_ot_color_palette_get_colors(aFace, paletteIndex, 0, nullptr, nullptr);
nsTArray<hb_color_t> colors;
colors.SetLength(count);
hb_ot_color_palette_get_colors(aFace, paletteIndex, 0, &count,
colors.Elements());
auto palette = MakeUnique<nsTArray<sRGBColor>>();
palette->SetCapacity(count);
for (const auto c : colors) {
palette->AppendElement(
sRGBColor(hb_color_get_red(c) / 255.0, hb_color_get_green(c) / 255.0,
hb_color_get_blue(c) / 255.0, hb_color_get_alpha(c) / 255.0));
}
// Apply @font-palette-values overrides, if present.
if (fpv) {
for (const auto overrideColor : fpv->mOverrides) {
if (overrideColor.mIndex < palette->Length()) {
(*palette)[overrideColor.mIndex] = overrideColor.mColor;
}
}
}
return palette;
}
const FontPaletteValueSet::PaletteValues* FontPaletteValueSet::Lookup(
nsAtom* aName, const nsACString& aFamily) const {
nsAutoCString family(aFamily);
ToLowerCase(family);
if (const HashEntry* entry =
mValues.GetEntry(PaletteHashKey(aName, family))) {
return &entry->mValue;
}
return nullptr;
}
FontPaletteValueSet::PaletteValues* FontPaletteValueSet::Insert(
nsAtom* aName, const nsACString& aFamily) {
nsAutoCString family(aFamily);
ToLowerCase(family);
HashEntry* entry = mValues.PutEntry(PaletteHashKey(aName, family));
return &entry->mValue;
}
} // end namespace mozilla::gfx

View File

@ -7,6 +7,10 @@
#define COLR_FONTS_H
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
#include "nsAtom.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
struct hb_blob_t;
struct hb_face_t;
@ -20,6 +24,70 @@ class TextDrawTarget;
namespace gfx {
class FontPaletteValueSet {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FontPaletteValueSet)
struct OverrideColor {
uint32_t mIndex = 0;
sRGBColor mColor;
};
struct PaletteValues {
enum { kLight = -1, kDark = -2 };
int32_t mBasePalette = 0; // 0-based index, or kLight/kDark constants
nsTArray<OverrideColor> mOverrides;
};
const PaletteValues* Lookup(nsAtom* aName, const nsACString& aFamily) const;
PaletteValues* Insert(nsAtom* aName, const nsACString& aFamily);
private:
~FontPaletteValueSet() = default;
struct PaletteHashKey {
RefPtr<nsAtom> mName;
nsCString mFamily;
PaletteHashKey() = delete;
PaletteHashKey(nsAtom* aName, const nsACString& aFamily)
: mName(aName), mFamily(aFamily) {}
PaletteHashKey(const PaletteHashKey& aKey) = default;
};
class HashEntry : public PLDHashEntryHdr {
public:
using KeyType = const PaletteHashKey&;
using KeyTypePointer = const PaletteHashKey*;
HashEntry() = delete;
explicit HashEntry(KeyTypePointer aKey) : mKey(*aKey) {}
HashEntry(HashEntry&& other) noexcept
: PLDHashEntryHdr(std::move(other)),
mKey(other.mKey),
mValue(std::move(other.mValue)) {
NS_ERROR("Should not be called");
}
~HashEntry() = default;
bool KeyEquals(const KeyTypePointer aKey) const {
return mKey.mName == aKey->mName && mKey.mFamily.Equals(aKey->mFamily);
}
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
return aKey->mName->hash() +
HashString(aKey->mFamily.get(), aKey->mFamily.Length());
}
enum { ALLOW_MEMMOVE = true };
PaletteHashKey mKey;
PaletteValues mValue;
};
nsTHashtable<HashEntry> mValues;
};
class COLRFonts {
public:
static bool ValidateColorGlyphs(hb_blob_t* aCOLR, hb_blob_t* aCPAL);
@ -33,8 +101,8 @@ class COLRFonts {
static bool PaintGlyphLayers(
hb_blob_t* aCOLR, hb_face_t* aFace, const GlyphLayers* aLayers,
DrawTarget* aDrawTarget, layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont, DrawOptions aDrawOptions,
const sRGBColor& aCurrentColor, const Point& aPoint);
ScaledFont* aScaledFont, DrawOptions aDrawOptions, const Point& aPoint,
const sRGBColor& aCurrentColor, const nsTArray<sRGBColor>* aColors);
// COLRv1 support: color glyph is represented by a directed acyclic graph of
// paint records.
@ -44,14 +112,12 @@ class COLRFonts {
static const GlyphPaintGraph* GetGlyphPaintGraph(hb_blob_t* aCOLR,
uint32_t aGlyphId);
static bool PaintGlyphGraph(hb_blob_t* aCOLR, hb_font_t* aFont,
const GlyphPaintGraph* aPaintGraph,
DrawTarget* aDrawTarget,
layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont, DrawOptions aDrawOptions,
const sRGBColor& aCurrentColor,
const Point& aPoint, uint32_t aGlyphId,
float aFontUnitsToPixels);
static bool PaintGlyphGraph(
hb_blob_t* aCOLR, hb_font_t* aFont, const GlyphPaintGraph* aPaintGraph,
DrawTarget* aDrawTarget, layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont, DrawOptions aDrawOptions, const Point& aPoint,
const sRGBColor& aCurrentColor, const nsTArray<sRGBColor>* aColors,
uint32_t aGlyphId, float aFontUnitsToPixels);
static Rect GetColorGlyphBounds(hb_blob_t* aCOLR, hb_font_t* aFont,
uint32_t aGlyphId, DrawTarget* aDrawTarget,
@ -59,6 +125,10 @@ class COLRFonts {
float aFontUnitsToPixels);
static uint16_t GetColrTableVersion(hb_blob_t* aCOLR);
static UniquePtr<nsTArray<sRGBColor>> SetupColorPalette(
hb_face_t* aFace, const FontPaletteValueSet* aPaletteValueSet,
nsAtom* aFontPalette, const nsACString& aFamilyName);
};
} // namespace gfx

View File

@ -2035,8 +2035,7 @@ void gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt,
if (fontParams.haveColorGlyphs && !UseNativeColrFontSupport() &&
RenderColorGlyph(runParams.dt, runParams.context, textDrawer,
fontParams.scaledFont, fontParams.drawOptions, devPt,
aGlyphID)) {
fontParams, devPt, aGlyphID)) {
return;
}
@ -2187,6 +2186,17 @@ void gfxFont::Draw(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
fontParams.haveColorGlyphs = GetFontEntry()->TryGetColorGlyphs();
fontParams.contextPaint = aRunParams.runContextPaint;
if (fontParams.haveColorGlyphs && !UseNativeColrFontSupport()) {
DeviceColor ctxColor;
fontParams.currentColor = aRunParams.context->GetDeviceColor(ctxColor)
? sRGBColor::FromABGR(ctxColor.ToABGR())
: sRGBColor::OpaqueBlack();
gfxFontEntry::AutoHBFace face = GetFontEntry()->GetHBFace();
fontParams.palette = COLRFonts::SetupColorPalette(
face, aRunParams.paletteValueSet, aRunParams.fontPalette,
GetFontEntry()->FamilyName());
}
if (textDrawer) {
fontParams.isVerticalFont = aRunParams.isVerticalRun;
} else {
@ -2468,24 +2478,17 @@ bool gfxFont::RenderSVGGlyph(gfxContext* aContext,
bool gfxFont::RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
layout::TextDrawTarget* aTextDrawer,
ScaledFont* aScaledFont,
DrawOptions aDrawOptions, const Point& aPoint,
uint32_t aGlyphId) {
auto currentColor = [=]() {
DeviceColor ctxColor;
return aContext->GetDeviceColor(ctxColor)
? sRGBColor::FromABGR(ctxColor.ToABGR())
: sRGBColor::OpaqueBlack();
};
const FontDrawParams& aFontParams,
const Point& aPoint, uint32_t aGlyphId) {
if (const auto* paintGraph =
COLRFonts::GetGlyphPaintGraph(GetFontEntry()->GetCOLR(), aGlyphId)) {
const auto* hbShaper = GetHarfBuzzShaper();
if (hbShaper && hbShaper->IsInitialized()) {
return COLRFonts::PaintGlyphGraph(
GetFontEntry()->GetCOLR(), hbShaper->GetHBFont(), paintGraph,
aDrawTarget, aTextDrawer, aScaledFont, aDrawOptions, currentColor(),
aPoint, aGlyphId, mFUnitsConvFactor);
aDrawTarget, aTextDrawer, aFontParams.scaledFont,
aFontParams.drawOptions, aPoint, aFontParams.currentColor,
aFontParams.palette.get(), aGlyphId, mFUnitsConvFactor);
}
}
@ -2494,7 +2497,8 @@ bool gfxFont::RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
auto face(GetFontEntry()->GetHBFace());
bool ok = COLRFonts::PaintGlyphLayers(
GetFontEntry()->GetCOLR(), face, layers, aDrawTarget, aTextDrawer,
aScaledFont, aDrawOptions, currentColor(), aPoint);
aFontParams.scaledFont, aFontParams.drawOptions, aPoint,
aFontParams.currentColor, aFontParams.palette.get());
return ok;
}

View File

@ -2263,10 +2263,12 @@ class gfxFont {
bool RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
mozilla::layout::TextDrawTarget* aTextDrawer,
mozilla::gfx::ScaledFont* scaledFont,
mozilla::gfx::DrawOptions drawOptions,
const FontDrawParams& aFontParams,
const mozilla::gfx::Point& aPoint, uint32_t aGlyphId);
void SetupColorPalette(FontDrawParams* aFontParams,
const TextRunDrawParams& aRunParams) const;
// Subclasses can override to return true if the platform is able to render
// COLR-font glyphs directly, instead of us painting the layers explicitly.
// (Currently used only for COLR.v0 fonts on macOS.)
@ -2301,6 +2303,8 @@ struct MOZ_STACK_CLASS TextRunDrawParams {
gfxPattern* textStrokePattern = nullptr;
const mozilla::gfx::StrokeOptions* strokeOpts = nullptr;
const mozilla::gfx::DrawOptions* drawOpts = nullptr;
const mozilla::gfx::FontPaletteValueSet* paletteValueSet = nullptr;
nsAtom* fontPalette = nullptr;
DrawMode drawMode = DrawMode::GLYPH_FILL;
bool isVerticalRun = false;
bool isRTL = false;
@ -2316,6 +2320,8 @@ struct MOZ_STACK_CLASS FontDrawParams {
int32_t extraStrikes;
mozilla::gfx::DrawOptions drawOptions;
gfxFloat advanceDirection;
mozilla::gfx::sRGBColor currentColor;
mozilla::UniquePtr<nsTArray<mozilla::gfx::sRGBColor>> palette;
bool isVerticalFont;
bool haveSVGGlyphs;
bool haveColorGlyphs;

View File

@ -613,12 +613,14 @@ bool gfxMacFont::ShouldRoundXOffset(cairo_t* aCairo) const {
}
bool gfxMacFont::UseNativeColrFontSupport() const {
if (nsCocoaFeatures::OnHighSierraOrLater()) {
auto* colr = GetFontEntry()->GetCOLR();
if (colr && COLRFonts::GetColrTableVersion(colr) == 0) {
return true;
/*
if (nsCocoaFeatures::OnHighSierraOrLater()) {
auto* colr = GetFontEntry()->GetCOLR();
if (colr && COLRFonts::GetColrTableVersion(colr) == 0) {
return true;
}
}
}
*/
return false;
}

View File

@ -1827,7 +1827,6 @@ bool gfxPlatform::IsFontFormatSupported(
}
StyleFontFaceSourceTechFlags unsupportedTechnologies =
StyleFontFaceSourceTechFlags::INCREMENTAL |
StyleFontFaceSourceTechFlags::PALETTES |
StyleFontFaceSourceTechFlags::COLOR_SBIX;
if (!StaticPrefs::gfx_downloadable_fonts_keep_color_bitmaps()) {
unsupportedTechnologies |= StyleFontFaceSourceTechFlags::COLOR_CBDT;
@ -1835,6 +1834,9 @@ bool gfxPlatform::IsFontFormatSupported(
if (!StaticPrefs::gfx_font_rendering_colr_v1_enabled()) {
unsupportedTechnologies |= StyleFontFaceSourceTechFlags::COLOR_COLRV1;
}
if (!StaticPrefs::layout_css_font_palette_enabled()) {
unsupportedTechnologies |= StyleFontFaceSourceTechFlags::PALETTES;
}
if (!StaticPrefs::layout_css_font_variations_enabled()) {
unsupportedTechnologies |= StyleFontFaceSourceTechFlags::VARIATIONS;
}

View File

@ -632,6 +632,8 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt,
params.direction = direction;
params.strokeOpts = aParams.strokeOpts;
params.textStrokeColor = aParams.textStrokeColor;
params.fontPalette = aParams.fontPalette;
params.paletteValueSet = aParams.paletteValueSet;
params.textStrokePattern = aParams.textStrokePattern;
params.drawOpts = aParams.drawOpts;
params.drawMode = aParams.drawMode;

View File

@ -252,6 +252,8 @@ class gfxTextRun : public gfxShapedText {
gfxContext* context;
DrawMode drawMode = DrawMode::GLYPH_FILL;
nscolor textStrokeColor = 0;
nsAtom* fontPalette = nullptr;
mozilla::gfx::FontPaletteValueSet* paletteValueSet = nullptr;
gfxPattern* textStrokePattern = nullptr;
const mozilla::gfx::StrokeOptions* strokeOpts = nullptr;
const mozilla::gfx::DrawOptions* drawOpts = nullptr;

View File

@ -214,6 +214,7 @@ struct nsTextFrame::DrawTextRunParams {
DrawPathCallbacks* callbacks = nullptr;
nscolor textColor = NS_RGBA(0, 0, 0, 0);
nscolor textStrokeColor = NS_RGBA(0, 0, 0, 0);
nsAtom* fontPalette = nullptr;
float textStrokeWidth = 0.0f;
bool drawSoftHyphen = false;
explicit DrawTextRunParams(gfxContext* aContext) : context(aContext) {}
@ -6346,6 +6347,7 @@ void nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
params.textStyle = &textPaintStyle;
params.textColor =
aParams.context == shadowContext ? shadowColor : NS_RGB(0, 0, 0);
params.fontPalette = nsGkAtoms::normal; // XXX fixme
params.clipEdges = aParams.clipEdges;
params.drawSoftHyphen = HasAnyStateBits(TEXT_HYPHEN_BREAK);
// Multi-color shadow is not allowed, so we use the same color of the text
@ -6478,6 +6480,7 @@ bool nsTextFrame::PaintTextWithSelectionColors(
params.advanceWidth = &advance;
params.callbacks = aParams.callbacks;
params.glyphRange = aParams.glyphRange;
params.fontPalette = StyleFont()->GetFontPaletteAtom();
PaintShadowParams shadowParams(aParams);
shadowParams.provider = aParams.provider;
@ -7048,6 +7051,8 @@ void nsTextFrame::PaintText(const PaintTextParams& aParams,
params.contextPaint = aParams.contextPaint;
params.callbacks = aParams.callbacks;
params.glyphRange = range;
params.fontPalette = StyleFont()->GetFontPaletteAtom();
DrawText(range, textBaselinePt, params);
}
@ -7060,6 +7065,7 @@ static void DrawTextRun(const gfxTextRun* aTextRun,
params.provider = aParams.provider;
params.advanceWidth = aParams.advanceWidth;
params.contextPaint = aParams.contextPaint;
params.fontPalette = aParams.fontPalette;
params.callbacks = aParams.callbacks;
if (aParams.callbacks) {
aParams.callbacks->NotifyBeforeText(aParams.textColor);

View File

@ -118,6 +118,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont {
static mozilla::Length ZoomText(const mozilla::dom::Document&,
mozilla::Length);
nsAtom* GetFontPaletteAtom() const { return mFontPalette._0.AsAtom(); }
nsFont mFont;
// Our "computed size". Can be different from mFont.size which is our "actual