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) {
GetStyleEngine().ApplyRuleSetChanges(GetDocument(), ActiveStyleSheetVector(),
new_style_sheets);
EXPECT_EQ(kSubtreeStyleChange,
GetDocument().documentElement()->GetStyleChangeType());
StyleChangeType expected =
RuntimeEnabledFeatures::CSSReducedFontLoadingInvalidationsEnabled()
? kNoStyleChange
: kSubtreeStyleChange;
EXPECT_EQ(expected, GetDocument().documentElement()->GetStyleChangeType());
}
TEST_F(ApplyRulesetsTest, AddFontFaceRuleToShadowTree) {
......
......@@ -738,7 +738,7 @@ void StyleEngine::DidDetach() {
environment_variables_ = nullptr;
}
bool StyleEngine::ClearFontCacheAndAddUserFonts() {
bool StyleEngine::ClearFontFaceCacheAndAddUserFonts() {
bool fonts_changed = false;
if (font_selector_ &&
......@@ -1515,29 +1515,18 @@ unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
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
void StyleEngine::InvalidateForRuleSetChanges(
TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags,
InvalidationScope invalidation_scope,
bool has_rebuilt_font_cache) {
InvalidationScope invalidation_scope) {
if (tree_scope.GetDocument().HasPendingForcedStyleRecalc())
return;
if (!tree_scope.GetDocument().documentElement())
return;
if (changed_rule_sets.IsEmpty() && !has_rebuilt_font_cache)
if (changed_rule_sets.IsEmpty())
return;
Element& invalidation_root =
......@@ -1545,8 +1534,7 @@ void StyleEngine::InvalidateForRuleSetChanges(
if (invalidation_root.GetStyleChangeType() == kSubtreeStyleChange)
return;
if (NeedsFullRecalcForRuleSetChanges(tree_scope, changed_rule_flags,
has_rebuilt_font_cache)) {
if (changed_rule_flags & kFullRecalcRules) {
invalidation_root.SetNeedsStyleRecalc(
kSubtreeStyleChange,
StyleChangeReasonForTracing::Create(
......@@ -1581,7 +1569,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
global_rule_set_->MarkDirty();
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 (ScopedStyleResolver* scoped_resolver =
GetDocument().GetScopedStyleResolver()) {
......@@ -1592,7 +1580,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
scoped_resolver->SetNeedsAppendAllSheets();
MarkDocumentDirty();
} else {
has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts();
has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
}
}
......@@ -1608,9 +1596,11 @@ void StyleEngine::ApplyUserRuleSetChanges(
ScopedStyleResolver::KeyframesRulesAdded(GetDocument());
}
if ((changed_rule_flags & kFontFaceRules) || has_rebuilt_font_face_cache)
GetFontSelector()->FontFaceInvalidated();
InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets,
changed_rule_flags, kInvalidateAllScopes,
has_rebuilt_font_cache);
changed_rule_flags, kInvalidateAllScopes);
}
void StyleEngine::ApplyRuleSetChanges(
......@@ -1626,12 +1616,12 @@ void StyleEngine::ApplyRuleSetChanges(
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) &&
tree_scope.RootNode().IsDocumentNode();
ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) {
rebuild_font_cache = true;
rebuild_font_face_cache = true;
change = kActiveSheetsChanged;
}
......@@ -1658,9 +1648,9 @@ void StyleEngine::ApplyRuleSetChanges(
}
}
bool has_rebuilt_font_cache = false;
if (rebuild_font_cache)
has_rebuilt_font_cache = ClearFontCacheAndAddUserFonts();
bool has_rebuilt_font_face_cache = false;
if (rebuild_font_face_cache)
has_rebuilt_font_face_cache = ClearFontFaceCacheAndAddUserFonts();
unsigned append_start_index = 0;
if (scoped_resolver) {
......@@ -1682,8 +1672,13 @@ void StyleEngine::ApplyRuleSetChanges(
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,
kInvalidateCurrentScope, has_rebuilt_font_cache);
kInvalidateCurrentScope);
}
void StyleEngine::LoadVisionDeficiencyFilter() {
......
......@@ -464,8 +464,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
TreeScope& tree_scope,
const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
unsigned changed_rule_flags,
InvalidationScope invalidation_scope,
bool rebuild_font_cache);
InvalidationScope invalidation_scope);
void InvalidateInitialData();
void UpdateViewport();
......@@ -480,7 +479,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
void UpdateStyleSheetList(TreeScope&);
// Returns true if any @font-face rules are added or removed.
bool ClearFontCacheAndAddUserFonts();
bool ClearFontFaceCacheAndAddUserFonts();
void ClearKeyframeRules() { keyframes_rule_map_.clear(); }
void ClearPropertyRules();
......
......@@ -65,6 +65,20 @@ Font& Font::operator=(const Font& other) {
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 {
FontSelector* first =
font_fallback_list_ ? font_fallback_list_->GetFontSelector() : nullptr;
......@@ -73,15 +87,8 @@ bool Font::operator==(const Font& other) const {
: nullptr;
return first == second && font_description_ == other.font_description_ &&
(font_fallback_list_
? font_fallback_list_->FontSelectorVersion()
: 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);
FontFallbackListVersionEqual(font_fallback_list_.get(),
other.font_fallback_list_.get());
}
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