void ShadowTreeStyleSheetCollection::updateActiveStyleSheets(StyleEngine* engine, StyleResolverUpdateMode updateMode) { StyleSheetCollection collection; collectStyleSheets(engine, collection); StyleSheetChange change; analyzeStyleSheetChange(updateMode, collection, change); if (StyleResolver* styleResolver = engine->resolver()) { if (change.styleResolverUpdateType != Additive) { // We should not destroy StyleResolver when we find any stylesheet update in a shadow tree. // In this case, we will reset rulesets created from style elements in the shadow tree. styleResolver->resetAuthorStyle(treeScope()); styleResolver->removePendingAuthorStyleSheets(m_activeAuthorStyleSheets); styleResolver->lazyAppendAuthorStyleSheets(0, collection.activeAuthorStyleSheets()); } else { styleResolver->lazyAppendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), collection.activeAuthorStyleSheets()); } } if (change.requiresFullStyleRecalc) toShadowRoot(treeScope().rootNode()).host()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::ActiveStylesheetsUpdate)); collection.swap(*this); updateUsesRemUnits(); }
void DocumentStyleSheetCollection::updateActiveStyleSheets(StyleEngine* engine, StyleResolverUpdateMode updateMode) { StyleSheetCollection collection; ActiveDocumentStyleSheetCollector collector(collection); collectStyleSheets(engine, collector); StyleSheetChange change; analyzeStyleSheetChange(updateMode, collection, change); if (change.styleResolverUpdateType == Reconstruct) { engine->clearMasterResolver(); // FIMXE: The following depends on whether StyleRuleFontFace was modified or not. // No need to always-clear font cache. engine->clearFontCache(); } else if (StyleResolver* styleResolver = engine->resolver()) { if (change.styleResolverUpdateType != Additive) { ASSERT(change.styleResolverUpdateType == Reset); styleResolver->resetAuthorStyle(treeScope()); engine->removeFontFaceRules(change.fontFaceRulesToRemove); styleResolver->removePendingAuthorStyleSheets(m_activeAuthorStyleSheets); styleResolver->lazyAppendAuthorStyleSheets(0, collection.activeAuthorStyleSheets()); } else { styleResolver->lazyAppendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), collection.activeAuthorStyleSheets()); } } if (change.requiresFullStyleRecalc) document().setNeedsStyleRecalc(SubtreeStyleChange); collection.swap(*this); updateUsesRemUnits(); }
void TreeScopeStyleSheetCollection::analyzeStyleSheetChange(StyleResolverUpdateMode updateMode, const StyleSheetCollection& newCollection, StyleSheetChange& change) { if (activeLoadingStyleSheetLoaded(newCollection.activeAuthorStyleSheets())) return; if (updateMode != AnalyzedStyleUpdate) return; // Find out which stylesheets are new. WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents>> addedSheets; if (m_activeAuthorStyleSheets.size() <= newCollection.activeAuthorStyleSheets().size()) { change.styleResolverUpdateType = compareStyleSheets(m_activeAuthorStyleSheets, newCollection.activeAuthorStyleSheets(), addedSheets); } else { StyleResolverUpdateType updateType = compareStyleSheets(newCollection.activeAuthorStyleSheets(), m_activeAuthorStyleSheets, addedSheets); if (updateType != Additive) { change.styleResolverUpdateType = updateType; } else { change.styleResolverUpdateType = Reset; // If @font-face is removed, needs full style recalc. if (findFontFaceRulesFromStyleSheetContents(addedSheets, change.fontFaceRulesToRemove)) return; } } // FIXME: If styleResolverUpdateType is Reconstruct, we should return early here since // we need to recalc the whole document. It's wrong to use StyleSheetInvalidationAnalysis since // it only looks at the addedSheets. // No point in doing the analysis work if we're just going to recalc the whole document anyways. // This needs to be done after the compareStyleSheets calls above to ensure we don't throw away // the StyleResolver if we don't need to. if (document().hasPendingForcedStyleRecalc()) return; // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs. if (!document().body() || document().hasNodesWithPlaceholderStyle()) return; StyleSheetInvalidationAnalysis invalidationAnalysis(addedSheets); if (invalidationAnalysis.dirtiesAllStyle()) return; invalidationAnalysis.invalidateStyle(document()); change.requiresFullStyleRecalc = false; return; }
void ShadowTreeStyleSheetCollection::collectStyleSheets(StyleEngine* engine, StyleSheetCollection& collection) { DocumentOrderedList::iterator begin = m_styleSheetCandidateNodes.begin(); DocumentOrderedList::iterator end = m_styleSheetCandidateNodes.end(); for (DocumentOrderedList::iterator it = begin; it != end; ++it) { Node* node = *it; StyleSheet* sheet = 0; CSSStyleSheet* activeSheet = 0; if (!isHTMLStyleElement(*node)) continue; HTMLStyleElement* element = toHTMLStyleElement(node); const AtomicString& title = element->fastGetAttribute(titleAttr); bool enabledViaScript = false; sheet = element->sheet(); if (sheet && !sheet->disabled() && sheet->isCSSStyleSheet()) activeSheet = toCSSStyleSheet(sheet); // FIXME: clarify how PREFERRED or ALTERNATE works in shadow trees. // Should we set preferred/selected stylesheets name in shadow trees and // use the name in document? if (!enabledViaScript && sheet && !title.isEmpty()) { if (engine->preferredStylesheetSetName().isEmpty()) { engine->setPreferredStylesheetSetName(title); engine->setSelectedStylesheetSetName(title); } if (title != engine->preferredStylesheetSetName()) activeSheet = 0; } const AtomicString& rel = element->fastGetAttribute(relAttr); if (rel.contains("alternate") && title.isEmpty()) activeSheet = 0; if (sheet) collection.appendSheetForList(sheet); if (activeSheet) collection.appendActiveStyleSheet(activeSheet); } }
void DocumentStyleSheetCollection::updateActiveStyleSheets(StyleEngine* engine, StyleResolverUpdateMode updateMode) { StyleSheetCollection collection; ActiveDocumentStyleSheetCollector collector(collection); collectStyleSheets(engine, collector); StyleSheetChange change; analyzeStyleSheetChange(updateMode, collection, change); if (change.styleResolverUpdateType == Reconstruct) { engine->clearMasterResolver(); // FIMXE: The following depends on whether StyleRuleFontFace was modified or not. // No need to always-clear font cache. engine->clearFontCache(); } else if (StyleResolver* styleResolver = engine->resolver()) { // FIXME: We might have already had styles in child treescope. In this case, we cannot use buildScopedStyleTreeInDocumentOrder. // Need to change "false" to some valid condition. styleResolver->setBuildScopedStyleTreeInDocumentOrder(false); if (change.styleResolverUpdateType != Additive) { ASSERT(change.styleResolverUpdateType == Reset); resetAllRuleSetsInTreeScope(styleResolver); engine->removeFontFaceRules(change.fontFaceRulesToRemove); styleResolver->removePendingAuthorStyleSheets(m_activeAuthorStyleSheets); styleResolver->lazyAppendAuthorStyleSheets(0, collection.activeAuthorStyleSheets()); } else { styleResolver->lazyAppendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), collection.activeAuthorStyleSheets()); } } if (change.requiresFullStyleRecalc) document().setNeedsStyleRecalc(SubtreeStyleChange); m_scopingNodesForStyleScoped.didRemoveScopingNodes(); collection.swap(*this); updateUsesRemUnits(); }
void ShadowTreeStyleSheetCollection::collectStyleSheets(StyleEngine* engine, StyleSheetCollection& collection) { for (Node* n : m_styleSheetCandidateNodes) { StyleSheetCandidate candidate(*n); ASSERT(!candidate.isXSL()); if (!candidate.isCSSStyle()) continue; StyleSheet* sheet = candidate.sheet(); if (!sheet) continue; // FIXME: clarify how PREFERRED or ALTERNATE works in shadow trees. // Should we set preferred/selected stylesheets name in shadow trees and // use the name in document? if (candidate.hasPreferrableName(engine->preferredStylesheetSetName())) engine->selectStylesheetSetName(candidate.title()); collection.appendSheetForList(sheet); if (candidate.canBeActivated(engine->preferredStylesheetSetName())) collection.appendActiveStyleSheet(toCSSStyleSheet(sheet)); } }