Bug 1791782 - Connect CSS font-palette features to rendering via the presContext. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D157959
This commit is contained in:
Jonathan Kew 2022-10-07 23:00:46 +00:00
parent d811a2820d
commit b593702fb8
13 changed files with 183 additions and 6 deletions

View File

@ -7184,6 +7184,7 @@ void Document::ApplicableStylesChanged() {
pc->MarkCounterStylesDirty();
pc->MarkFontFeatureValuesDirty();
pc->MarkFontPaletteValuesDirty();
pc->RestyleManager()->NextRestyleIsForCSSRuleChanges();
}

View File

@ -4350,6 +4350,8 @@ void PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush) {
mPresContext->FlushFontFeatureValues();
mPresContext->FlushFontPaletteValues();
// Flush any requested SMIL samples.
if (mDocument->HasAnimationController()) {
mDocument->GetAnimationController()->FlushResampleRequests();
@ -9408,6 +9410,8 @@ void PresShell::WillDoReflow() {
mPresContext->FlushFontFeatureValues();
mPresContext->FlushFontPaletteValues();
mLastReflowStart = GetPerformanceNowUnclamped();
}

View File

@ -277,6 +277,7 @@ nsPresContext::nsPresContext(dom::Document* aDocument, nsPresContextType aType)
mIsGlyph(false),
mCounterStylesDirty(true),
mFontFeatureValuesDirty(true),
mFontPaletteValuesDirty(true),
mIsVisual(false),
mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
mQuirkSheetAdded(false),
@ -1835,6 +1836,7 @@ void nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint,
mDocument->MarkUserFontSetDirty();
MarkCounterStylesDirty();
MarkFontFeatureValuesDirty();
MarkFontPaletteValuesDirty();
PostRebuildAllStyleDataEvent(aExtraHint, aRestyleHint);
}
@ -2780,11 +2782,31 @@ void nsPresContext::FlushFontFeatureValues() {
return; // we've been torn down
}
if (mFontFeatureValuesDirty) {
ServoStyleSet* styleSet = mPresShell->StyleSet();
mFontFeatureValuesLookup = styleSet->BuildFontFeatureValueSet();
mFontFeatureValuesDirty = false;
if (!mFontFeatureValuesDirty) {
return;
}
ServoStyleSet* styleSet = mPresShell->StyleSet();
mFontFeatureValuesLookup = styleSet->BuildFontFeatureValueSet();
mFontFeatureValuesDirty = false;
}
void nsPresContext::FlushFontPaletteValues() {
if (!mPresShell) {
return; // we've been torn down
}
if (!mFontPaletteValuesDirty) {
return;
}
ServoStyleSet* styleSet = mPresShell->StyleSet();
mFontPaletteValueSet = styleSet->BuildFontPaletteValueSet();
mFontPaletteValuesDirty = false;
// Even if we're not reflowing anything, a change to the palette means we
// need to repaint in order to show the new colors.
InvalidatePaintedLayers();
}
void nsPresContext::SetVisibleArea(const nsRect& r) {

View File

@ -92,6 +92,9 @@ class Document;
class Element;
enum class PrefersColorSchemeOverride : uint8_t;
} // namespace dom
namespace gfx {
class FontPaletteValueSet;
} // namespace gfx
} // namespace mozilla
// supported values for cached integer pref types
@ -923,6 +926,9 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
void FlushFontFeatureValues();
void MarkFontFeatureValuesDirty() { mFontFeatureValuesDirty = true; }
void FlushFontPaletteValues();
void MarkFontPaletteValuesDirty() { mFontPaletteValuesDirty = true; }
// Ensure that it is safe to hand out CSS rules outside the layout
// engine by ensuring that all CSS style sheets have unique inners
// and, if necessary, synchronously rebuilding all style data.
@ -1084,6 +1090,10 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
return mFontFeatureValuesLookup;
}
mozilla::gfx::FontPaletteValueSet* GetFontPaletteValueSet() const {
return mFontPaletteValueSet;
}
protected:
friend class nsRunnableMethod<nsPresContext>;
void ThemeChangedInternal();
@ -1185,6 +1195,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
RefPtr<mozilla::CounterStyleManager> mCounterStyleManager;
const nsStaticAtom* mMedium;
RefPtr<gfxFontFeatureValueSet> mFontFeatureValuesLookup;
RefPtr<mozilla::gfx::FontPaletteValueSet> mFontPaletteValueSet;
// TODO(emilio): Maybe lazily create and put under a UniquePtr if this grows a
// lot?
@ -1340,6 +1351,9 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
// Is the current mFontFeatureValuesLookup valid?
unsigned mFontFeatureValuesDirty : 1;
// Is the current mFontFeatureValueSet valid?
unsigned mFontPaletteValuesDirty : 1;
unsigned mIsVisual : 1;
unsigned mHasWarnedAboutTooLargeDashedOrDottedRadius : 1;

