From d811a2820d2c5238ad7990bd49060ea6510b6e9a Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 7 Oct 2022 23:00:45 +0000 Subject: [PATCH] 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 --- gfx/tests/fuzz/TestCOLRv1.cpp | 10 ++- gfx/thebes/COLRFonts.cpp | 137 +++++++++++++++++++++++++-------- gfx/thebes/COLRFonts.h | 90 +++++++++++++++++++--- gfx/thebes/gfxFont.cpp | 34 ++++---- gfx/thebes/gfxFont.h | 10 ++- gfx/thebes/gfxMacFont.cpp | 12 +-- gfx/thebes/gfxPlatform.cpp | 4 +- gfx/thebes/gfxTextRun.cpp | 2 + gfx/thebes/gfxTextRun.h | 2 + layout/generic/nsTextFrame.cpp | 6 ++ layout/style/nsStyleStruct.h | 2 + 11 files changed, 242 insertions(+), 67 deletions(-) diff --git a/gfx/tests/fuzz/TestCOLRv1.cpp b/gfx/tests/fuzz/TestCOLRv1.cpp index 0811fc4f6d32..9d8dc6186aec 100644 --- a/gfx/tests/fuzz/TestCOLRv1.cpp +++ b/gfx/tests/fuzz/TestCOLRv1.cpp @@ -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> 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()); } } diff --git a/gfx/thebes/COLRFonts.cpp b/gfx/thebes/COLRFonts.cpp index a9926cb99b9f..60f9e2d5139d 100644 --- a/gfx/thebes/COLRFonts.cpp +++ b/gfx/thebes/COLRFonts.cpp @@ -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* aColors) { const auto* glyphRecord = reinterpret_cast(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 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(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* 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 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 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> 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 colors; + colors.SetLength(count); + hb_ot_color_palette_get_colors(aFace, paletteIndex, 0, &count, + colors.Elements()); + + auto palette = MakeUnique>(); + 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 diff --git a/gfx/thebes/COLRFonts.h b/gfx/thebes/COLRFonts.h index 6a7175c2c0bf..a073bb416462 100644 --- a/gfx/thebes/COLRFonts.h +++ b/gfx/thebes/COLRFonts.h @@ -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 mOverrides; + }; + + const PaletteValues* Lookup(nsAtom* aName, const nsACString& aFamily) const; + + PaletteValues* Insert(nsAtom* aName, const nsACString& aFamily); + + private: + ~FontPaletteValueSet() = default; + + struct PaletteHashKey { + RefPtr 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 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* 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* 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> SetupColorPalette( + hb_face_t* aFace, const FontPaletteValueSet* aPaletteValueSet, + nsAtom* aFontPalette, const nsACString& aFamilyName); }; } // namespace gfx diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 4652399a74b2..a2e7a61f3c64 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -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; } diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 4f357a6f158e..6c9d304ea55c 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -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> palette; bool isVerticalFont; bool haveSVGGlyphs; bool haveColorGlyphs; diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 939d115b09c5..07a159bd416e 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -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; } diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index a29ce7c3a4bf..67b738b06270 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -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; } diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index 6e90a6e728d9..5a01ee22ecf4 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -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; diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h index 5bccb017c8ed..aafc422e58bb 100644 --- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -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; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 6100b3936ba2..599136d87a11 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -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); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index cb58860881aa..9324c027f21b 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -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