Commit fc7ea76f authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Unify invalidation code paths for font-face rule changes and font loading

Currently, there are two different invalidation code paths for font-face
related changes:

1. Via FontSelector::FontFaceInvalidated(). This is called when:
- The loading status of a font changes
- A FontFace is changed via the JavaScript API

This code path also allows partial style invalidation when the feature
CSSReducedFontLoadingInvalidations is enabled; Otherwise, it marks the
full document's style as dirty.

2. Via StyleEngine::InvalidateForRuleSetChanges(). This is called when
StyleEngine identifies changes in the active @font-face rules. It marks
the full document's style as dirty.

This patch makes (2) to also use FontSelector::FontFaceInvalidated() to
update style and layout, instead of directly marking full document style
dirty. As a result:

- When the feature is enabled, @font-face rule changes don't need full
  document style recalc

- We no longer need to compare FontSelector versions in style diff. This
  is required by partial layout recalc for font loading

- There is no essential behavioral change when the feature is disabled,
  since in that case both code paths mark style dirty on the full doc

Note: there's also a renaming to certain variables & functions to make
code more readable, since what they actually rebuild is FontFaceCache
instead of FontCache.

Bug: 441925
Change-Id: I5207e99fdb7e610bcdedc4c7b3615b0c13b69c6b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2147687Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759124}
parent 431a687b
...@@ -470,8 +470,12 @@ TEST_F(ApplyRulesetsTest, AddFontFaceRuleToDocument) { ...@@ -470,8 +470,12 @@ TEST_F(ApplyRulesetsTest, AddFontFaceRuleToDocument) {
GetStyleEngine().ApplyRuleSetChanges(GetDocument(), ActiveStyleSheetVector(), GetStyleEngine().ApplyRuleSetChanges(GetDocument(), ActiveStyleSheetVector(),
new_style_sheets); new_style_sheets);
EXPECT_EQ(kSubtreeStyleChange, StyleChangeType expected =
GetDocument().documentElement()->GetStyleChangeType()); RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()
? kNoStyleChange
: kSubtreeStyleChange;
EXPECT_EQ(expected, GetDocument().documentElement()->GetStyleChangeType());
} }
TEST_F(ApplyRulesetsTest, AddFontFaceRuleToShadowTree) { TEST_F(ApplyRulesetsTest, AddFontFaceRuleToShadowTree) {
......
...@@ -738,7 +738,7 @@ void StyleEngine::DidDetach() { ...@@ -738,7 +738,7 @@ void StyleEngine::DidDetach() {
environment_variables_ = nullptr; environment_variables_ = nullptr;
} }
bool StyleEngine::ClearFontCacheAndAddUserFonts() { bool StyleEngine::ClearFontFaceCacheAndAddUserFonts() {
bool fonts_changed = false; bool fonts_changed = false;
if (font_selector_ && if (font_selector_ &&
...@@ -1515,29 +1515,18 @@ unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) { ...@@ -1515,29 +1515,18 @@ unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
return flags; return flags;
} }
bool NeedsFullRecalcForRuleSetChanges(TreeScope& tree_scope,
unsigned changed_rule_flags,
bool has_rebuilt_font_cache) {
if (changed_rule_flags & kFullRecalcRules)
return true;
if (!tree_scope.RootNode().IsDocumentNode())
return false;
return (changed_rule_flags & kFontFaceRules) || has_rebuilt_font_cache;
}
} // namespace } // namespace
void StyleEngine::InvalidateForRuleSetChanges( void StyleEngine::InvalidateForRuleSetChanges(
TreeScope& tree_scope, TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets, const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags, unsigned changed_rule_flags,
InvalidationScope invalidation_scope, InvalidationScope invalidation_scope) {
bool has_rebuilt_font_cache) {
if (tree_scope.GetDocument().HasPendingForcedStyleRecalc()) if (tree_scope.GetDocument().HasPendingForcedStyleRecalc())
return; return;
if (!tree_scope.GetDocument().documentElement()) if (!tree_scope.GetDocument().documentElement())
return; return;
if (changed_rule_sets.IsEmpty() && !has_rebuilt_font_cache) if (changed_rule_sets.IsEmpty())
return; return;
Element& invalidation_root = Element& invalidation_root =
...@@ -1545,8 +1534,7 @@ void StyleEngine::InvalidateForRuleSetChanges( ...@@ -1545,8 +1534,7 @@ void StyleEngine::InvalidateForRuleSetChanges(
if (invalidation_root.GetStyleChangeType() == kSubtreeStyleChange) if (invalidation_root.GetStyleChangeType() == kSubtreeStyleChange)
return; return;
if (NeedsFullRecalcForRuleSetChanges(tree_scope, changed_rule_flags, if (changed_rule_flags & kFullRecalcRules) {
has_rebuilt_font_cache)) {
invalidation_root.SetNeedsStyleRecalc( invalidation_root.SetNeedsStyleRecalc(
kSubtreeStyleChange, kSubtreeStyleChange,
StyleChangeReasonForTracing::Create( StyleChangeReasonForTracing::Create(
...@@ -1581,7 +1569,7 @@ void StyleEngine::ApplyUserRuleSetChanges( ...@@ -1581,7 +1569,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
global_rule_set_->MarkDirty(); global_rule_set_->MarkDirty();
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets); unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
bool has_rebuilt_font_cache = false; bool has_rebuilt_font_face_cache = false;
if (changed_rule_flags & kFontFaceRules) { if (changed_rule_flags & kFontFaceRules) {
if (ScopedStyleResolver* scoped_resolver = if (ScopedStyleResolver* scoped_resolver =
GetDocument().GetScopedStyleResolver()) { GetDocument().GetScopedStyleResolver()) {
...@@ -1592,7 +1580,7 @@ void StyleEngine::ApplyUserRuleSetChanges( ...@@ -1592,7 +1580,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
scoped_resolver->SetNeedsAppendAllSheets(); scoped_resolver->SetNeedsAppendAllSheets();
MarkDocumentDirty(); MarkDocumentDirty();
} else { } else {
has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts(); has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
} }
} }
...@@ -1608,9 +1596,11 @@ void StyleEngine::ApplyUserRuleSetChanges( ...@@ -1608,9 +1596,11 @@ void StyleEngine::ApplyUserRuleSetChanges(
ScopedStyleResolver::KeyframesRulesAdded(GetDocument()); ScopedStyleResolver::KeyframesRulesAdded(GetDocument());
} }
if ((changed_rule_flags & kFontFaceRules) || has_rebuilt_font_face_cache)
GetFontSelector()->FontFaceInvalidated();
InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets, InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets,
changed_rule_flags, kInvalidateAllScopes, changed_rule_flags, kInvalidateAllScopes);
has_rebuilt_font_cache);
} }
void StyleEngine::ApplyRuleSetChanges( void StyleEngine::ApplyRuleSetChanges(
...@@ -1626,12 +1616,12 @@ void StyleEngine::ApplyRuleSetChanges( ...@@ -1626,12 +1616,12 @@ void StyleEngine::ApplyRuleSetChanges(
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets); unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
bool rebuild_font_cache = change == kActiveSheetsChanged && bool rebuild_font_face_cache = change == kActiveSheetsChanged &&
(changed_rule_flags & kFontFaceRules) && (changed_rule_flags & kFontFaceRules) &&
tree_scope.RootNode().IsDocumentNode(); tree_scope.RootNode().IsDocumentNode();
ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver(); ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) { if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) {
rebuild_font_cache = true; rebuild_font_face_cache = true;
change = kActiveSheetsChanged; change = kActiveSheetsChanged;
} }
...@@ -1658,9 +1648,9 @@ void StyleEngine::ApplyRuleSetChanges( ...@@ -1658,9 +1648,9 @@ void StyleEngine::ApplyRuleSetChanges(
} }
} }
bool has_rebuilt_font_cache = false; bool has_rebuilt_font_face_cache = false;
if (rebuild_font_cache) if (rebuild_font_face_cache)
has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts(); has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
unsigned append_start_index = 0; unsigned append_start_index = 0;
if (scoped_resolver) { if (scoped_resolver) {
...@@ -1682,8 +1672,13 @@ void StyleEngine::ApplyRuleSetChanges( ...@@ -1682,8 +1672,13 @@ void StyleEngine::ApplyRuleSetChanges(
append_start_index, new_style_sheets); append_start_index, new_style_sheets);
} }
if (tree_scope.RootNode().IsDocumentNode()) {
if ((changed_rule_flags & kFontFaceRules) || has_rebuilt_font_face_cache)
GetFontSelector()->FontFaceInvalidated();
}
InvalidateForRuleSetChanges(tree_scope, changed_rule_sets, changed_rule_flags, InvalidateForRuleSetChanges(tree_scope, changed_rule_sets, changed_rule_flags,
kInvalidateCurrentScope, has_rebuilt_font_cache); kInvalidateCurrentScope);
} }
void StyleEngine::LoadVisionDeficiencyFilter() { void StyleEngine::LoadVisionDeficiencyFilter() {
......
...@@ -464,8 +464,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>, ...@@ -464,8 +464,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
TreeScope& tree_scope, TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets, const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags, unsigned changed_rule_flags,
InvalidationScope invalidation_scope, InvalidationScope invalidation_scope);
bool rebuild_font_cache);
void InvalidateInitialData(); void InvalidateInitialData();
void UpdateViewport(); void UpdateViewport();
...@@ -480,7 +479,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>, ...@@ -480,7 +479,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
void UpdateStyleSheetList(TreeScope&); void UpdateStyleSheetList(TreeScope&);
// Returns true if any @font-face rules are added or removed. // Returns true if any @font-face rules are added or removed.
bool ClearFontCacheAndAddUserFonts(); bool ClearFontFaceCacheAndAddUserFonts();
void ClearKeyframeRules() { keyframes_rule_map_.clear(); } void ClearKeyframeRules() { keyframes_rule_map_.clear(); }
void ClearPropertyRules(); void ClearPropertyRules();
......
...@@ -65,6 +65,20 @@ Font& Font::operator=(const Font& other) { ...@@ -65,6 +65,20 @@ Font& Font::operator=(const Font& other) {
return *this; return *this;
} }
namespace {
bool FontFallbackListVersionEqual(const FontFallbackList* first,
const FontFallbackList* second) {
if (RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled())
return true;
return (first ? first->FontSelectorVersion() : 0) ==
(second ? second->FontSelectorVersion() : 0) &&
(first ? first->Generation() : 0) ==
(second ? second->Generation() : 0);
}
} // namespace
bool Font::operator==(const Font& other) const { bool Font::operator==(const Font& other) const {
FontSelector* first = FontSelector* first =
font_fallback_list_ ? font_fallback_list_->GetFontSelector() : nullptr; font_fallback_list_ ? font_fallback_list_->GetFontSelector() : nullptr;
...@@ -73,15 +87,8 @@ bool Font::operator==(const Font& other) const { ...@@ -73,15 +87,8 @@ bool Font::operator==(const Font& other) const {
: nullptr; : nullptr;
return first == second && font_description_ == other.font_description_ && return first == second && font_description_ == other.font_description_ &&
(font_fallback_list_ FontFallbackListVersionEqual(font_fallback_list_.get(),
? font_fallback_list_->FontSelectorVersion() other.font_fallback_list_.get());
: 0) == (other.font_fallback_list_
? other.font_fallback_list_->FontSelectorVersion()
: 0) &&
(font_fallback_list_ ? font_fallback_list_->Generation() : 0) ==
(other.font_fallback_list_
? other.font_fallback_list_->Generation()
: 0);
} }
namespace { namespace {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment