1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * (C) 2006 Alexey Proskuryakov (ap (at) 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. 11 * 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. 16 * 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. 21 * 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. 26 */ 27 28 #include "config.h" 29 #include "core/dom/StyleEngine.h" 30 31 #include "HTMLNames.h" 32 #include "SVGNames.h" 33 #include "core/css/CSSFontSelector.h" 34 #include "core/css/CSSStyleSheet.h" 35 #include "core/css/StyleInvalidationAnalysis.h" 36 #include "core/css/StyleSheetContents.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/HTMLImport.h" 43 #include "core/html/HTMLLinkElement.h" 44 #include "core/html/HTMLStyleElement.h" 45 #include "core/inspector/InspectorInstrumentation.h" 46 #include "core/page/Page.h" 47 #include "core/page/PageGroup.h" 48 #include "core/frame/Settings.h" 49 #include "core/svg/SVGStyleElement.h" 50 #include "platform/URLPatternMatcher.h" 51 52 namespace WebCore { 53 54 using namespace HTMLNames; 55 56 StyleEngine::StyleEngine(Document& document) 57 : m_document(document) 58 , m_isMaster(HTMLImport::isMaster(&document)) 59 , m_pendingStylesheets(0) 60 , m_injectedStyleSheetCacheValid(false) 61 , m_needsUpdateActiveStylesheetsOnStyleRecalc(false) 62 , m_documentStyleSheetCollection(document) 63 , m_documentScopeDirty(true) 64 , m_usesSiblingRules(false) 65 , m_usesSiblingRulesOverride(false) 66 , m_usesFirstLineRules(false) 67 , m_usesFirstLetterRules(false) 68 , m_usesRemUnits(false) 69 , m_maxDirectAdjacentSelectors(0) 70 , m_ignorePendingStylesheets(false) 71 , m_didCalculateResolver(false) 72 , m_lastResolverAccessCount(0) 73 , m_resolverThrowawayTimer(this, &StyleEngine::resolverThrowawayTimerFired) 74 // We don't need to create CSSFontSelector for imported document or 75 // HTMLTemplateElement's document, because those documents have no frame. 76 , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : 0) 77 { 78 } 79 80 StyleEngine::~StyleEngine() 81 { 82 for (unsigned i = 0; i < m_injectedAuthorStyleSheets.size(); ++i) 83 m_injectedAuthorStyleSheets[i]->clearOwnerNode(); 84 for (unsigned i = 0; i < m_authorStyleSheets.size(); ++i) 85 m_authorStyleSheets[i]->clearOwnerNode(); 86 87 if (m_fontSelector) { 88 m_fontSelector->clearDocument(); 89 if (m_resolver) 90 m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get()); 91 } 92 } 93 94 inline Document* StyleEngine::master() 95 { 96 if (isMaster()) 97 return &m_document; 98 HTMLImport* import = m_document.import(); 99 if (!import) // Document::import() can return null while executing its destructor. 100 return 0; 101 return import->master(); 102 } 103 104 void StyleEngine::insertTreeScopeInDocumentOrder(TreeScopeSet& treeScopes, TreeScope* treeScope) 105 { 106 if (treeScopes.isEmpty()) { 107 treeScopes.add(treeScope); 108 return; 109 } 110 if (treeScopes.contains(treeScope)) 111 return; 112 113 TreeScopeSet::iterator begin = treeScopes.begin(); 114 TreeScopeSet::iterator end = treeScopes.end(); 115 TreeScopeSet::iterator it = end; 116 TreeScope* followingTreeScope = 0; 117 do { 118 --it; 119 TreeScope* n = *it; 120 unsigned short position = n->comparePosition(*treeScope); 121 if (position & Node::DOCUMENT_POSITION_FOLLOWING) { 122 treeScopes.insertBefore(followingTreeScope, treeScope); 123 return; 124 } 125 followingTreeScope = n; 126 } while (it != begin); 127 128 treeScopes.insertBefore(followingTreeScope, treeScope); 129 } 130 131 StyleSheetCollection* StyleEngine::ensureStyleSheetCollectionFor(TreeScope& treeScope) 132 { 133 if (treeScope == m_document) 134 return &m_documentStyleSheetCollection; 135 136 HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::AddResult result = m_styleSheetCollectionMap.add(&treeScope, nullptr); 137 if (result.isNewEntry) 138 result.iterator->value = adoptPtr(new ShadowTreeStyleSheetCollection(toShadowRoot(treeScope))); 139 return result.iterator->value.get(); 140 } 141 142 StyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& treeScope) 143 { 144 if (treeScope == m_document) 145 return &m_documentStyleSheetCollection; 146 147 HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::iterator it = m_styleSheetCollectionMap.find(&treeScope); 148 if (it == m_styleSheetCollectionMap.end()) 149 return 0; 150 return it->value.get(); 151 } 152 153 const Vector<RefPtr<StyleSheet> >& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope) 154 { 155 if (treeScope == m_document) 156 return m_documentStyleSheetCollection.styleSheetsForStyleSheetList(); 157 158 return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList(); 159 } 160 161 const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::activeAuthorStyleSheets() const 162 { 163 return m_documentStyleSheetCollection.activeAuthorStyleSheets(); 164 } 165 166 void StyleEngine::getActiveAuthorStyleSheets(Vector<const Vector<RefPtr<CSSStyleSheet> >*>& activeAuthorStyleSheets) const 167 { 168 activeAuthorStyleSheets.append(&m_documentStyleSheetCollection.activeAuthorStyleSheets()); 169 170 HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values begin = m_styleSheetCollectionMap.values().begin(); 171 HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values end = m_styleSheetCollectionMap.values().end(); 172 HashMap<TreeScope*, OwnPtr<StyleSheetCollection> >::const_iterator::Values it = begin; 173 for (; it != end; ++it) { 174 const StyleSheetCollection* collection = it->get(); 175 activeAuthorStyleSheets.append(&collection->activeAuthorStyleSheets()); 176 } 177 } 178 179 void StyleEngine::combineCSSFeatureFlags(const RuleFeatureSet& features) 180 { 181 // 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). 182 m_usesSiblingRules = m_usesSiblingRules || features.usesSiblingRules(); 183 m_usesFirstLineRules = m_usesFirstLineRules || features.usesFirstLineRules(); 184 m_maxDirectAdjacentSelectors = max(m_maxDirectAdjacentSelectors, features.maxDirectAdjacentSelectors()); 185 } 186 187 void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features) 188 { 189 m_usesSiblingRules = features.usesSiblingRules(); 190 m_usesFirstLineRules = features.usesFirstLineRules(); 191 m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors(); 192 } 193 194 const Vector<RefPtr<CSSStyleSheet> >& StyleEngine::injectedAuthorStyleSheets() const 195 { 196 updateInjectedStyleSheetCache(); 197 return m_injectedAuthorStyleSheets; 198 } 199 200 void StyleEngine::updateInjectedStyleSheetCache() const 201 { 202 if (m_injectedStyleSheetCacheValid) 203 return; 204 m_injectedStyleSheetCacheValid = true; 205 m_injectedAuthorStyleSheets.clear(); 206 207 Page* owningPage = m_document.page(); 208 if (!owningPage) 209 return; 210 211 const PageGroup& pageGroup = owningPage->group(); 212 const InjectedStyleSheetVector& sheets = pageGroup.injectedStyleSheets(); 213 for (unsigned i = 0; i < sheets.size(); ++i) { 214 const InjectedStyleSheet* sheet = sheets[i].get(); 215 if (sheet->injectedFrames() == InjectStyleInTopFrameOnly && m_document.ownerElement()) 216 continue; 217 if (!URLPatternMatcher::matchesPatterns(m_document.url(), sheet->whitelist())) 218 continue; 219 RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(&m_document), KURL()); 220 m_injectedAuthorStyleSheets.append(groupSheet); 221 groupSheet->contents()->parseString(sheet->source()); 222 } 223 } 224 225 void StyleEngine::invalidateInjectedStyleSheetCache() 226 { 227 m_injectedStyleSheetCacheValid = false; 228 markDocumentDirty(); 229 // FIXME: updateInjectedStyleSheetCache is called inside StyleSheetCollection::updateActiveStyleSheets 230 // and batch updates lots of sheets so we can't call addedStyleSheet() or removedStyleSheet(). 231 m_document.styleResolverChanged(RecalcStyleDeferred); 232 } 233 234 void StyleEngine::addAuthorSheet(PassRefPtr<StyleSheetContents> authorSheet) 235 { 236 m_authorStyleSheets.append(CSSStyleSheet::create(authorSheet, &m_document)); 237 m_document.addedStyleSheet(m_authorStyleSheets.last().get(), RecalcStyleImmediately); 238 markDocumentDirty(); 239 } 240 241 void StyleEngine::addPendingSheet() 242 { 243 master()->styleEngine()->notifyPendingStyleSheetAdded(); 244 } 245 246 // This method is called whenever a top-level stylesheet has finished loading. 247 void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, RemovePendingSheetNotificationType notification) 248 { 249 TreeScope* treeScope = isHTMLStyleElement(styleSheetCandidateNode) ? &styleSheetCandidateNode->treeScope() : &m_document; 250 markTreeScopeDirty(*treeScope); 251 master()->styleEngine()->notifyPendingStyleSheetRemoved(notification); 252 } 253 254 void StyleEngine::notifyPendingStyleSheetAdded() 255 { 256 ASSERT(isMaster()); 257 m_pendingStylesheets++; 258 } 259 260 void StyleEngine::notifyPendingStyleSheetRemoved(RemovePendingSheetNotificationType notification) 261 { 262 ASSERT(isMaster()); 263 // Make sure we knew this sheet was pending, and that our count isn't out of sync. 264 ASSERT(m_pendingStylesheets > 0); 265 266 m_pendingStylesheets--; 267 if (m_pendingStylesheets) 268 return; 269 270 if (notification == RemovePendingSheetNotifyLater) { 271 m_document.setNeedsNotifyRemoveAllPendingStylesheet(); 272 return; 273 } 274 275 // FIXME: We can't call addedStyleSheet or removedStyleSheet here because we don't know 276 // what's new. We should track that to tell the style system what changed. 277 m_document.didRemoveAllPendingStylesheet(); 278 } 279 280 void StyleEngine::modifiedStyleSheet(StyleSheet* sheet) 281 { 282 if (!sheet) 283 return; 284 285 Node* node = sheet->ownerNode(); 286 if (!node || !node->inDocument()) 287 return; 288 289 TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document; 290 ASSERT(isHTMLStyleElement(node) || treeScope == m_document); 291 292 markTreeScopeDirty(treeScope); 293 } 294 295 void StyleEngine::addStyleSheetCandidateNode(Node* node, bool createdByParser) 296 { 297 if (!node->inDocument()) 298 return; 299 300 TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document; 301 ASSERT(isHTMLStyleElement(node) || treeScope == m_document); 302 303 StyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope); 304 ASSERT(collection); 305 collection->addStyleSheetCandidateNode(node, createdByParser); 306 307 markTreeScopeDirty(treeScope); 308 if (treeScope != m_document) 309 insertTreeScopeInDocumentOrder(m_activeTreeScopes, &treeScope); 310 } 311 312 void StyleEngine::removeStyleSheetCandidateNode(Node* node, ContainerNode* scopingNode) 313 { 314 TreeScope& treeScope = scopingNode ? scopingNode->treeScope() : m_document; 315 ASSERT(isHTMLStyleElement(node) || treeScope == m_document); 316 317 StyleSheetCollection* collection = styleSheetCollectionFor(treeScope); 318 ASSERT(collection); 319 collection->removeStyleSheetCandidateNode(node, scopingNode); 320 321 markTreeScopeDirty(treeScope); 322 m_activeTreeScopes.remove(&treeScope); 323 } 324 325 void StyleEngine::modifiedStyleSheetCandidateNode(Node* node) 326 { 327 if (!node->inDocument()) 328 return; 329 330 TreeScope& treeScope = isHTMLStyleElement(node) ? node->treeScope() : m_document; 331 ASSERT(isHTMLStyleElement(node) || treeScope == m_document); 332 markTreeScopeDirty(treeScope); 333 } 334 335 bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode) 336 { 337 return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate; 338 } 339 340 void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet treeScopes) 341 { 342 for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) { 343 TreeScope& treeScope = **it; 344 ASSERT(treeScope != m_document); 345 ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(treeScope)); 346 ASSERT(collection); 347 collection->clearMediaQueryRuleSetStyleSheets(); 348 } 349 } 350 351 void StyleEngine::clearMediaQueryRuleSetStyleSheets() 352 { 353 m_documentStyleSheetCollection.clearMediaQueryRuleSetStyleSheets(); 354 clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes); 355 clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_dirtyTreeScopes); 356 } 357 358 void StyleEngine::collectDocumentActiveStyleSheets(StyleSheetCollectionBase& collection) 359 { 360 ASSERT(isMaster()); 361 362 if (HTMLImport* rootImport = m_document.import()) { 363 for (HTMLImport* import = traverseFirstPostOrder(rootImport); import; import = traverseNextPostOrder(import)) { 364 Document* document = import->document(); 365 if (!document) 366 continue; 367 StyleEngine* engine = document->styleEngine(); 368 DocumentStyleSheetCollection::CollectFor collectFor = document == &m_document ? 369 DocumentStyleSheetCollection::CollectForList : DocumentStyleSheetCollection::DontCollectForList; 370 engine->m_documentStyleSheetCollection.collectStyleSheets(engine, collection, collectFor); 371 } 372 } else { 373 m_documentStyleSheetCollection.collectStyleSheets(this, collection, DocumentStyleSheetCollection::CollectForList); 374 } 375 } 376 377 bool StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode) 378 { 379 ASSERT(isMaster()); 380 381 if (m_document.inStyleRecalc()) { 382 // SVG <use> element may manage to invalidate style selector in the middle of a style recalc. 383 // https://bugs.webkit.org/show_bug.cgi?id=54344 384 // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc). 385 m_needsUpdateActiveStylesheetsOnStyleRecalc = true; 386 return false; 387 388 } 389 if (!m_document.isActive()) 390 return false; 391 392 bool requiresFullStyleRecalc = false; 393 if (m_documentScopeDirty || updateMode == FullStyleUpdate) 394 requiresFullStyleRecalc = m_documentStyleSheetCollection.updateActiveStyleSheets(this, updateMode); 395 396 if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) { 397 TreeScopeSet treeScopes = updateMode == FullStyleUpdate ? m_activeTreeScopes : m_dirtyTreeScopes; 398 HashSet<TreeScope*> treeScopesRemoved; 399 400 for (TreeScopeSet::iterator it = treeScopes.begin(); it != treeScopes.end(); ++it) { 401 TreeScope* treeScope = *it; 402 ASSERT(treeScope != m_document); 403 ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope)); 404 ASSERT(collection); 405 collection->updateActiveStyleSheets(this, updateMode); 406 if (!collection->hasStyleSheetCandidateNodes()) 407 treeScopesRemoved.add(treeScope); 408 } 409 if (!treeScopesRemoved.isEmpty()) 410 for (HashSet<TreeScope*>::iterator it = treeScopesRemoved.begin(); it != treeScopesRemoved.end(); ++it) 411 m_activeTreeScopes.remove(*it); 412 } 413 m_needsUpdateActiveStylesheetsOnStyleRecalc = false; 414 activeStyleSheetsUpdatedForInspector(); 415 m_usesRemUnits = m_documentStyleSheetCollection.usesRemUnits(); 416 417 if (m_documentScopeDirty || updateMode == FullStyleUpdate) 418 m_document.notifySeamlessChildDocumentsOfStylesheetUpdate(); 419 420 m_dirtyTreeScopes.clear(); 421 m_documentScopeDirty = false; 422 423 return requiresFullStyleRecalc; 424 } 425 426 void StyleEngine::activeStyleSheetsUpdatedForInspector() 427 { 428 if (m_activeTreeScopes.isEmpty()) { 429 InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, m_documentStyleSheetCollection.styleSheetsForStyleSheetList()); 430 return; 431 } 432 Vector<RefPtr<StyleSheet> > activeStyleSheets; 433 434 activeStyleSheets.append(m_documentStyleSheetCollection.styleSheetsForStyleSheetList()); 435 436 TreeScopeSet::iterator begin = m_activeTreeScopes.begin(); 437 TreeScopeSet::iterator end = m_activeTreeScopes.end(); 438 for (TreeScopeSet::iterator it = begin; it != end; ++it) { 439 if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it)) 440 activeStyleSheets.append(collection->styleSheetsForStyleSheetList()); 441 } 442 443 // FIXME: Inspector needs a vector which has all active stylesheets. 444 // However, creating such a large vector might cause performance regression. 445 // Need to implement some smarter solution. 446 InspectorInstrumentation::activeStyleSheetsUpdated(&m_document, activeStyleSheets); 447 } 448 449 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot) 450 { 451 m_styleSheetCollectionMap.remove(shadowRoot); 452 } 453 454 void StyleEngine::appendActiveAuthorStyleSheets() 455 { 456 ASSERT(isMaster()); 457 458 m_resolver->setBuildScopedStyleTreeInDocumentOrder(true); 459 m_resolver->appendAuthorStyleSheets(0, m_documentStyleSheetCollection.activeAuthorStyleSheets()); 460 461 TreeScopeSet::iterator begin = m_activeTreeScopes.begin(); 462 TreeScopeSet::iterator end = m_activeTreeScopes.end(); 463 for (TreeScopeSet::iterator it = begin; it != end; ++it) { 464 if (StyleSheetCollection* collection = m_styleSheetCollectionMap.get(*it)) { 465 m_resolver->setBuildScopedStyleTreeInDocumentOrder(!collection->scopingNodesForStyleScoped()); 466 m_resolver->appendAuthorStyleSheets(0, collection->activeAuthorStyleSheets()); 467 } 468 } 469 m_resolver->finishAppendAuthorStyleSheets(); 470 m_resolver->setBuildScopedStyleTreeInDocumentOrder(false); 471 } 472 473 void StyleEngine::createResolver() 474 { 475 // It is a programming error to attempt to resolve style on a Document 476 // which is not in a frame. Code which hits this should have checked 477 // Document::isActive() before calling into code which could get here. 478 479 ASSERT(m_document.frame()); 480 ASSERT(m_fontSelector); 481 482 m_resolver = adoptPtr(new StyleResolver(m_document)); 483 appendActiveAuthorStyleSheets(); 484 m_fontSelector->registerForInvalidationCallbacks(m_resolver.get()); 485 combineCSSFeatureFlags(m_resolver->ensureRuleFeatureSet()); 486 } 487 488 void StyleEngine::clearResolver() 489 { 490 ASSERT(!m_document.inStyleRecalc()); 491 ASSERT(isMaster() || !m_resolver); 492 ASSERT(m_fontSelector || !m_resolver); 493 if (m_resolver) 494 m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get()); 495 m_resolver.clear(); 496 } 497 498 void StyleEngine::clearMasterResolver() 499 { 500 if (Document* master = this->master()) 501 master->styleEngine()->clearResolver(); 502 } 503 504 unsigned StyleEngine::resolverAccessCount() const 505 { 506 return m_resolver ? m_resolver->accessCount() : 0; 507 } 508 509 void StyleEngine::resolverThrowawayTimerFired(Timer<StyleEngine>*) 510 { 511 if (resolverAccessCount() == m_lastResolverAccessCount) 512 clearResolver(); 513 m_lastResolverAccessCount = resolverAccessCount(); 514 } 515 516 void StyleEngine::didAttach() 517 { 518 m_resolverThrowawayTimer.startRepeating(60); 519 } 520 521 void StyleEngine::didDetach() 522 { 523 m_resolverThrowawayTimer.stop(); 524 clearResolver(); 525 } 526 527 bool StyleEngine::shouldClearResolver() const 528 { 529 return !m_didCalculateResolver && !haveStylesheetsLoaded(); 530 } 531 532 StyleResolverChange StyleEngine::resolverChanged(RecalcStyleTime time, StyleResolverUpdateMode mode) 533 { 534 StyleResolverChange change; 535 536 if (!isMaster()) { 537 if (Document* master = this->master()) 538 master->styleResolverChanged(time, mode); 539 return change; 540 } 541 542 // Don't bother updating, since we haven't loaded all our style info yet 543 // and haven't calculated the style selector for the first time. 544 if (!m_document.isActive() || shouldClearResolver()) { 545 clearResolver(); 546 return change; 547 } 548 549 m_didCalculateResolver = true; 550 if (m_document.didLayoutWithPendingStylesheets() && !hasPendingSheets()) 551 change.setNeedsRepaint(); 552 553 if (updateActiveStyleSheets(mode)) 554 change.setNeedsStyleRecalc(); 555 556 return change; 557 } 558 559 void StyleEngine::resetFontSelector() 560 { 561 if (!m_fontSelector) 562 return; 563 564 m_fontSelector->clearDocument(); 565 if (m_resolver) { 566 m_fontSelector->unregisterForInvalidationCallbacks(m_resolver.get()); 567 m_resolver->invalidateMatchedPropertiesCache(); 568 } 569 570 // If the document has been already detached, we don't need to recreate 571 // CSSFontSelector. 572 if (m_document.isActive()) { 573 m_fontSelector = CSSFontSelector::create(&m_document); 574 if (m_resolver) 575 m_fontSelector->registerForInvalidationCallbacks(m_resolver.get()); 576 } else { 577 m_fontSelector = 0; 578 } 579 } 580 581 void StyleEngine::markTreeScopeDirty(TreeScope& scope) 582 { 583 if (scope == m_document) { 584 markDocumentDirty(); 585 return; 586 } 587 588 m_dirtyTreeScopes.add(&scope); 589 } 590 591 void StyleEngine::markDocumentDirty() 592 { 593 m_documentScopeDirty = true; 594 if (!HTMLImport::isMaster(&m_document)) 595 m_document.import()->master()->styleEngine()->markDocumentDirty(); 596 } 597 598 } 599