2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
29 #include "core/dom/StyleEngine.h"
31 #include "core/HTMLNames.h"
32 #include "core/css/CSSFontSelector.h"
33 #include "core/css/CSSStyleSheet.h"
34 #include "core/css/FontFaceCache.h"
35 #include "core/css/StyleSheetContents.h"
36 #include "core/dom/DocumentStyleSheetCollector.h"
37 #include "core/dom/Element.h"
38 #include "core/dom/ProcessingInstruction.h"
39 #include "core/dom/ShadowTreeStyleSheetCollection.h"
40 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/html/HTMLIFrameElement.h"
42 #include "core/html/HTMLLinkElement.h"
43 #include "core/html/imports/HTMLImportsController.h"
44 #include "core/inspector/InspectorInstrumentation.h"
45 #include "core/page/InjectedStyleSheets.h"
46 #include "core/page/Page.h"
47 #include "core/frame/Settings.h"
48 #include "platform/URLPatternMatcher.h"
52 using namespace HTMLNames;
54 StyleEngine::StyleEngine(Document& document)
55 : m_document(&document)
56 , m_isMaster(!document.importsController() || document.importsController()->master() == &document)
57 , m_pendingStylesheets(0)
58 , m_injectedStyleSheetCacheValid(false)
59 , m_documentStyleSheetCollection(DocumentStyleSheetCollection::create(document))
60 , m_documentScopeDirty(true)
61 , m_usesSiblingRules(false)
62 , m_usesSiblingRulesOverride(false)
63 , m_usesFirstLineRules(false)
64 , m_usesFirstLetterRules(false)
65 , m_usesRemUnits(false)
66 , m_maxDirectAdjacentSelectors(0)
67 , m_ignorePendingStylesheets(false)
68 , m_didCalculateResolver(false)
69 // We don't need to create CSSFontSelector for imported document or
70 // HTMLTemplateElement's document, because those documents have no frame.
71 , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nullptr)
72 , m_xslStyleSheet(nullptr)
75 m_fontSelector->registerForInvalidationCallbacks(this);
78 StyleEngine::~StyleEngine()
82 static bool isStyleElement(Node& node)
84 return isHTMLStyleElement(node) || isSVGStyleElement(node);
88 void StyleEngine::detachFromDocument()
90 // Cleanup is performed eagerly when the StyleEngine is removed from the
91 // document. The StyleEngine is unreachable after this, since only the
92 // document has a reference to it.
93 for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i)
94 m_injectedAuthorStyleSheets[i]->clearOwnerNode();
95 for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i)
96 m_authorStyleSheets[i]->clearOwnerNode();
99 m_fontSelector->clearDocument();
100 m_fontSelector->unregisterForInvalidationCallbacks(this);
103 // Decrement reference counts for things we could be keeping alive.
104 m_fontSelector.clear();
106 m_styleSheetCollectionMap.clear();
107 for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
108 const_cast<TreeScope&>((*it)->treeScope()).clearScopedStyleResolver();
109 m_scopedStyleResolvers.clear();
113 inline Document* StyleEngine::master()
117 HTMLImportsController* import = document().importsController();
118 if (!import) // Document::import() can return null while executing its destructor.
120 return import->master();
123 void StyleEngine::insertTreeScopeInDocumentOrder(TreeScopeSet& treeScopes, TreeScope* treeScope)
125 if (treeScopes.isEmpty()) {
126 treeScopes.add(treeScope);
129 if (treeScopes.contains(treeScope))
132 TreeScopeSet::iterator begin = treeScopes.begin();
133 TreeScopeSet::iterator end = treeScopes.end();
134 TreeScopeSet::iterator it = end;
135 TreeScope* followingTreeScope = 0;
139 unsigned short position = n->comparePosition(*treeScope);
140 if (position & Node::DOCUMENT_POSITION_FOLLOWING) {
141 treeScopes.insertBefore(followingTreeScope, treeScope);
144 followingTreeScope = n;
145 } while (it != begin);
147 treeScopes.insertBefore(followingTreeScope, treeScope);
150 TreeScopeStyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope)
152 if (treeScope == m_document)
153 return documentStyleSheetCollection();
155 StyleSheetCollectionMap::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr);
156 if (result.isNewEntry)
157 result.storedValue->value = adoptPtrWillBeNoop(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope)));
158 return result.storedValue->value.get();
161 TreeScopeStyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope)
163 if (treeScope == m_document)
164 return documentStyleSheetCollection();
166 StyleSheetCollectionMap::iterator it = m_styleSheetCollectionMap.find(&treeScope);
167 if (it == m_styleSheetCollectionMap.end())
169 return it->value.get();
172 const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope)
174 if (treeScope == m_document)
175 return documentStyleSheetCollection()->styleSheetsForStyleSheetList();
177 return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList();
180 const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const
182 return documentStyleSheetCollection()->activeAuthorStyleSheets();
185 void StyleEngine::combineCSSFeatureFlags(const RuleFeatureSet& features)
187 // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after).
188 m_usesSiblingRules = m_usesSiblingRules || features.usesSiblingRules();
189 m_usesFirstLineRules = m_usesFirstLineRules || features.usesFirstLineRules();
190 m_maxDirectAdjacentSelectors = max(m_maxDirectAdjacentSelectors, features.maxDirectAdjacentSelectors());
193 void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features)
195 m_usesSiblingRules = features.usesSiblingRules();
196 m_usesFirstLineRules = features.usesFirstLineRules();
197 m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors();
200 const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const
202 updateInjectedStyleSheetCache();
203 return m_injectedAuthorStyleSheets;
206 void StyleEngine::updateInjectedStyleSheetCache() const
208 if (m_injectedStyleSheetCacheValid)
210 m_injectedStyleSheetCacheValid = true;
211 m_injectedAuthorStyleSheets.clear();
213 Page* owningPage = document().page();
217 const InjectedStyleSheetEntryVector& entries = InjectedStyleSheets::instance().entries();
218 for (unsigned i = 0; i < entries.size(); ++i) {
219 const InjectedStyleSheetEntry* entry = entries[i].get();
220 if (entry->injectedFrames() == InjectStyleInTopFrameOnly && document().ownerElement())
222 if (!URLPatternMatcher::matchesPatterns(document().url(), entry->whitelist()))
224 RefPtrWillBeRawPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(m_document, KURL());
225 m_injectedAuthorStyleSheets.append(groupSheet);
226 groupSheet->contents()->parseString(entry->source());
230 void StyleEngine::invalidateInjectedStyleSheetCache()
232 m_injectedStyleSheetCacheValid = false;
234 // FIXME: updateInjectedStyleSheetCache is called inside StyleSheetCollection::updateActiveStyleSheets
235 // and batch updates lots of sheets so we can't call addedStyleSheet() or removedStyleSheet().
236 document().styleResolverChanged();
239 void StyleEngine::compatibilityModeChanged()
241 if (!m_injectedAuthorStyleSheets.isEmpty())
242 invalidateInjectedStyleSheetCache();
245 void StyleEngine::addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet)
247 m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_document));
248 document().addedStyleSheet(m_authorStyleSheets.last().get());
252 void StyleEngine::addPendingSheet()
254 m_pendingStylesheets++;
257 // This method is called whenever a top-level stylesheet has finished loading.
258 void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode)
260 ASSERT(styleSheetCandidateNode);
261 TreeScope* treeScope = isStyleElement(*styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : m_document.get();
262 markTreeScopeDirty(*treeScope);
264 // Make sure we knew this sheet was pending, and that our count isn't out of sync.
265 ASSERT(m_pendingStylesheets > 0);
267 m_pendingStylesheets--;
268 if (m_pendingStylesheets)
271 // FIXME: We can't call addedStyleSheet or removedStyleSheet here because we don't know
272 // what's new. We should track that to tell the style system what changed.
273 document().didRemoveAllPendingStylesheet();
276 void StyleEngine::modifiedStyleSheet(StyleSheet* sheet)
281 Node* node = sheet->ownerNode();
282 if (!node || !node->inDocument())
285 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
286 ASSERT(isStyleElement(*node) || treeScope == m_document);
288 markTreeScopeDirty(treeScope);
291 void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser)
293 if (!node->inDocument())
296 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
297 ASSERT(isStyleElement(*node) || treeScope == m_document);
298 ASSERT(!isXSLStyleSheet(*node));
299 TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
301 collection->addStyleSheetCandidateNode(node, createdByParser);
303 markTreeScopeDirty(treeScope);
304 if (treeScope != m_document)
305 insertTreeScopeInDocumentOrder(m_activeTreeScopes, &treeScope);
308 void StyleEngine::removeStyleSheetCandidateNode(Node* node)
310 removeStyleSheetCandidateNode(node, *m_document);
313 void StyleEngine::removeStyleSheetCandidateNode(Node* node, TreeScope& treeScope)
315 ASSERT(isStyleElement(*node) || treeScope == m_document);
316 ASSERT(!isXSLStyleSheet(*node));
318 TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(treeScope);
320 collection->removeStyleSheetCandidateNode(node);
322 markTreeScopeDirty(treeScope);
323 m_activeTreeScopes.remove(&treeScope);
326 void StyleEngine::addXSLStyleSheet(ProcessingInstruction* node, bool createdByParser)
328 if (!node->inDocument())
331 ASSERT(isXSLStyleSheet(*node));
332 bool needToUpdate = false;
333 if (createdByParser || !m_xslStyleSheet) {
334 needToUpdate = !m_xslStyleSheet;
336 unsigned position = m_xslStyleSheet->compareDocumentPosition(node, Node::TreatShadowTreesAsDisconnected);
337 needToUpdate = position & Node::DOCUMENT_POSITION_FOLLOWING;
343 markTreeScopeDirty(*m_document);
344 m_xslStyleSheet = node;
347 void StyleEngine::removeXSLStyleSheet(ProcessingInstruction* node)
349 ASSERT(isXSLStyleSheet(*node));
350 if (m_xslStyleSheet != node)
353 markTreeScopeDirty(*m_document);
354 m_xslStyleSheet = nullptr;
357 void StyleEngine::modifiedStyleSheetCandidateNode(Node* node)
359 if (!node->inDocument())
362 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
363 ASSERT(isStyleElement(*node) || treeScope == m_document);
364 markTreeScopeDirty(treeScope);
367 void StyleEngine::enableExitTransitionStylesheets()
369 TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(*m_document);
370 collection->enableExitTransitionStylesheets();
373 bool StyleEngine::shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMode updateMode) const
375 return m_documentScopeDirty || updateMode == FullStyleUpdate;
378 bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode) const
380 return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate;
383 void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet treeScopes)
385 for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) {
386 TreeScope& treeScope = **it;
387 ASSERT(treeScope != m_document);
388 ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(treeScope));
390 collection->clearMediaQueryRuleSetStyleSheets();
394 void StyleEngine::clearMediaQueryRuleSetStyleSheets()
396 documentStyleSheetCollection()->clearMediaQueryRuleSetStyleSheets();
397 clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes);
398 clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_dirtyTreeScopes);
401 void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector)
404 WillBeHeapVector<RefPtrWillBeMember<StyleSheet> > sheetsForList;
405 ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForList);
406 documentStyleSheetCollection()->collectStyleSheets(this, subcollector);
407 documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList);
410 void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode)
413 ASSERT(!document().inStyleRecalc());
415 if (!document().isActive())
418 if (shouldUpdateDocumentStyleSheetCollection(updateMode))
419 documentStyleSheetCollection()->updateActiveStyleSheets(this, updateMode);
421 if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) {
422 TreeScopeSet treeScopes = updateMode == FullStyleUpdate ? m_activeTreeScopes : m_dirtyTreeScopes;
423 HashSet<TreeScope*> treeScopesRemoved;
425 for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) {
426 TreeScope* treeScope = *it;
427 ASSERT(treeScope != m_document);
428 ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope));
430 collection->updateActiveStyleSheets(this, updateMode);
431 if (!collection->hasStyleSheetCandidateNodes())
432 treeScopesRemoved.add(treeScope);
434 m_activeTreeScopes.removeAll(treeScopesRemoved);
437 InspectorInstrumentation::activeStyleSheetsUpdated(m_document);
438 m_usesRemUnits = documentStyleSheetCollection()->usesRemUnits();
440 m_dirtyTreeScopes.clear();
441 m_documentScopeDirty = false;
444 const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > StyleEngine::activeStyleSheetsForInspector() const
446 if (m_activeTreeScopes.isEmpty())
447 return documentStyleSheetCollection()->activeAuthorStyleSheets();
449 WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > activeStyleSheets;
451 activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorStyleSheets());
453 TreeScopeSet::const_iterator begin = m_activeTreeScopes.begin();
454 TreeScopeSet::const_iterator end = m_activeTreeScopes.end();
455 for (TreeScopeSet::const_iterator it = begin; it != end; ++it) {
456 if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
457 activeStyleSheets.appendVector(collection->activeAuthorStyleSheets());
460 // FIXME: Inspector needs a vector which has all active stylesheets.
461 // However, creating such a large vector might cause performance regression.
462 // Need to implement some smarter solution.
463 return activeStyleSheets;
466 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot)
468 if (shadowRoot->scopedStyleResolver())
469 removeScopedStyleResolver(shadowRoot->scopedStyleResolver());
470 m_styleSheetCollectionMap.remove(shadowRoot);
473 void StyleEngine::appendActiveAuthorStyleSheets()
477 m_resolver->appendAuthorStyleSheets(documentStyleSheetCollection()->activeAuthorStyleSheets());
479 TreeScopeSet::iterator begin = m_activeTreeScopes.begin();
480 TreeScopeSet::iterator end = m_activeTreeScopes.end();
481 for (TreeScopeSet::iterator it = begin; it != end; ++it) {
482 if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it))
483 m_resolver->appendAuthorStyleSheets(collection->activeAuthorStyleSheets());
485 m_resolver->finishAppendAuthorStyleSheets();
488 void StyleEngine::createResolver()
490 // It is a programming error to attempt to resolve style on a Document
491 // which is not in a frame. Code which hits this should have checked
492 // Document::isActive() before calling into code which could get here.
494 ASSERT(document().frame());
496 m_resolver = adoptPtrWillBeNoop(new StyleResolver(*m_document));
497 addScopedStyleResolver(&m_document->ensureScopedStyleResolver());
499 appendActiveAuthorStyleSheets();
500 combineCSSFeatureFlags(m_resolver->ensureUpdatedRuleFeatureSet());
503 void StyleEngine::clearResolver()
505 ASSERT(!document().inStyleRecalc());
506 ASSERT(isMaster() || !m_resolver);
508 for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
509 const_cast<TreeScope&>((*it)->treeScope()).clearScopedStyleResolver();
510 m_scopedStyleResolvers.clear();
513 document().updateStyleInvalidationIfNeeded();
517 void StyleEngine::clearMasterResolver()
519 if (Document* master = this->master())
520 master->styleEngine()->clearResolver();
523 unsigned StyleEngine::resolverAccessCount() const
525 return m_resolver ? m_resolver->accessCount() : 0;
528 void StyleEngine::didDetach()
533 bool StyleEngine::shouldClearResolver() const
535 return !m_didCalculateResolver && !haveStylesheetsLoaded();
538 bool StyleEngine::shouldApplyXSLTransform() const
540 if (!RuntimeEnabledFeatures::xsltEnabled())
542 return m_xslStyleSheet && !m_document->transformSourceDocument();
545 void StyleEngine::resolverChanged(StyleResolverUpdateMode mode)
548 if (Document* master = this->master())
549 master->styleResolverChanged(mode);
553 // Don't bother updating, since we haven't loaded all our style info yet
554 // and haven't calculated the style selector for the first time.
555 if (!document().isActive() || shouldClearResolver()) {
560 if (shouldApplyXSLTransform()) {
561 // Processing instruction (XML documents only).
562 // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
563 // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
564 if (!m_document->parsing() && !m_xslStyleSheet->isLoading())
565 m_document->applyXSLTransform(m_xslStyleSheet.get());
569 m_didCalculateResolver = true;
570 updateActiveStyleSheets(mode);
573 void StyleEngine::clearFontCache()
576 m_fontSelector->fontFaceCache()->clearCSSConnected();
578 m_resolver->invalidateMatchedPropertiesCache();
581 void StyleEngine::updateGenericFontFamilySettings()
583 // FIXME: we should not update generic font family settings when
584 // document is inactive.
585 ASSERT(document().isActive());
590 m_fontSelector->updateGenericFontFamilySettings(*m_document);
592 m_resolver->invalidateMatchedPropertiesCache();
595 void StyleEngine::removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules)
600 FontFaceCache* cache = m_fontSelector->fontFaceCache();
601 for (unsigned i = 0; i < fontFaceRules.size(); ++i)
602 cache->remove(fontFaceRules[i]);
604 m_resolver->invalidateMatchedPropertiesCache();
607 void StyleEngine::markTreeScopeDirty(TreeScope& scope)
609 if (scope == m_document) {
614 m_dirtyTreeScopes.add(&scope);
617 void StyleEngine::markDocumentDirty()
619 m_documentScopeDirty = true;
620 if (document().importLoader())
621 document().importsController()->master()->styleEngine()->markDocumentDirty();
624 static bool isCacheableForStyleElement(const StyleSheetContents& contents)
626 // FIXME: Support copying import rules.
627 if (!contents.importRules().isEmpty())
629 // Until import rules are supported in cached sheets it's not possible for loading to fail.
630 ASSERT(!contents.didLoadErrorOccur());
631 // It is not the original sheet anymore.
632 if (contents.isMutable())
634 if (!contents.hasSyntacticallyValidCSSHeader())
639 PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
641 RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
643 e->document().styleEngine()->addPendingSheet();
645 if (!e->document().inQuirksMode()) {
646 AtomicString textContent(text);
648 WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<StyleSheetContents> >::AddResult result = m_textToSheetCache.add(textContent, nullptr);
649 if (result.isNewEntry || !result.storedValue->value) {
650 styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
651 if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
652 result.storedValue->value = styleSheet->contents();
653 m_sheetToTextCache.add(styleSheet->contents(), textContent);
656 StyleSheetContents* contents = result.storedValue->value;
658 ASSERT(isCacheableForStyleElement(*contents));
659 ASSERT(contents->singleOwnerDocument() == e->document());
660 styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
663 // FIXME: currently we don't cache StyleSheetContents inQuirksMode.
664 styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
668 styleSheet->setTitle(e->title());
672 PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::parseSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
674 RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;
675 styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, e->document().inputEncoding());
676 styleSheet->contents()->parseStringAtPosition(text, startPosition, createdByParser);
680 void StyleEngine::removeSheet(StyleSheetContents* contents)
682 WillBeHeapHashMap<RawPtrWillBeMember<StyleSheetContents>, AtomicString>::iterator it = m_sheetToTextCache.find(contents);
683 if (it == m_sheetToTextCache.end())
686 m_textToSheetCache.remove(it->value);
687 m_sheetToTextCache.remove(contents);
690 void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const
692 HashSet<const StyleSheetContents*> visitedSharedStyleSheetContents;
693 for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
694 (*it)->collectFeaturesTo(features, visitedSharedStyleSheetContents);
697 void StyleEngine::fontsNeedUpdate(CSSFontSelector*)
699 if (!document().isActive())
703 m_resolver->invalidateMatchedPropertiesCache();
704 document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Fonts));
707 void StyleEngine::trace(Visitor* visitor)
710 visitor->trace(m_document);
711 visitor->trace(m_injectedAuthorStyleSheets);
712 visitor->trace(m_authorStyleSheets);
713 visitor->trace(m_documentStyleSheetCollection);
714 visitor->trace(m_styleSheetCollectionMap);
715 visitor->trace(m_scopedStyleResolvers);
716 visitor->trace(m_resolver);
717 visitor->trace(m_fontSelector);
718 visitor->trace(m_textToSheetCache);
719 visitor->trace(m_sheetToTextCache);
720 visitor->trace(m_xslStyleSheet);
722 CSSFontSelectorClient::trace(visitor);