OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/css/ActiveStyleSheets.h" | 5 #include "core/css/ActiveStyleSheets.h" |
6 | 6 |
7 #include "core/css/CSSStyleSheet.h" | 7 #include "core/css/CSSStyleSheet.h" |
8 #include "core/css/RuleSet.h" | 8 #include "core/css/RuleSet.h" |
| 9 #include "core/css/resolver/ScopedStyleResolver.h" |
| 10 #include "core/dom/ContainerNode.h" |
| 11 #include "core/dom/StyleChangeReason.h" |
| 12 #include "core/dom/StyleEngine.h" |
9 | 13 |
10 namespace blink { | 14 namespace blink { |
11 | 15 |
12 ActiveSheetsChange compareActiveStyleSheets( | 16 ActiveSheetsChange compareActiveStyleSheets( |
13 const ActiveStyleSheetVector& oldStyleSheets, | 17 const ActiveStyleSheetVector& oldStyleSheets, |
14 const ActiveStyleSheetVector& newStyleSheets, | 18 const ActiveStyleSheetVector& newStyleSheets, |
15 HeapVector<Member<RuleSet>>& changedRuleSets) { | 19 HeapVector<Member<RuleSet>>& changedRuleSets) { |
16 unsigned newStyleSheetCount = newStyleSheets.size(); | 20 unsigned newStyleSheetCount = newStyleSheets.size(); |
17 unsigned oldStyleSheetCount = oldStyleSheets.size(); | 21 unsigned oldStyleSheetCount = oldStyleSheets.size(); |
18 | 22 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 // Active rules for the given stylesheet changed. | 96 // Active rules for the given stylesheet changed. |
93 // DOM, CSSOM, or media query changes. | 97 // DOM, CSSOM, or media query changes. |
94 if (sheet1.second) | 98 if (sheet1.second) |
95 changedRuleSets.append(sheet1.second); | 99 changedRuleSets.append(sheet1.second); |
96 if (sheet2.second) | 100 if (sheet2.second) |
97 changedRuleSets.append(sheet2.second); | 101 changedRuleSets.append(sheet2.second); |
98 } | 102 } |
99 return changedRuleSets.size() ? ActiveSheetsChanged : NoActiveSheetsChanged; | 103 return changedRuleSets.size() ? ActiveSheetsChanged : NoActiveSheetsChanged; |
100 } | 104 } |
101 | 105 |
| 106 namespace { |
| 107 |
| 108 enum RuleSetFlags { |
| 109 FontFaceRules = 1 << 0, |
| 110 KeyframesRules = 1 << 1, |
| 111 FullRecalcRules = 1 << 2 |
| 112 }; |
| 113 |
| 114 unsigned getRuleSetFlags(const HeapVector<Member<RuleSet>> ruleSets) { |
| 115 unsigned flags = 0; |
| 116 for (auto& ruleSet : ruleSets) { |
| 117 ruleSet->compactRulesIfNeeded(); |
| 118 if (!ruleSet->keyframesRules().isEmpty()) |
| 119 flags |= KeyframesRules; |
| 120 if (!ruleSet->fontFaceRules().isEmpty()) |
| 121 flags |= FontFaceRules; |
| 122 if (ruleSet->needsFullRecalcForRuleSetInvalidation()) |
| 123 flags |= FullRecalcRules; |
| 124 } |
| 125 return flags; |
| 126 } |
| 127 |
| 128 } // namespace |
| 129 |
| 130 void applyRuleSetChanges(StyleEngine& engine, |
| 131 TreeScope& treeScope, |
| 132 const ActiveStyleSheetVector& oldStyleSheets, |
| 133 const ActiveStyleSheetVector& newStyleSheets) { |
| 134 HeapVector<Member<RuleSet>> changedRuleSets; |
| 135 |
| 136 ActiveSheetsChange change = |
| 137 compareActiveStyleSheets(oldStyleSheets, newStyleSheets, changedRuleSets); |
| 138 if (change == NoActiveSheetsChanged) |
| 139 return; |
| 140 |
| 141 // TODO(rune@opera.com): engine.setNeedsGlobalRuleSetUpdate(); |
| 142 |
| 143 unsigned changedRuleFlags = getRuleSetFlags(changedRuleSets); |
| 144 bool fontsChanged = treeScope.rootNode().isDocumentNode() && |
| 145 (changedRuleFlags & FontFaceRules); |
| 146 unsigned appendStartIndex = 0; |
| 147 |
| 148 // We don't need to clear the font cache if new sheets are appended. |
| 149 if (fontsChanged && change == ActiveSheetsChanged) |
| 150 engine.clearFontCache(); |
| 151 |
| 152 // - If all sheets were removed, we remove the ScopedStyleResolver. |
| 153 // - If new sheets were appended to existing ones, start appending after the |
| 154 // common prefix. |
| 155 // - For other diffs, reset author style and re-add all sheets for the |
| 156 // TreeScope. |
| 157 if (treeScope.scopedStyleResolver()) { |
| 158 if (newStyleSheets.isEmpty()) |
| 159 treeScope.clearScopedStyleResolver(); |
| 160 else if (change == ActiveSheetsAppended) |
| 161 appendStartIndex = oldStyleSheets.size(); |
| 162 else |
| 163 treeScope.scopedStyleResolver()->resetAuthorStyle(); |
| 164 } |
| 165 |
| 166 if (!newStyleSheets.isEmpty()) { |
| 167 treeScope.ensureScopedStyleResolver().appendActiveStyleSheets( |
| 168 appendStartIndex, newStyleSheets); |
| 169 } |
| 170 |
| 171 if (treeScope.document().hasPendingForcedStyleRecalc()) |
| 172 return; |
| 173 |
| 174 if (!treeScope.document().body() || |
| 175 treeScope.document().hasNodesWithPlaceholderStyle()) { |
| 176 treeScope.document().setNeedsStyleRecalc( |
| 177 SubtreeStyleChange, StyleChangeReasonForTracing::create( |
| 178 StyleChangeReason::CleanupPlaceholderStyles)); |
| 179 return; |
| 180 } |
| 181 |
| 182 if (changedRuleFlags & KeyframesRules) |
| 183 ScopedStyleResolver::keyframesRulesAdded(treeScope); |
| 184 |
| 185 if (fontsChanged || (changedRuleFlags & FullRecalcRules)) { |
| 186 ScopedStyleResolver::invalidationRootForTreeScope(treeScope) |
| 187 .setNeedsStyleRecalc(SubtreeStyleChange, |
| 188 StyleChangeReasonForTracing::create( |
| 189 StyleChangeReason::ActiveStylesheetsUpdate)); |
| 190 return; |
| 191 } |
| 192 |
| 193 engine.scheduleInvalidationsForRuleSets(treeScope, changedRuleSets); |
| 194 } |
| 195 |
102 } // namespace blink | 196 } // namespace blink |
OLD | NEW |