зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1664372 - Fix font loading invalidation to account for metrics coming from the parent style. r=jfkthame
We were only looking at the given frame's style, which is not sufficient for this case. Differential Revision: https://phabricator.services.mozilla.com/D96237
This commit is contained in:
Родитель
1a3ae2644d
Коммит
8bd419268c
|
@ -152,10 +152,15 @@ class ComputedStyle {
|
|||
// only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText().
|
||||
bool IsTextCombined() const { return bool(Flags() & Flag::IS_TEXT_COMBINED); }
|
||||
|
||||
// Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
|
||||
// only set on ComputedStyles whose pseudo is nsCSSAnonBoxes::mozText().
|
||||
bool DependsOnFontMetrics() const {
|
||||
return bool(Flags() & Flag::DEPENDS_ON_FONT_METRICS);
|
||||
// Whether there's any font metric dependency coming directly from our style.
|
||||
bool DependsOnSelfFontMetrics() const {
|
||||
return bool(Flags() & Flag::DEPENDS_ON_SELF_FONT_METRICS);
|
||||
}
|
||||
|
||||
// Whether there's any font metric dependency coming directly from our parent
|
||||
// style.
|
||||
bool DependsOnInheritedFontMetrics() const {
|
||||
return bool(Flags() & Flag::DEPENDS_ON_INHERITED_FONT_METRICS);
|
||||
}
|
||||
|
||||
// Does this ComputedStyle represent the style for a pseudo-element or
|
||||
|
|
|
@ -24,40 +24,67 @@ enum class FontUsageKind {
|
|||
None = 0,
|
||||
// The frame uses the given font, but doesn't use font-metric-dependent units,
|
||||
// which means that its style doesn't depend on this font.
|
||||
Frame,
|
||||
// The frame uses this font and also has some font-metric-dependent units.
|
||||
Frame = 1 << 0,
|
||||
// The frame uses has some font-metric-dependent units on this font.
|
||||
// This means that its style depends on this font, and we need to restyle the
|
||||
// element the frame came from.
|
||||
FrameAndFontMetrics,
|
||||
FontMetrics = 1 << 1,
|
||||
|
||||
Max = Frame | FontMetrics,
|
||||
};
|
||||
|
||||
static FontUsageKind StyleFontUsage(ComputedStyle* aComputedStyle,
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(FontUsageKind);
|
||||
|
||||
static FontUsageKind StyleFontUsage(nsIFrame* aFrame, ComputedStyle* aStyle,
|
||||
nsPresContext* aPresContext,
|
||||
const gfxUserFontSet* aUserFontSet,
|
||||
const gfxUserFontEntry* aFont,
|
||||
const nsAString& aFamilyName) {
|
||||
const nsAString& aFamilyName,
|
||||
bool aIsExtraStyle) {
|
||||
MOZ_ASSERT(NS_ConvertUTF8toUTF16(aFont->FamilyName()) == aFamilyName);
|
||||
|
||||
// first, check if the family name is in the fontlist
|
||||
if (!aComputedStyle->StyleFont()->mFont.fontlist.Contains(aFamilyName)) {
|
||||
return FontUsageKind::None;
|
||||
auto FontIsUsed = [&aFont, &aPresContext,
|
||||
&aFamilyName](ComputedStyle* aStyle) {
|
||||
if (!aStyle->StyleFont()->mFont.fontlist.Contains(aFamilyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// family name is in the fontlist, check to see if the font group
|
||||
// associated with the frame includes the specific userfont.
|
||||
//
|
||||
// TODO(emilio): Is this check really useful? I guess it's useful for
|
||||
// different font faces of the same font?
|
||||
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForComputedStyle(
|
||||
aStyle, aPresContext, 1.0f);
|
||||
return fm->GetThebesFontGroup()->ContainsUserFont(aFont);
|
||||
};
|
||||
|
||||
auto usage = FontUsageKind::None;
|
||||
|
||||
if (FontIsUsed(aStyle)) {
|
||||
usage |= FontUsageKind::Frame;
|
||||
if (aStyle->DependsOnSelfFontMetrics()) {
|
||||
MOZ_ASSERT(aPresContext->UsesExChUnits());
|
||||
usage |= FontUsageKind::FontMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
// family name is in the fontlist, check to see if the font group
|
||||
// associated with the frame includes the specific userfont
|
||||
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForComputedStyle(
|
||||
aComputedStyle, aPresContext, 1.0f);
|
||||
|
||||
if (!fm->GetThebesFontGroup()->ContainsUserFont(aFont)) {
|
||||
return FontUsageKind::None;
|
||||
}
|
||||
|
||||
if (aComputedStyle->DependsOnFontMetrics()) {
|
||||
if (aStyle->DependsOnInheritedFontMetrics() &&
|
||||
!(usage & FontUsageKind::FontMetrics)) {
|
||||
MOZ_ASSERT(aPresContext->UsesExChUnits());
|
||||
return FontUsageKind::FrameAndFontMetrics;
|
||||
ComputedStyle* parentStyle = nullptr;
|
||||
if (aIsExtraStyle) {
|
||||
parentStyle = aFrame->Style();
|
||||
} else {
|
||||
nsIFrame* provider = nullptr;
|
||||
parentStyle = aFrame->GetParentComputedStyle(&provider);
|
||||
}
|
||||
|
||||
if (parentStyle && FontIsUsed(parentStyle)) {
|
||||
usage |= FontUsageKind::FontMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
return FontUsageKind::Frame;
|
||||
return usage;
|
||||
}
|
||||
|
||||
static FontUsageKind FrameFontUsage(nsIFrame* aFrame,
|
||||
|
@ -65,10 +92,9 @@ static FontUsageKind FrameFontUsage(nsIFrame* aFrame,
|
|||
const gfxUserFontEntry* aFont,
|
||||
const nsAString& aFamilyName) {
|
||||
// check the style of the frame
|
||||
gfxUserFontSet* ufs = aPresContext->GetUserFontSet();
|
||||
FontUsageKind kind =
|
||||
StyleFontUsage(aFrame->Style(), aPresContext, ufs, aFont, aFamilyName);
|
||||
if (kind == FontUsageKind::FrameAndFontMetrics) {
|
||||
FontUsageKind kind = StyleFontUsage(aFrame, aFrame->Style(), aPresContext,
|
||||
aFont, aFamilyName, /* extra = */ false);
|
||||
if (kind == FontUsageKind::Max) {
|
||||
return kind;
|
||||
}
|
||||
|
||||
|
@ -77,9 +103,9 @@ static FontUsageKind FrameFontUsage(nsIFrame* aFrame,
|
|||
for (ComputedStyle* extraContext;
|
||||
(extraContext = aFrame->GetAdditionalComputedStyle(contextIndex));
|
||||
++contextIndex) {
|
||||
kind = std::max(kind, StyleFontUsage(extraContext, aPresContext, ufs, aFont,
|
||||
aFamilyName));
|
||||
if (kind == FontUsageKind::FrameAndFontMetrics) {
|
||||
kind |= StyleFontUsage(aFrame, extraContext, aPresContext, aFont,
|
||||
aFamilyName, /* extra = */ true);
|
||||
if (kind == FontUsageKind::Max) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -160,11 +186,12 @@ void nsFontFaceUtils::MarkDirtyForFontChange(nsIFrame* aSubtreeRoot,
|
|||
// and skip checking its children
|
||||
FontUsageKind kind = FrameFontUsage(f, pc, aFont, familyName);
|
||||
if (kind != FontUsageKind::None) {
|
||||
if (alreadyScheduled == ReflowAlreadyScheduled::No) {
|
||||
if ((kind & FontUsageKind::Frame) &&
|
||||
alreadyScheduled == ReflowAlreadyScheduled::No) {
|
||||
ScheduleReflow(presShell, f);
|
||||
alreadyScheduled = ReflowAlreadyScheduled::Yes;
|
||||
}
|
||||
if (kind == FontUsageKind::FrameAndFontMetrics) {
|
||||
if (kind & FontUsageKind::FontMetrics) {
|
||||
MOZ_ASSERT(f->GetContent() && f->GetContent()->IsElement(),
|
||||
"How could we target a non-element with selectors?");
|
||||
f->PresContext()->RestyleManager()->PostRestyleEvent(
|
||||
|
|
|
@ -57,19 +57,24 @@ bitflags! {
|
|||
/// Whether the child explicitly inherits any reset property.
|
||||
const INHERITS_RESET_STYLE = 1 << 8;
|
||||
|
||||
/// Whether any value on our style is font-metric-dependent.
|
||||
const DEPENDS_ON_FONT_METRICS = 1 << 9;
|
||||
/// Whether any value on our style is font-metric-dependent on our
|
||||
/// primary font.
|
||||
const DEPENDS_ON_SELF_FONT_METRICS = 1 << 9;
|
||||
|
||||
/// Whether any value on our style is font-metric-dependent on the
|
||||
/// primary font of our parent.
|
||||
const DEPENDS_ON_INHERITED_FONT_METRICS = 1 << 10;
|
||||
|
||||
/// Whether the style or any of the ancestors has a multicol style.
|
||||
///
|
||||
/// Only used in Servo.
|
||||
const CAN_BE_FRAGMENTED = 1 << 10;
|
||||
const CAN_BE_FRAGMENTED = 1 << 11;
|
||||
|
||||
/// Whether this style is the style of the document element.
|
||||
const IS_ROOT_ELEMENT_STYLE = 1 << 11;
|
||||
const IS_ROOT_ELEMENT_STYLE = 1 << 12;
|
||||
|
||||
/// Whether this element is inside an `opacity: 0` subtree.
|
||||
const IS_IN_OPACITY_ZERO_SUBTREE = 1 << 12;
|
||||
const IS_IN_OPACITY_ZERO_SUBTREE = 1 << 13;
|
||||
|
||||
/// Whether there are author-specified rules for border-* properties
|
||||
/// (except border-image-*), background-color, or background-image.
|
||||
|
@ -77,13 +82,13 @@ bitflags! {
|
|||
/// TODO(emilio): Maybe do include border-image, see:
|
||||
///
|
||||
/// https://github.com/w3c/csswg-drafts/issues/4777#issuecomment-604424845
|
||||
const HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND = 1 << 13;
|
||||
const HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND = 1 << 14;
|
||||
|
||||
/// Whether there are author-specified rules for padding-* properties.
|
||||
///
|
||||
/// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see
|
||||
/// https://github.com/w3c/csswg-drafts/issues/4777
|
||||
const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 14;
|
||||
const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 15;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ impl FontRelativeLength {
|
|||
}
|
||||
|
||||
let reference_font_size = base_size.resolve(context);
|
||||
let font_metrics_flag = match base_size {
|
||||
FontBaseSize::CurrentStyle => ComputedValueFlags::DEPENDS_ON_SELF_FONT_METRICS,
|
||||
FontBaseSize::InheritedStyle => ComputedValueFlags::DEPENDS_ON_INHERITED_FONT_METRICS,
|
||||
};
|
||||
match *self {
|
||||
FontRelativeLength::Em(length) => {
|
||||
if context.for_non_inherited_property.is_some() {
|
||||
|
@ -178,9 +182,7 @@ impl FontRelativeLength {
|
|||
if context.for_non_inherited_property.is_some() {
|
||||
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
||||
}
|
||||
context
|
||||
.builder
|
||||
.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS);
|
||||
context.builder.add_flags(font_metrics_flag);
|
||||
// The x-height is an intrinsically horizontal metric.
|
||||
let metrics =
|
||||
query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal);
|
||||
|
@ -199,9 +201,7 @@ impl FontRelativeLength {
|
|||
if context.for_non_inherited_property.is_some() {
|
||||
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
||||
}
|
||||
context
|
||||
.builder
|
||||
.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS);
|
||||
context.builder.add_flags(font_metrics_flag);
|
||||
// https://drafts.csswg.org/css-values/#ch:
|
||||
//
|
||||
// Equal to the used advance measure of the “0” (ZERO,
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
[ch-pseudo-recalc-on-font-load.html]
|
||||
[ch in pseudo-element ::marker should be recalculated after loading a web font]
|
||||
expected:
|
||||
if (os == "win") and webrender and not debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and webrender and debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86"): ["FAIL", "PASS"]
|
||||
if (os == "linux") and not webrender and (processor == "x86_64"): ["PASS", "FAIL"]
|
||||
if os == "mac": ["PASS", "FAIL"]
|
||||
|
||||
[ch in pseudo-element ::after should be recalculated after loading a web font]
|
||||
expected:
|
||||
if (os == "win") and webrender and not debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and webrender and debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86_64"): ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86"): ["FAIL", "PASS"]
|
||||
if os == "mac": ["PASS", "FAIL"]
|
||||
|
||||
[ch in pseudo-element ::first-line should be recalculated after loading a web font]
|
||||
expected:
|
||||
if (os == "linux") and webrender and debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "win") and webrender and not debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86_64"): ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86"): ["FAIL", "PASS"]
|
||||
if os == "mac": ["PASS", "FAIL"]
|
||||
|
||||
[ch in pseudo-element ::before should be recalculated after loading a web font]
|
||||
expected:
|
||||
if (os == "linux") and webrender and debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "win") and webrender and not debug and not fission: ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86_64"): ["PASS", "FAIL"]
|
||||
if (os == "linux") and not webrender and (processor == "x86"): ["FAIL", "PASS"]
|
||||
if os == "mac": ["PASS", "FAIL"]
|
||||
|
Загрузка…
Ссылка в новой задаче