View File

@ -215,6 +215,7 @@ struct nsTextFrame::DrawTextRunParams {
nscolor textColor = NS_RGBA(0, 0, 0, 0);
nscolor textStrokeColor = NS_RGBA(0, 0, 0, 0);
nsAtom* fontPalette = nullptr;
gfx::FontPaletteValueSet* paletteValueSet = nullptr;
float textStrokeWidth = 0.0f;
bool drawSoftHyphen = false;
explicit DrawTextRunParams(gfxContext* aContext) : context(aContext) {}
@ -6347,12 +6348,14 @@ 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
// color.
params.decorationOverrideColor = &params.textColor;
params.fontPalette = StyleFont()->GetFontPaletteAtom();
params.paletteValueSet = PresContext()->GetFontPaletteValueSet();
DrawText(aParams.range, aParams.textBaselinePt + shadowGfxOffset, params);
contextBoxBlur.DoPaint();
@ -6481,6 +6484,7 @@ bool nsTextFrame::PaintTextWithSelectionColors(
params.callbacks = aParams.callbacks;
params.glyphRange = aParams.glyphRange;
params.fontPalette = StyleFont()->GetFontPaletteAtom();
params.paletteValueSet = PresContext()->GetFontPaletteValueSet();
PaintShadowParams shadowParams(aParams);
shadowParams.provider = aParams.provider;
@ -7052,6 +7056,7 @@ void nsTextFrame::PaintText(const PaintTextParams& aParams,
params.callbacks = aParams.callbacks;
params.glyphRange = range;
params.fontPalette = StyleFont()->GetFontPaletteAtom();
params.paletteValueSet = PresContext()->GetFontPaletteValueSet();
DrawText(range, textBaselinePt, params);
}
@ -7066,6 +7071,7 @@ static void DrawTextRun(const gfxTextRun* aTextRun,
params.advanceWidth = aParams.advanceWidth;
params.contextPaint = aParams.contextPaint;
params.fontPalette = aParams.fontPalette;
params.paletteValueSet = aParams.paletteValueSet;
params.callbacks = aParams.callbacks;
if (aParams.callbacks) {
aParams.callbacks->NotifyBeforeText(aParams.textColor);

View File

@ -1005,6 +1005,32 @@ nsTArray<uint32_t>* Gecko_AppendFeatureValueHashEntry(
aName, aAlternate);
}
gfx::FontPaletteValueSet* Gecko_ConstructFontPaletteValueSet() {
return new gfx::FontPaletteValueSet();
}
gfx::FontPaletteValueSet::PaletteValues* Gecko_AppendPaletteValueHashEntry(
gfx::FontPaletteValueSet* aPaletteValueSet, nsAtom* aFamily,
nsAtom* aName) {
MOZ_ASSERT(NS_IsMainThread());
return aPaletteValueSet->Insert(aName, nsAtomCString(aFamily));
}
void Gecko_SetFontPaletteBase(gfx::FontPaletteValueSet::PaletteValues* aValues,
int32_t aBasePaletteIndex) {
aValues->mBasePalette = aBasePaletteIndex;
}
void Gecko_SetFontPaletteOverride(
gfx::FontPaletteValueSet::PaletteValues* aValues, int32_t aIndex,
StyleRGBA aColor) {
if (aIndex < 0) {
return;
}
aValues->mOverrides.AppendElement(gfx::FontPaletteValueSet::OverrideColor{
uint32_t(aIndex), gfx::sRGBColor::FromABGR(aColor.ToColor())});
}
void Gecko_CounterStyle_ToPtr(const StyleCounterStyle* aStyle,
CounterStylePtr* aPtr) {
*aPtr = CounterStylePtr::FromStyle(*aStyle);

View File

@ -19,6 +19,7 @@
#include "mozilla/EffectCompositor.h"
#include "mozilla/PreferenceSheet.h"
#include "nsStyleStruct.h"
#include "COLRFonts.h"
class nsAtom;
class nsIURI;
@ -287,6 +288,22 @@ void Gecko_AppendAlternateValues(nsFont* font, uint32_t alternate_name,
void Gecko_CopyAlternateValuesFrom(nsFont* dest, const nsFont* src);
// The FontPaletteValueSet returned from this function has zero reference.
mozilla::gfx::FontPaletteValueSet* Gecko_ConstructFontPaletteValueSet();
mozilla::gfx::FontPaletteValueSet::PaletteValues*
Gecko_AppendPaletteValueHashEntry(
mozilla::gfx::FontPaletteValueSet* aPaletteValueSet, nsAtom* aFamily,
nsAtom* aName);
void Gecko_SetFontPaletteBase(
mozilla::gfx::FontPaletteValueSet::PaletteValues* aValues,
int32_t aBasePaletteIndex);
void Gecko_SetFontPaletteOverride(
mozilla::gfx::FontPaletteValueSet::PaletteValues* aValues, int32_t aIndex,
mozilla::StyleRGBA aColor);
// Visibility style
void Gecko_SetImageOrientation(nsStyleVisibility* aVisibility,
uint8_t aOrientation, bool aFlip);

View File

@ -4,6 +4,7 @@ headers = [
"mozilla/StyleAnimationValue.h",
"gfxFontConstants.h",
"gfxFontFeatures.h",
"COLRFonts.h",
"nsStyleConsts.h",
"mozilla/css/Loader.h",
"mozilla/css/SheetLoadData.h",
@ -234,6 +235,8 @@ allowlist-types = [
"mozilla::LookAndFeel",
"mozilla::gfx::Float",
"mozilla::gfx::FontVariation",
"mozilla::gfx::FontPaletteValueSet",
"mozilla::gfx::FontPaletteValueSet::PaletteValeus",
"mozilla::StyleImageLayerAttachment",
"gfxFontFeature",
"gfxFontVariation",

View File

@ -1225,6 +1225,14 @@ ServoStyleSet::BuildFontFeatureValueSet() {
return set.forget();
}
already_AddRefed<gfx::FontPaletteValueSet>
ServoStyleSet::BuildFontPaletteValueSet() {
MOZ_ASSERT(!StylistNeedsUpdate());
RefPtr<gfx::FontPaletteValueSet> set =
Servo_StyleSet_BuildFontPaletteValueSet(mRawSet.get());
return set.forget();
}
already_AddRefed<ComputedStyle> ServoStyleSet::ResolveForDeclarations(
const ComputedStyle* aParentOrNull,
const RawServoDeclarationBlock* aDeclarations) {

View File

@ -45,6 +45,9 @@ class CSSImportRule;
class Element;
class ShadowRoot;
} // namespace dom
namespace gfx {
class FontPaletteValueSet;
} // namespace gfx
class StyleSheet;
struct Keyframe;
class ServoElementSnapshotTable;
@ -366,6 +369,9 @@ class ServoStyleSet {
// Get all the currently-active font feature values set.
already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
// Get the set of all currently-active font-palette-values.
already_AddRefed<gfx::FontPaletteValueSet> BuildFontPaletteValueSet();
already_AddRefed<ComputedStyle> GetBaseContextForElement(
dom::Element* aElement, const ComputedStyle* aStyle);

View File

@ -8,6 +8,11 @@
use crate::error_reporting::ContextualParseError;
use crate::parser::{Parse, ParserContext};
use crate::gecko_bindings::bindings::Gecko_AppendPaletteValueHashEntry;
use crate::gecko_bindings::bindings::{Gecko_SetFontPaletteBase, Gecko_SetFontPaletteOverride};
use crate::gecko_bindings::structs::gfx::FontPaletteValueSet;
use crate::gecko_bindings::structs::gfx::FontPaletteValueSet_PaletteValues_kLight;
use crate::gecko_bindings::structs::gfx::FontPaletteValueSet_PaletteValues_kDark;
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use crate::str::CssStringWriter;
use crate::values::computed::font::FamilyName;
@ -152,6 +157,38 @@ impl FontPaletteValuesRule {
}
Ok(())
}
/// Convert to Gecko FontPaletteValueSet.
pub fn to_gecko_palette_value_set(&self, dest: *mut FontPaletteValueSet) {
for ref family in self.family_names.iter() {
let family = family.name.to_ascii_lowercase();
let palette_values = unsafe {
Gecko_AppendPaletteValueHashEntry(
dest,
family.as_ptr(),
self.name.0.as_ptr()
)
};
if let Some(base_palette) = &self.base_palette {
unsafe {
Gecko_SetFontPaletteBase(palette_values, match &base_palette {
FontPaletteBase::Light => FontPaletteValueSet_PaletteValues_kLight,
FontPaletteBase::Dark => FontPaletteValueSet_PaletteValues_kDark,
FontPaletteBase::Index(i) => i.0.value() as i32,
});
}
}
for c in &self.override_colors {
if let SpecifiedColor::Numeric { parsed, authored: _ } = &c.color {
unsafe {
Gecko_SetFontPaletteOverride(palette_values,
c.index.0.value(),
*parsed);
}
}
}
}
}
}
impl ToCssWithGuard for FontPaletteValuesRule {

View File

@ -309,6 +309,8 @@ renaming_overrides_prefixing = true
"ServoTraversalFlags" = "ServoTraversalFlags"
"ServoStyleSetSizes" = "ServoStyleSetSizes"
"BeforeFlag" = "StyleEasingBeforeFlag"
"FontPaletteValueSet" = "gfx::FontPaletteValueSet"
"PaletteValues" = "gfx::FontPaletteValueSet::PaletteValues"
[export.body]
"CSSPixelLength" = """

View File

@ -41,12 +41,14 @@ use style::gecko_bindings::bindings::nsAString;
use style::gecko_bindings::bindings::Gecko_AddPropertyToSet;
use style::gecko_bindings::bindings::Gecko_AppendPropertyValuePair;
use style::gecko_bindings::bindings::Gecko_ConstructFontFeatureValueSet;
use style::gecko_bindings::bindings::Gecko_ConstructFontPaletteValueSet;
use style::gecko_bindings::bindings::Gecko_GetOrCreateFinalKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::gfxFontFeatureValueSet;
use style::gecko_bindings::structs::gfx::FontPaletteValueSet;
use style::gecko_bindings::structs::ipc::ByteBuf;
use style::gecko_bindings::structs::nsAtom;
use style::gecko_bindings::structs::nsCSSCounterDesc;
@ -6557,7 +6559,36 @@ pub extern "C" fn Servo_StyleSet_BuildFontFeatureValueSet(
set
}
/// TODO FontPaletteValues?
#[no_mangle]
pub extern "C" fn Servo_StyleSet_BuildFontPaletteValueSet(
raw_data: &RawServoStyleSet,
) -> *mut FontPaletteValueSet {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let has_rule = data
.stylist
.iter_extra_data_origins()
.any(|(d, _)| !d.font_palette_values.is_empty());
if !has_rule {
return ptr::null_mut();
}
let font_palette_values_iter = data
.stylist
.iter_extra_data_origins_rev()
.flat_map(|(d, _)| d.font_palette_values.iter());
let set = unsafe { Gecko_ConstructFontPaletteValueSet() };
for &(ref src, _) in font_palette_values_iter {
let rule = src.read_with(&guard);
rule.to_gecko_palette_value_set(set);
}
set
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(