1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * Copyright (C) 2012 Google Inc. All rights reserved. 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Library General Public 15 * License as published by the Free Software Foundation; either 16 * version 2 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Library General Public License for more details. 22 * 23 * You should have received a copy of the GNU Library General Public License 24 * along with this library; see the file COPYING.LIB. If not, write to 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26 * Boston, MA 02110-1301, USA. 27 */ 28 29 #include "config.h" 30 #include "core/css/resolver/StyleResolver.h" 31 32 #include "core/CSSPropertyNames.h" 33 #include "core/HTMLNames.h" 34 #include "core/MediaTypeNames.h" 35 #include "core/StylePropertyShorthand.h" 36 #include "core/animation/ActiveAnimations.h" 37 #include "core/animation/Animation.h" 38 #include "core/animation/AnimationTimeline.h" 39 #include "core/animation/StyleInterpolation.h" 40 #include "core/animation/animatable/AnimatableValue.h" 41 #include "core/animation/css/CSSAnimatableValueFactory.h" 42 #include "core/animation/css/CSSAnimations.h" 43 #include "core/css/CSSCalculationValue.h" 44 #include "core/css/CSSDefaultStyleSheets.h" 45 #include "core/css/CSSFontSelector.h" 46 #include "core/css/CSSKeyframeRule.h" 47 #include "core/css/CSSKeyframesRule.h" 48 #include "core/css/CSSReflectValue.h" 49 #include "core/css/CSSRuleList.h" 50 #include "core/css/CSSSelector.h" 51 #include "core/css/CSSStyleRule.h" 52 #include "core/css/CSSValueList.h" 53 #include "core/css/CSSValuePool.h" 54 #include "core/css/ElementRuleCollector.h" 55 #include "core/css/FontFace.h" 56 #include "core/css/MediaQueryEvaluator.h" 57 #include "core/css/PageRuleCollector.h" 58 #include "core/css/StylePropertySet.h" 59 #include "core/css/StyleRuleImport.h" 60 #include "core/css/StyleSheetContents.h" 61 #include "core/css/resolver/AnimatedStyleBuilder.h" 62 #include "core/css/resolver/MatchResult.h" 63 #include "core/css/resolver/MediaQueryResult.h" 64 #include "core/css/resolver/SharedStyleFinder.h" 65 #include "core/css/resolver/StyleAdjuster.h" 66 #include "core/css/resolver/StyleResolverParentScope.h" 67 #include "core/css/resolver/StyleResolverState.h" 68 #include "core/css/resolver/StyleResolverStats.h" 69 #include "core/css/resolver/ViewportStyleResolver.h" 70 #include "core/dom/CSSSelectorWatch.h" 71 #include "core/dom/NodeRenderStyle.h" 72 #include "core/dom/StyleEngine.h" 73 #include "core/dom/Text.h" 74 #include "core/dom/shadow/ElementShadow.h" 75 #include "core/dom/shadow/ShadowRoot.h" 76 #include "core/frame/FrameView.h" 77 #include "core/frame/LocalFrame.h" 78 #include "core/html/HTMLIFrameElement.h" 79 #include "core/inspector/InspectorInstrumentation.h" 80 #include "core/rendering/RenderView.h" 81 #include "core/rendering/style/KeyframeList.h" 82 #include "core/svg/SVGDocumentExtensions.h" 83 #include "core/svg/SVGElement.h" 84 #include "core/svg/SVGFontFaceElement.h" 85 #include "platform/RuntimeEnabledFeatures.h" 86 #include "wtf/StdLibExtras.h" 87 88 namespace { 89 90 using namespace blink; 91 92 void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) 93 { 94 // If any changes to CSS Animations were detected, stash the update away for application after the 95 // render object is updated if we're in the appropriate scope. 96 if (state.animationUpdate()) 97 element.ensureActiveAnimations().cssAnimations().setPendingUpdate(state.takeAnimationUpdate()); 98 } 99 100 } // namespace 101 102 namespace blink { 103 104 using namespace HTMLNames; 105 106 RenderStyle* StyleResolver::s_styleNotYetAvailable; 107 108 static StylePropertySet* leftToRightDeclaration() 109 { 110 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(MutableStylePropertySet, leftToRightDecl, (MutableStylePropertySet::create())); 111 if (leftToRightDecl->isEmpty()) 112 leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr); 113 return leftToRightDecl; 114 } 115 116 static StylePropertySet* rightToLeftDeclaration() 117 { 118 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(MutableStylePropertySet, rightToLeftDecl, (MutableStylePropertySet::create())); 119 if (rightToLeftDecl->isEmpty()) 120 rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl); 121 return rightToLeftDecl; 122 } 123 124 static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule) 125 { 126 RefPtrWillBeRawPtr<FontFace> fontFace = FontFace::create(document, fontFaceRule); 127 if (fontFace) 128 cssFontSelector->fontFaceCache()->add(cssFontSelector, fontFaceRule, fontFace); 129 } 130 131 StyleResolver::StyleResolver(Document& document) 132 : m_document(document) 133 , m_viewportStyleResolver(ViewportStyleResolver::create(&document)) 134 , m_needCollectFeatures(false) 135 , m_printMediaType(false) 136 , m_styleResourceLoader(document.fetcher()) 137 , m_styleSharingDepth(0) 138 , m_styleResolverStatsSequence(0) 139 , m_accessCount(0) 140 { 141 FrameView* view = document.view(); 142 if (view) { 143 m_medium = adoptPtr(new MediaQueryEvaluator(&view->frame())); 144 m_printMediaType = equalIgnoringCase(view->mediaType(), MediaTypeNames::print); 145 } else { 146 m_medium = adoptPtr(new MediaQueryEvaluator("all")); 147 } 148 149 initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors()); 150 151 #if ENABLE(SVG_FONTS) 152 if (document.svgExtensions()) { 153 const WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements(); 154 WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator end = svgFontFaceElements.end(); 155 for (WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator it = svgFontFaceElements.begin(); it != end; ++it) 156 addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule()); 157 } 158 #endif 159 } 160 161 void StyleResolver::initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors) 162 { 163 if (!watchedSelectors.size()) 164 return; 165 m_watchedSelectorsRules = RuleSet::create(); 166 for (unsigned i = 0; i < watchedSelectors.size(); ++i) 167 m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState); 168 } 169 170 void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) 171 { 172 unsigned size = styleSheets.size(); 173 for (unsigned i = firstNew; i < size; ++i) 174 m_pendingStyleSheets.add(styleSheets[i].get()); 175 } 176 177 void StyleResolver::removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) 178 { 179 for (unsigned i = 0; i < styleSheets.size(); ++i) 180 m_pendingStyleSheets.remove(styleSheets[i].get()); 181 } 182 183 void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet) 184 { 185 ASSERT(cssSheet); 186 ASSERT(!cssSheet->disabled()); 187 if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults)) 188 return; 189 190 TreeScope* treeScope = ScopedStyleResolver::treeScopeFor(document(), cssSheet); 191 if (!treeScope) 192 return; 193 194 ScopedStyleResolver& resolver = treeScope->ensureScopedStyleResolver(); 195 document().styleEngine()->addScopedStyleResolver(&resolver); 196 resolver.addRulesFromSheet(cssSheet, *m_medium, this); 197 } 198 199 void StyleResolver::appendPendingAuthorStyleSheets() 200 { 201 for (WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it) 202 appendCSSStyleSheet(*it); 203 204 m_pendingStyleSheets.clear(); 205 finishAppendAuthorStyleSheets(); 206 } 207 208 void StyleResolver::appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) 209 { 210 // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver 211 // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated. 212 unsigned size = styleSheets.size(); 213 for (unsigned i = 0; i < size; ++i) 214 appendCSSStyleSheet(styleSheets[i].get()); 215 } 216 217 void StyleResolver::finishAppendAuthorStyleSheets() 218 { 219 collectFeatures(); 220 221 if (document().renderView() && document().renderView()->style()) 222 document().renderView()->style()->font().update(document().styleEngine()->fontSelector()); 223 224 collectViewportRules(); 225 226 document().styleEngine()->resetCSSFeatureFlags(m_features); 227 } 228 229 void StyleResolver::resetRuleFeatures() 230 { 231 // Need to recreate RuleFeatureSet. 232 m_features.clear(); 233 m_siblingRuleSet.clear(); 234 m_uncommonAttributeRuleSet.clear(); 235 m_needCollectFeatures = true; 236 } 237 238 void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, unsigned parentIndex, ContainerNode& scope) 239 { 240 const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules(); 241 ScopedStyleResolver* resolver = &scope.treeScope().ensureScopedStyleResolver(); 242 document().styleEngine()->addScopedStyleResolver(resolver); 243 for (unsigned i = 0; i < keyframesRules.size(); ++i) 244 resolver->addKeyframeStyle(keyframesRules[i]); 245 246 m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, parentStyleSheet, parentIndex, scope); 247 248 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. 249 if (scope.isDocumentNode()) { 250 const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > fontFaceRules = authorRules.fontFaceRules(); 251 for (unsigned i = 0; i < fontFaceRules.size(); ++i) 252 addFontFaceRule(m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]); 253 if (fontFaceRules.size()) 254 invalidateMatchedPropertiesCache(); 255 } 256 } 257 258 void StyleResolver::resetAuthorStyle(TreeScope& treeScope) 259 { 260 ScopedStyleResolver* resolver = treeScope.scopedStyleResolver(); 261 if (!resolver) 262 return; 263 264 m_treeBoundaryCrossingRules.reset(&treeScope.rootNode()); 265 266 resolver->resetAuthorStyle(); 267 resetRuleFeatures(); 268 if (treeScope.rootNode().isDocumentNode()) 269 return; 270 271 // resolver is going to be freed below. 272 document().styleEngine()->removeScopedStyleResolver(resolver); 273 treeScope.clearScopedStyleResolver(); 274 } 275 276 static PassOwnPtrWillBeRawPtr<RuleSet> makeRuleSet(const WillBeHeapVector<RuleFeature>& rules) 277 { 278 size_t size = rules.size(); 279 if (!size) 280 return nullptr; 281 OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create(); 282 for (size_t i = 0; i < size; ++i) 283 ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState); 284 return ruleSet.release(); 285 } 286 287 void StyleResolver::collectFeatures() 288 { 289 m_features.clear(); 290 // Collect all ids and rules using sibling selectors (:first-child and similar) 291 // in the current set of stylesheets. Style sharing code uses this information to reject 292 // sharing candidates. 293 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); 294 if (defaultStyleSheets.defaultStyle()) 295 m_features.add(defaultStyleSheets.defaultStyle()->features()); 296 297 if (document().isViewSource()) 298 m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features()); 299 300 if (document().isTransitionDocument()) 301 m_features.add(defaultStyleSheets.defaultTransitionStyle()->features()); 302 303 if (m_watchedSelectorsRules) 304 m_features.add(m_watchedSelectorsRules->features()); 305 306 m_treeBoundaryCrossingRules.collectFeaturesTo(m_features); 307 308 document().styleEngine()->collectScopedStyleFeaturesTo(m_features); 309 310 m_siblingRuleSet = makeRuleSet(m_features.siblingRules); 311 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); 312 m_needCollectFeatures = false; 313 } 314 315 bool StyleResolver::hasRulesForId(const AtomicString& id) const 316 { 317 return m_features.hasSelectorForId(id); 318 } 319 320 void StyleResolver::addToStyleSharingList(Element& element) 321 { 322 // Never add elements to the style sharing list if we're not in a recalcStyle, 323 // otherwise we could leave stale pointers in there. 324 if (!document().inStyleRecalc()) 325 return; 326 INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates); 327 StyleSharingList& list = styleSharingList(); 328 if (list.size() >= styleSharingListSize) 329 list.removeLast(); 330 list.prepend(&element); 331 } 332 333 StyleSharingList& StyleResolver::styleSharingList() 334 { 335 m_styleSharingLists.resize(styleSharingMaxDepth); 336 337 // We never put things at depth 0 into the list since that's only the <html> element 338 // and it has no siblings or cousins to share with. 339 unsigned depth = std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u; 340 341 if (!m_styleSharingLists[depth]) 342 m_styleSharingLists[depth] = adoptPtrWillBeNoop(new StyleSharingList); 343 return *m_styleSharingLists[depth]; 344 } 345 346 void StyleResolver::clearStyleSharingList() 347 { 348 m_styleSharingLists.resize(0); 349 } 350 351 void StyleResolver::pushParentElement(Element& parent) 352 { 353 const ContainerNode* parentsParent = parent.parentOrShadowHostElement(); 354 355 // We are not always invoked consistently. For example, script execution can cause us to enter 356 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree. 357 // Reset the stack in this case, or if we see a new root element. 358 // Otherwise just push the new parent. 359 if (!parentsParent || m_selectorFilter.parentStackIsEmpty()) 360 m_selectorFilter.setupParentStack(parent); 361 else 362 m_selectorFilter.pushParent(parent); 363 } 364 365 void StyleResolver::popParentElement(Element& parent) 366 { 367 // Note that we may get invoked for some random elements in some wacky cases during style resolve. 368 // Pause maintaining the stack in this case. 369 if (m_selectorFilter.parentStackIsConsistent(&parent)) 370 m_selectorFilter.popParent(); 371 } 372 373 StyleResolver::~StyleResolver() 374 { 375 } 376 377 void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolversInShadowTree) 378 { 379 collector.clearMatchedRules(); 380 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1; 381 382 CascadeScope cascadeScope = 0; 383 CascadeOrder cascadeOrder = 0; 384 385 for (int j = resolversInShadowTree.size() - 1; j >= 0; --j) 386 resolversInShadowTree.at(j)->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope, cascadeOrder++); 387 388 if (resolvers.isEmpty() || resolvers.first()->treeScope() != element->treeScope()) 389 ++cascadeScope; 390 cascadeOrder += resolvers.size(); 391 for (unsigned i = 0; i < resolvers.size(); ++i) 392 resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, --cascadeOrder); 393 394 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); 395 collector.sortAndTransferMatchedRules(); 396 } 397 398 void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules) 399 { 400 collector.clearMatchedRules(); 401 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1; 402 403 if (document().styleEngine()->hasOnlyScopedResolverForDocument()) { 404 document().scopedStyleResolver()->collectMatchingAuthorRules(collector, includeEmptyRules, ignoreCascadeScope); 405 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); 406 collector.sortAndTransferMatchedRules(); 407 return; 408 } 409 410 WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolvers; 411 resolveScopedStyles(element, resolvers); 412 413 WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolversInShadowTree; 414 collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree); 415 if (!resolversInShadowTree.isEmpty()) { 416 matchAuthorRulesForShadowHost(element, collector, includeEmptyRules, resolvers, resolversInShadowTree); 417 return; 418 } 419 420 if (resolvers.isEmpty()) 421 return; 422 423 CascadeScope cascadeScope = 0; 424 CascadeOrder cascadeOrder = resolvers.size(); 425 for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) { 426 ScopedStyleResolver* resolver = resolvers.at(i); 427 // FIXME: Need to clarify how to treat style scoped. 428 resolver->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->treeScope().rootNode().isShadowRoot() ? 0 : cascadeOrder); 429 } 430 431 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); 432 collector.sortAndTransferMatchedRules(); 433 } 434 435 void StyleResolver::matchUARules(ElementRuleCollector& collector) 436 { 437 collector.setMatchingUARules(true); 438 439 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); 440 RuleSet* userAgentStyleSheet = m_printMediaType ? defaultStyleSheets.defaultPrintStyle() : defaultStyleSheets.defaultStyle(); 441 matchUARules(collector, userAgentStyleSheet); 442 443 // In quirks mode, we match rules from the quirks user agent sheet. 444 if (document().inQuirksMode()) 445 matchUARules(collector, defaultStyleSheets.defaultQuirksStyle()); 446 447 // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet. 448 if (document().isViewSource()) 449 matchUARules(collector, defaultStyleSheets.defaultViewSourceStyle()); 450 451 if (document().isTransitionDocument()) 452 matchUARules(collector, defaultStyleSheets.defaultTransitionStyle()); 453 454 collector.setMatchingUARules(false); 455 } 456 457 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules) 458 { 459 collector.clearMatchedRules(); 460 collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1; 461 462 RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange(); 463 collector.collectMatchingRules(MatchRequest(rules), ruleRange); 464 465 collector.sortAndTransferMatchedRules(); 466 } 467 468 void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollector& collector, bool includeSMILProperties) 469 { 470 matchUARules(collector); 471 472 // Now check author rules, beginning first with presentational attributes mapped from HTML. 473 if (state.element()->isStyledElement()) { 474 collector.addElementStyleProperties(state.element()->presentationAttributeStyle()); 475 476 // Now we check additional mapped declarations. 477 // Tables and table cells share an additional mapped rule that must be applied 478 // after all attributes, since their mapped style depends on the values of multiple attributes. 479 collector.addElementStyleProperties(state.element()->additionalPresentationAttributeStyle()); 480 481 if (state.element()->isHTMLElement()) { 482 bool isAuto; 483 TextDirection textDirection = toHTMLElement(state.element())->directionalityIfhasDirAutoAttribute(isAuto); 484 if (isAuto) 485 collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration()); 486 } 487 } 488 489 matchAuthorRules(state.element(), collector, false); 490 491 if (state.element()->isStyledElement()) { 492 if (state.element()->inlineStyle()) { 493 // Inline style is immutable as long as there is no CSSOM wrapper. 494 bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMutable(); 495 collector.addElementStyleProperties(state.element()->inlineStyle(), isInlineStyleCacheable); 496 } 497 498 // Now check SMIL animation override style. 499 if (includeSMILProperties && state.element()->isSVGElement()) 500 collector.addElementStyleProperties(toSVGElement(state.element())->animatedSMILStyleProperties(), false /* isCacheable */); 501 } 502 } 503 504 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document) 505 { 506 const LocalFrame* frame = document.frame(); 507 508 RefPtr<RenderStyle> documentStyle = RenderStyle::create(); 509 documentStyle->setDisplay(BLOCK); 510 documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder); 511 documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1); 512 documentStyle->setLocale(document.contentLanguage()); 513 documentStyle->setZIndex(0); 514 documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY); 515 516 document.setupFontBuilder(documentStyle.get()); 517 518 return documentStyle.release(); 519 } 520 521 static inline void resetDirectionAndWritingModeOnDocument(Document& document) 522 { 523 document.setDirectionSetOnDocumentElement(false); 524 document.setWritingModeSetOnDocumentElement(false); 525 } 526 527 static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features) 528 { 529 for (size_t i = 0; i < contentAttrValues.size(); ++i) 530 features.addContentAttr(contentAttrValues[i]); 531 } 532 533 void StyleResolver::adjustRenderStyle(StyleResolverState& state, Element* element) 534 { 535 StyleAdjuster adjuster(document().inQuirksMode()); 536 adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element, state.cachedUAStyle()); 537 } 538 539 // Start loading resources referenced by this style. 540 void StyleResolver::loadPendingResources(StyleResolverState& state) 541 { 542 m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources()); 543 document().styleEngine()->fontSelector()->fontLoader()->loadPendingFonts(); 544 } 545 546 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior, 547 RuleMatchingBehavior matchingBehavior) 548 { 549 ASSERT(document().frame()); 550 ASSERT(document().settings()); 551 ASSERT(!hasPendingAuthorStyleSheets()); 552 ASSERT(!m_needCollectFeatures); 553 554 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer 555 // will vanish if a style recalc happens during loading. 556 if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() && !element->renderer()) { 557 if (!s_styleNotYetAvailable) { 558 s_styleNotYetAvailable = RenderStyle::create().leakRef(); 559 s_styleNotYetAvailable->setDisplay(NONE); 560 s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector()); 561 } 562 563 document().setHasNodesWithPlaceholderStyle(); 564 return s_styleNotYetAvailable; 565 } 566 567 didAccess(); 568 569 StyleResolverParentScope::ensureParentStackIsPushed(); 570 571 if (element == document().documentElement()) 572 resetDirectionAndWritingModeOnDocument(document()); 573 StyleResolverState state(document(), element, defaultParent); 574 575 if (sharingBehavior == AllowStyleSharing && state.parentStyle()) { 576 SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this); 577 if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle()) 578 return sharedStyle.release(); 579 } 580 581 if (state.parentStyle()) { 582 state.setStyle(RenderStyle::create()); 583 state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary); 584 } else { 585 state.setStyle(defaultStyleForElement()); 586 state.setParentStyle(RenderStyle::clone(state.style())); 587 } 588 // contenteditable attribute (implemented by -webkit-user-modify) should 589 // be propagated from shadow host to distributed node. 590 if (state.distributedToInsertionPoint()) { 591 if (Element* parent = element->parentElement()) { 592 if (RenderStyle* styleOfShadowHost = parent->renderStyle()) 593 state.style()->setUserModify(styleOfShadowHost->userModify()); 594 } 595 } 596 597 state.fontBuilder().initForStyleResolve(state.document(), state.style()); 598 599 if (element->isLink()) { 600 state.style()->setIsLink(true); 601 EInsideLink linkState = state.elementLinkState(); 602 if (linkState != NotInsideLink) { 603 bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited); 604 if (forceVisited) 605 linkState = InsideVisitedLink; 606 } 607 state.style()->setInsideLink(linkState); 608 } 609 610 bool needsCollection = false; 611 CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element, needsCollection); 612 if (needsCollection) 613 collectFeatures(); 614 615 { 616 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); 617 618 matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL); 619 620 applyMatchedProperties(state, collector.matchedResult()); 621 applyCallbackSelectors(state); 622 623 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); 624 } 625 626 // Cache our original display. 627 state.style()->setOriginalDisplay(state.style()->display()); 628 629 adjustRenderStyle(state, element); 630 631 // FIXME: The CSSWG wants to specify that the effects of animations are applied before 632 // important rules, but this currently happens here as we require adjustment to have happened 633 // before deciding which properties to transition. 634 if (applyAnimatedProperties(state, element)) 635 adjustRenderStyle(state, element); 636 637 if (isHTMLBodyElement(*element)) 638 document().textLinkColors().setTextColor(state.style()->color()); 639 640 setAnimationUpdateIfNeeded(state, *element); 641 642 if (state.style()->hasViewportUnits()) 643 document().setHasViewportUnits(); 644 645 // Now return the style. 646 return state.takeStyle(); 647 } 648 649 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element& element, const RenderStyle& elementStyle, RenderStyle* parentStyle, const StyleKeyframe* keyframe, const AtomicString& animationName) 650 { 651 ASSERT(document().frame()); 652 ASSERT(document().settings()); 653 ASSERT(!hasPendingAuthorStyleSheets()); 654 655 if (&element == document().documentElement()) 656 resetDirectionAndWritingModeOnDocument(document()); 657 StyleResolverState state(document(), &element, parentStyle); 658 659 MatchResult result; 660 result.addMatchedProperties(&keyframe->properties()); 661 662 ASSERT(!state.style()); 663 664 // Create the style 665 state.setStyle(RenderStyle::clone(&elementStyle)); 666 state.setLineHeightValue(0); 667 668 state.fontBuilder().initForStyleResolve(state.document(), state.style()); 669 670 // We don't need to bother with !important. Since there is only ever one 671 // decl, there's nothing to override. So just add the first properties. 672 // We also don't need to bother with animation properties since the only 673 // relevant one is animation-timing-function and we special-case that in 674 // CSSAnimations.cpp 675 bool inheritedOnly = false; 676 applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); 677 678 // If our font got dirtied, go ahead and update it now. 679 updateFont(state); 680 681 // Line-height is set when we are sure we decided on the font-size 682 if (state.lineHeightValue()) 683 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue()); 684 685 // Now do rest of the properties. 686 applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); 687 688 loadPendingResources(state); 689 690 didAccess(); 691 692 return state.takeStyle(); 693 } 694 695 // This function is used by the WebAnimations JavaScript API method animate(). 696 // FIXME: Remove this when animate() switches away from resolution-dependent parsing. 697 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(Element& element, CSSPropertyID property, CSSValue& value) 698 { 699 RefPtr<RenderStyle> style; 700 if (element.renderStyle()) 701 style = RenderStyle::clone(element.renderStyle()); 702 else 703 style = RenderStyle::create(); 704 StyleResolverState state(element.document(), &element); 705 state.setStyle(style); 706 state.fontBuilder().initForStyleResolve(state.document(), state.style()); 707 return createAnimatableValueSnapshot(state, property, value); 708 } 709 710 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(StyleResolverState& state, CSSPropertyID property, CSSValue& value) 711 { 712 StyleBuilder::applyProperty(property, state, &value); 713 return CSSAnimatableValueFactory::create(property, *state.style()); 714 } 715 716 PassRefPtrWillBeRawPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& parent, PseudoId pseudoId) 717 { 718 RenderObject* parentRenderer = parent.renderer(); 719 if (!parentRenderer) 720 return nullptr; 721 722 if (pseudoId < FIRST_INTERNAL_PSEUDOID && !parentRenderer->style()->hasPseudoStyle(pseudoId)) 723 return nullptr; 724 725 if (pseudoId == BACKDROP && !parent.isInTopLayer()) 726 return nullptr; 727 728 if (!parentRenderer->canHaveGeneratedChildren()) 729 return nullptr; 730 731 RenderStyle* parentStyle = parentRenderer->style(); 732 if (RenderStyle* cachedStyle = parentStyle->getCachedPseudoStyle(pseudoId)) { 733 if (!pseudoElementRendererIsNeeded(cachedStyle)) 734 return nullptr; 735 return PseudoElement::create(&parent, pseudoId); 736 } 737 738 StyleResolverState state(document(), &parent, parentStyle); 739 if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state)) 740 return nullptr; 741 RefPtr<RenderStyle> style = state.takeStyle(); 742 ASSERT(style); 743 parentStyle->addCachedPseudoStyle(style); 744 745 if (!pseudoElementRendererIsNeeded(style.get())) 746 return nullptr; 747 748 RefPtrWillBeRawPtr<PseudoElement> pseudo = PseudoElement::create(&parent, pseudoId); 749 750 setAnimationUpdateIfNeeded(state, *pseudo); 751 if (ActiveAnimations* activeAnimations = pseudo->activeAnimations()) 752 activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get()); 753 return pseudo.release(); 754 } 755 756 bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state) 757 { 758 ASSERT(document().frame()); 759 ASSERT(document().settings()); 760 ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED); 761 762 StyleResolverParentScope::ensureParentStackIsPushed(); 763 764 if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) { 765 state.setStyle(RenderStyle::create()); 766 state.style()->inheritFrom(state.parentStyle()); 767 } else { 768 state.setStyle(defaultStyleForElement()); 769 state.setParentStyle(RenderStyle::clone(state.style())); 770 } 771 772 state.style()->setStyleType(pseudoStyleRequest.pseudoId); 773 state.fontBuilder().initForStyleResolve(state.document(), state.style()); 774 775 // Since we don't use pseudo-elements in any of our quirk/print 776 // user agent rules, don't waste time walking those rules. 777 778 { 779 // Check UA, user and author rules. 780 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); 781 collector.setPseudoStyleRequest(pseudoStyleRequest); 782 783 matchUARules(collector); 784 matchAuthorRules(state.element(), collector, false); 785 786 if (collector.matchedResult().matchedProperties.isEmpty()) 787 return false; 788 789 applyMatchedProperties(state, collector.matchedResult()); 790 applyCallbackSelectors(state); 791 792 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); 793 } 794 795 // Cache our original display. 796 state.style()->setOriginalDisplay(state.style()->display()); 797 798 // FIXME: Passing 0 as the Element* introduces a lot of complexity 799 // in the adjustRenderStyle code. 800 adjustRenderStyle(state, 0); 801 802 // FIXME: The CSSWG wants to specify that the effects of animations are applied before 803 // important rules, but this currently happens here as we require adjustment to have happened 804 // before deciding which properties to transition. 805 if (applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId))) 806 adjustRenderStyle(state, 0); 807 808 didAccess(); 809 810 if (state.style()->hasViewportUnits()) 811 document().setHasViewportUnits(); 812 813 return true; 814 } 815 816 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle) 817 { 818 ASSERT(parentStyle); 819 if (!element) 820 return nullptr; 821 822 StyleResolverState state(document(), element, parentStyle); 823 if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state)) { 824 if (pseudoStyleRequest.type == PseudoStyleRequest::ForRenderer) 825 return nullptr; 826 return state.takeStyle(); 827 } 828 829 if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId)) 830 setAnimationUpdateIfNeeded(state, *pseudoElement); 831 832 // Now return the style. 833 return state.takeStyle(); 834 } 835 836 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) 837 { 838 ASSERT(!hasPendingAuthorStyleSheets()); 839 resetDirectionAndWritingModeOnDocument(document()); 840 StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style. 841 842 state.setStyle(RenderStyle::create()); 843 const RenderStyle* rootElementStyle = state.rootElementStyle() ? state.rootElementStyle() : document().renderStyle(); 844 ASSERT(rootElementStyle); 845 state.style()->inheritFrom(rootElementStyle); 846 847 state.fontBuilder().initForStyleResolve(state.document(), state.style()); 848 849 PageRuleCollector collector(rootElementStyle, pageIndex); 850 851 collector.matchPageRules(CSSDefaultStyleSheets::instance().defaultPrintStyle()); 852 853 if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver()) 854 scopedResolver->matchPageRules(collector); 855 856 state.setLineHeightValue(0); 857 bool inheritedOnly = false; 858 859 MatchResult& result = collector.matchedResult(); 860 applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); 861 862 // If our font got dirtied, go ahead and update it now. 863 updateFont(state); 864 865 // Line-height is set when we are sure we decided on the font-size. 866 if (state.lineHeightValue()) 867 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue()); 868 869 applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); 870 871 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); 872 873 loadPendingResources(state); 874 875 didAccess(); 876 877 // Now return the style. 878 return state.takeStyle(); 879 } 880 881 void StyleResolver::collectViewportRules() 882 { 883 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); 884 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultStyle(), ViewportStyleResolver::UserAgentOrigin); 885 886 if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this)) 887 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultViewportStyle(), ViewportStyleResolver::UserAgentOrigin); 888 889 if (document().isMobileDocument()) 890 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin); 891 892 if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver()) 893 scopedResolver->collectViewportRulesTo(this); 894 895 viewportStyleResolver()->resolve(); 896 } 897 898 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement() 899 { 900 StyleResolverState state(document(), 0); 901 state.setStyle(RenderStyle::create()); 902 state.fontBuilder().initForStyleResolve(document(), state.style()); 903 state.style()->setLineHeight(RenderStyle::initialLineHeight()); 904 state.setLineHeightValue(0); 905 state.fontBuilder().setInitial(state.style()->effectiveZoom()); 906 state.style()->font().update(document().styleEngine()->fontSelector()); 907 return state.takeStyle(); 908 } 909 910 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode) 911 { 912 ASSERT(textNode); 913 914 Node* parentNode = NodeRenderingTraversal::parent(textNode); 915 if (!parentNode || !parentNode->renderStyle()) 916 return defaultStyleForElement(); 917 return parentNode->renderStyle(); 918 } 919 920 void StyleResolver::updateFont(StyleResolverState& state) 921 { 922 state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style()); 923 } 924 925 PassRefPtrWillBeRawPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude) 926 { 927 ASSERT(element); 928 StyleResolverState state(document(), element); 929 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); 930 collector.setMode(SelectorChecker::CollectingStyleRules); 931 collectPseudoRulesForElement(element, collector, NOPSEUDO, rulesToInclude); 932 return collector.matchedStyleRuleList(); 933 } 934 935 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude) 936 { 937 ASSERT(element); 938 StyleResolverState state(document(), element); 939 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); 940 collector.setMode(SelectorChecker::CollectingCSSRules); 941 collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude); 942 return collector.matchedCSSRuleList(); 943 } 944 945 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude) 946 { 947 return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude); 948 } 949 950 void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude) 951 { 952 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId)); 953 954 if (rulesToInclude & UAAndUserCSSRules) 955 matchUARules(collector); 956 957 if (rulesToInclude & AuthorCSSRules) { 958 collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules)); 959 matchAuthorRules(element, collector, rulesToInclude & EmptyCSSRules); 960 } 961 } 962 963 // ------------------------------------------------------------------------------------- 964 // this is mostly boring stuff on how to apply a certain rule to the renderstyle... 965 966 bool StyleResolver::applyAnimatedProperties(StyleResolverState& state, const Element* animatingElement) 967 { 968 Element* element = state.element(); 969 ASSERT(element); 970 971 // The animating element may be this element, or its pseudo element. It is 972 // null when calculating the style for a potential pseudo element that has 973 // yet to be created. 974 ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element); 975 976 if (!(animatingElement && animatingElement->hasActiveAnimations()) 977 && !state.style()->transitions() && !state.style()->animations()) 978 return false; 979 980 state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this)); 981 if (!state.animationUpdate()) 982 return false; 983 984 const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations = state.animationUpdate()->activeInterpolationsForAnimations(); 985 const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions = state.animationUpdate()->activeInterpolationsForTransitions(); 986 applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForAnimations); 987 applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForTransitions); 988 989 updateFont(state); 990 991 applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForAnimations); 992 applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForTransitions); 993 994 // Start loading resources used by animations. 995 loadPendingResources(state); 996 997 ASSERT(!state.fontBuilder().fontDirty()); 998 999 return true; 1000 } 1001 1002 static inline ScopedStyleResolver* scopedResolverFor(const Element* element) 1003 { 1004 for (TreeScope* treeScope = &element->treeScope(); treeScope; treeScope = treeScope->parentTreeScope()) { 1005 if (ScopedStyleResolver* scopedStyleResolver = treeScope->scopedStyleResolver()) 1006 return scopedStyleResolver; 1007 } 1008 return 0; 1009 } 1010 1011 void StyleResolver::resolveScopedStyles(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers) 1012 { 1013 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent()) 1014 resolvers.append(scopedResolver); 1015 } 1016 1017 void StyleResolver::collectScopedResolversForHostedShadowTrees(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers) 1018 { 1019 ElementShadow* shadow = element->shadow(); 1020 if (!shadow) 1021 return; 1022 1023 // Adding scoped resolver for active shadow roots for shadow host styling. 1024 for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { 1025 if (shadowRoot->numberOfStyles() > 0) { 1026 if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver()) 1027 resolvers.append(resolver); 1028 } 1029 } 1030 } 1031 1032 void StyleResolver::styleTreeResolveScopedKeyframesRules(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers) 1033 { 1034 TreeScope& treeScope = element->treeScope(); 1035 1036 // Add resolvers for shadow roots hosted by the given element. 1037 collectScopedResolversForHostedShadowTrees(element, resolvers); 1038 1039 // Add resolvers while walking up DOM tree from the given element. 1040 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent()) { 1041 if (scopedResolver->treeScope() == treeScope) 1042 resolvers.append(scopedResolver); 1043 } 1044 } 1045 1046 template <StyleResolver::StyleApplicationPass pass> 1047 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolations) 1048 { 1049 for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = activeInterpolations.begin(); iter != activeInterpolations.end(); ++iter) { 1050 CSSPropertyID property = iter->key; 1051 if (!isPropertyForPass<pass>(property)) 1052 continue; 1053 const StyleInterpolation* interpolation = toStyleInterpolation(iter->value.get()); 1054 interpolation->apply(state); 1055 } 1056 } 1057 1058 static inline bool isValidCueStyleProperty(CSSPropertyID id) 1059 { 1060 switch (id) { 1061 case CSSPropertyBackground: 1062 case CSSPropertyBackgroundAttachment: 1063 case CSSPropertyBackgroundClip: 1064 case CSSPropertyBackgroundColor: 1065 case CSSPropertyBackgroundImage: 1066 case CSSPropertyBackgroundOrigin: 1067 case CSSPropertyBackgroundPosition: 1068 case CSSPropertyBackgroundPositionX: 1069 case CSSPropertyBackgroundPositionY: 1070 case CSSPropertyBackgroundRepeat: 1071 case CSSPropertyBackgroundRepeatX: 1072 case CSSPropertyBackgroundRepeatY: 1073 case CSSPropertyBackgroundSize: 1074 case CSSPropertyColor: 1075 case CSSPropertyFont: 1076 case CSSPropertyFontFamily: 1077 case CSSPropertyFontSize: 1078 case CSSPropertyFontStretch: 1079 case CSSPropertyFontStyle: 1080 case CSSPropertyFontVariant: 1081 case CSSPropertyFontWeight: 1082 case CSSPropertyLineHeight: 1083 case CSSPropertyOpacity: 1084 case CSSPropertyOutline: 1085 case CSSPropertyOutlineColor: 1086 case CSSPropertyOutlineOffset: 1087 case CSSPropertyOutlineStyle: 1088 case CSSPropertyOutlineWidth: 1089 case CSSPropertyVisibility: 1090 case CSSPropertyWhiteSpace: 1091 // FIXME: 'text-decoration' shorthand to be handled when available. 1092 // See https://chromiumcodereview.appspot.com/19516002 for details. 1093 case CSSPropertyTextDecoration: 1094 case CSSPropertyTextShadow: 1095 case CSSPropertyBorderStyle: 1096 return true; 1097 case CSSPropertyTextDecorationLine: 1098 case CSSPropertyTextDecorationStyle: 1099 case CSSPropertyTextDecorationColor: 1100 return RuntimeEnabledFeatures::css3TextDecorationsEnabled(); 1101 default: 1102 break; 1103 } 1104 return false; 1105 } 1106 1107 static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id) 1108 { 1109 switch (id) { 1110 // Valid ::first-letter properties listed in spec: 1111 // http://www.w3.org/TR/css3-selectors/#application-in-css 1112 case CSSPropertyBackgroundAttachment: 1113 case CSSPropertyBackgroundBlendMode: 1114 case CSSPropertyBackgroundClip: 1115 case CSSPropertyBackgroundColor: 1116 case CSSPropertyBackgroundImage: 1117 case CSSPropertyBackgroundOrigin: 1118 case CSSPropertyBackgroundPosition: 1119 case CSSPropertyBackgroundPositionX: 1120 case CSSPropertyBackgroundPositionY: 1121 case CSSPropertyBackgroundRepeat: 1122 case CSSPropertyBackgroundRepeatX: 1123 case CSSPropertyBackgroundRepeatY: 1124 case CSSPropertyBackgroundSize: 1125 case CSSPropertyBorderBottomColor: 1126 case CSSPropertyBorderBottomLeftRadius: 1127 case CSSPropertyBorderBottomRightRadius: 1128 case CSSPropertyBorderBottomStyle: 1129 case CSSPropertyBorderBottomWidth: 1130 case CSSPropertyBorderImageOutset: 1131 case CSSPropertyBorderImageRepeat: 1132 case CSSPropertyBorderImageSlice: 1133 case CSSPropertyBorderImageSource: 1134 case CSSPropertyBorderImageWidth: 1135 case CSSPropertyBorderLeftColor: 1136 case CSSPropertyBorderLeftStyle: 1137 case CSSPropertyBorderLeftWidth: 1138 case CSSPropertyBorderRightColor: 1139 case CSSPropertyBorderRightStyle: 1140 case CSSPropertyBorderRightWidth: 1141 case CSSPropertyBorderTopColor: 1142 case CSSPropertyBorderTopLeftRadius: 1143 case CSSPropertyBorderTopRightRadius: 1144 case CSSPropertyBorderTopStyle: 1145 case CSSPropertyBorderTopWidth: 1146 case CSSPropertyColor: 1147 case CSSPropertyFloat: 1148 case CSSPropertyFont: 1149 case CSSPropertyFontFamily: 1150 case CSSPropertyFontKerning: 1151 case CSSPropertyFontSize: 1152 case CSSPropertyFontStretch: 1153 case CSSPropertyFontStyle: 1154 case CSSPropertyFontVariant: 1155 case CSSPropertyFontVariantLigatures: 1156 case CSSPropertyFontWeight: 1157 case CSSPropertyLetterSpacing: 1158 case CSSPropertyLineHeight: 1159 case CSSPropertyMarginBottom: 1160 case CSSPropertyMarginLeft: 1161 case CSSPropertyMarginRight: 1162 case CSSPropertyMarginTop: 1163 case CSSPropertyPaddingBottom: 1164 case CSSPropertyPaddingLeft: 1165 case CSSPropertyPaddingRight: 1166 case CSSPropertyPaddingTop: 1167 case CSSPropertyTextTransform: 1168 case CSSPropertyVerticalAlign: 1169 case CSSPropertyWebkitBackgroundClip: 1170 case CSSPropertyWebkitBackgroundComposite: 1171 case CSSPropertyWebkitBackgroundOrigin: 1172 case CSSPropertyWebkitBackgroundSize: 1173 case CSSPropertyWebkitBorderAfter: 1174 case CSSPropertyWebkitBorderAfterColor: 1175 case CSSPropertyWebkitBorderAfterStyle: 1176 case CSSPropertyWebkitBorderAfterWidth: 1177 case CSSPropertyWebkitBorderBefore: 1178 case CSSPropertyWebkitBorderBeforeColor: 1179 case CSSPropertyWebkitBorderBeforeStyle: 1180 case CSSPropertyWebkitBorderBeforeWidth: 1181 case CSSPropertyWebkitBorderEnd: 1182 case CSSPropertyWebkitBorderEndColor: 1183 case CSSPropertyWebkitBorderEndStyle: 1184 case CSSPropertyWebkitBorderEndWidth: 1185 case CSSPropertyWebkitBorderFit: 1186 case CSSPropertyWebkitBorderHorizontalSpacing: 1187 case CSSPropertyWebkitBorderImage: 1188 case CSSPropertyWebkitBorderRadius: 1189 case CSSPropertyWebkitBorderStart: 1190 case CSSPropertyWebkitBorderStartColor: 1191 case CSSPropertyWebkitBorderStartStyle: 1192 case CSSPropertyWebkitBorderStartWidth: 1193 case CSSPropertyWebkitBorderVerticalSpacing: 1194 case CSSPropertyWebkitFontSmoothing: 1195 case CSSPropertyWebkitMarginAfter: 1196 case CSSPropertyWebkitMarginAfterCollapse: 1197 case CSSPropertyWebkitMarginBefore: 1198 case CSSPropertyWebkitMarginBeforeCollapse: 1199 case CSSPropertyWebkitMarginBottomCollapse: 1200 case CSSPropertyWebkitMarginCollapse: 1201 case CSSPropertyWebkitMarginEnd: 1202 case CSSPropertyWebkitMarginStart: 1203 case CSSPropertyWebkitMarginTopCollapse: 1204 case CSSPropertyWordSpacing: 1205 return true; 1206 case CSSPropertyTextDecorationColor: 1207 case CSSPropertyTextDecorationLine: 1208 case CSSPropertyTextDecorationStyle: 1209 return RuntimeEnabledFeatures::css3TextDecorationsEnabled(); 1210 1211 // text-shadow added in text decoration spec: 1212 // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property 1213 case CSSPropertyTextShadow: 1214 // box-shadox added in CSS3 backgrounds spec: 1215 // http://www.w3.org/TR/css3-background/#placement 1216 case CSSPropertyBoxShadow: 1217 case CSSPropertyWebkitBoxShadow: 1218 // Properties that we currently support outside of spec. 1219 case CSSPropertyWebkitLineBoxContain: 1220 case CSSPropertyVisibility: 1221 return true; 1222 1223 default: 1224 return false; 1225 } 1226 } 1227 1228 // FIXME: Consider refactoring to create a new class which owns the following 1229 // first/last/range properties. 1230 // This method returns the first CSSPropertyId of high priority properties. 1231 // Other properties can depend on high priority properties. For example, 1232 // border-color property with currentColor value depends on color property. 1233 // All high priority properties are obtained by using 1234 // firstCSSPropertyId<HighPriorityProperties> and 1235 // lastCSSPropertyId<HighPriorityProperties>. 1236 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::HighPriorityProperties>() 1237 { 1238 COMPILE_ASSERT(CSSPropertyColor == firstCSSProperty, CSS_color_is_first_high_priority_property); 1239 return CSSPropertyColor; 1240 } 1241 1242 // This method returns the last CSSPropertyId of high priority properties. 1243 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::HighPriorityProperties>() 1244 { 1245 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyColor + 18, CSS_line_height_is_end_of_high_prioity_property_range); 1246 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyLineHeight - 1, CSS_zoom_is_before_line_height); 1247 return CSSPropertyLineHeight; 1248 } 1249 1250 // This method returns the first CSSPropertyId of remaining properties, 1251 // i.e. low priority properties. No properties depend on low priority 1252 // properties. So we don't need to resolve such properties quickly. 1253 // All low priority properties are obtained by using 1254 // firstCSSPropertyId<LowPriorityProperties> and 1255 // lastCSSPropertyId<LowPriorityProperties>. 1256 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::LowPriorityProperties>() 1257 { 1258 COMPILE_ASSERT(CSSPropertyAlignContent == CSSPropertyLineHeight + 1, CSS_background_is_first_low_priority_property); 1259 return CSSPropertyAlignContent; 1260 } 1261 1262 // This method returns the last CSSPropertyId of low priority properties. 1263 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::LowPriorityProperties>() 1264 { 1265 return static_cast<CSSPropertyID>(lastCSSProperty); 1266 } 1267 1268 template <StyleResolver::StyleApplicationPass pass> 1269 bool StyleResolver::isPropertyForPass(CSSPropertyID property) 1270 { 1271 return firstCSSPropertyId<pass>() <= property && property <= lastCSSPropertyId<pass>(); 1272 } 1273 1274 // This method expands the 'all' shorthand property to longhand properties 1275 // and applies the expanded longhand properties. 1276 template <StyleResolver::StyleApplicationPass pass> 1277 void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue) 1278 { 1279 bool isUnsetValue = !allValue->isInitialValue() && !allValue->isInheritedValue(); 1280 unsigned startCSSProperty = firstCSSPropertyId<pass>(); 1281 unsigned endCSSProperty = lastCSSPropertyId<pass>(); 1282 1283 for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) { 1284 CSSPropertyID propertyId = static_cast<CSSPropertyID>(i); 1285 1286 // StyleBuilder does not allow any expanded shorthands. 1287 if (isExpandedShorthandForAll(propertyId)) 1288 continue; 1289 1290 // all shorthand spec says: 1291 // The all property is a shorthand that resets all CSS properties 1292 // except direction and unicode-bidi. 1293 // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand 1294 // We skip applyProperty when a given property is unicode-bidi or 1295 // direction. 1296 if (!CSSProperty::isAffectedByAllProperty(propertyId)) 1297 continue; 1298 1299 CSSValue* value; 1300 if (!isUnsetValue) { 1301 value = allValue; 1302 } else { 1303 if (CSSPropertyMetadata::isInheritedProperty(propertyId)) 1304 value = cssValuePool().createInheritedValue().get(); 1305 else 1306 value = cssValuePool().createExplicitInitialValue().get(); 1307 } 1308 StyleBuilder::applyProperty(propertyId, state, value); 1309 } 1310 } 1311 1312 template <StyleResolver::StyleApplicationPass pass> 1313 void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType) 1314 { 1315 unsigned propertyCount = properties->propertyCount(); 1316 for (unsigned i = 0; i < propertyCount; ++i) { 1317 StylePropertySet::PropertyReference current = properties->propertyAt(i); 1318 if (isImportant != current.isImportant()) 1319 continue; 1320 1321 CSSPropertyID property = current.id(); 1322 if (property == CSSPropertyAll) { 1323 applyAllProperty<pass>(state, current.value()); 1324 continue; 1325 } 1326 1327 if (inheritedOnly && !current.isInherited()) { 1328 // If the property value is explicitly inherited, we need to apply further non-inherited properties 1329 // as they might override the value inherited here. For this reason we don't allow declarations with 1330 // explicitly inherited properties to be cached. 1331 ASSERT(!current.value()->isInheritedValue()); 1332 continue; 1333 } 1334 1335 if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property)) 1336 continue; 1337 if (propertyWhitelistType == PropertyWhitelistFirstLetter && !isValidFirstLetterStyleProperty(property)) 1338 continue; 1339 if (!isPropertyForPass<pass>(property)) 1340 continue; 1341 if (pass == HighPriorityProperties && property == CSSPropertyLineHeight) 1342 state.setLineHeightValue(current.value()); 1343 else 1344 StyleBuilder::applyProperty(current.id(), state, current.value()); 1345 } 1346 } 1347 1348 template <StyleResolver::StyleApplicationPass pass> 1349 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly) 1350 { 1351 if (startIndex == -1) 1352 return; 1353 1354 if (state.style()->insideLink() != NotInsideLink) { 1355 for (int i = startIndex; i <= endIndex; ++i) { 1356 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i]; 1357 unsigned linkMatchType = matchedProperties.m_types.linkMatchType; 1358 // FIXME: It would be nicer to pass these as arguments but that requires changes in many places. 1359 state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink); 1360 state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited); 1361 1362 applyProperties<pass>(state, matchedProperties.properties.get(), isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.m_types.whitelistType)); 1363 } 1364 state.setApplyPropertyToRegularStyle(true); 1365 state.setApplyPropertyToVisitedLinkStyle(false); 1366 return; 1367 } 1368 for (int i = startIndex; i <= endIndex; ++i) { 1369 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i]; 1370 applyProperties<pass>(state, matchedProperties.properties.get(), isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.m_types.whitelistType)); 1371 } 1372 } 1373 1374 static unsigned computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size) 1375 { 1376 return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size); 1377 } 1378 1379 void StyleResolver::invalidateMatchedPropertiesCache() 1380 { 1381 m_matchedPropertiesCache.clear(); 1382 } 1383 1384 void StyleResolver::notifyResizeForViewportUnits() 1385 { 1386 collectViewportRules(); 1387 m_matchedPropertiesCache.clearViewportDependent(); 1388 } 1389 1390 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult) 1391 { 1392 const Element* element = state.element(); 1393 ASSERT(element); 1394 1395 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply); 1396 1397 unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0; 1398 bool applyInheritedOnly = false; 1399 const CachedMatchedProperties* cachedMatchedProperties = cacheHash ? m_matchedPropertiesCache.find(cacheHash, state, matchResult) : 0; 1400 1401 if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) { 1402 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit); 1403 // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact 1404 // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 1405 // element context. This is fast and saves memory by reusing the style data structures. 1406 state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get()); 1407 if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element) 1408 && (!state.distributedToInsertionPoint() || state.style()->userModify() == READ_ONLY)) { 1409 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit); 1410 1411 EInsideLink linkStatus = state.style()->insideLink(); 1412 // If the cache item parent style has identical inherited properties to the current parent style then the 1413 // resulting style will be identical too. We copy the inherited properties over from the cache and are done. 1414 state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get()); 1415 1416 // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it. 1417 state.style()->setInsideLink(linkStatus); 1418 return; 1419 } 1420 applyInheritedOnly = true; 1421 } 1422 1423 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply 1424 // high-priority properties first, i.e., those properties that other properties depend on. 1425 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important 1426 // and (4) normal important. 1427 state.setLineHeightValue(0); 1428 applyMatchedProperties<HighPriorityProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly); 1429 applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); 1430 applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1431 1432 if (UNLIKELY(isSVGForeignObjectElement(element))) { 1433 // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should not be scaled again. 1434 // 1435 // FIXME: The following hijacks the zoom property for foreignObject so that children of foreignObject get the 1436 // correct font-size in case of zooming. 'zoom' is part of HighPriorityProperties, along with other font-related 1437 // properties used as input to the FontBuilder, so resetting it here may cause the FontBuilder to recompute the 1438 // font used as inheritable font for foreignObject content. If we want to support zoom on foreignObject we'll 1439 // need to find another way of handling the SVG zoom model. 1440 state.setEffectiveZoom(RenderStyle::initialZoom()); 1441 } 1442 1443 if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) { 1444 state.fontBuilder().setFontDirty(true); 1445 applyInheritedOnly = false; 1446 } 1447 1448 // If our font got dirtied, go ahead and update it now. 1449 updateFont(state); 1450 1451 // Line-height is set when we are sure we decided on the font-size. 1452 if (state.lineHeightValue()) 1453 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue()); 1454 1455 // Many properties depend on the font. If it changes we just apply all properties. 1456 if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription()) 1457 applyInheritedOnly = false; 1458 1459 // Now do the normal priority UA properties. 1460 applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1461 1462 // Cache the UA properties to pass them to RenderTheme in adjustRenderStyle. 1463 state.cacheUserAgentBorderAndBackground(); 1464 1465 // Now do the author and user normal priority properties and all the !important properties. 1466 applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly); 1467 applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); 1468 applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1469 1470 loadPendingResources(state); 1471 1472 if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) { 1473 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded); 1474 m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult); 1475 } 1476 1477 ASSERT(!state.fontBuilder().fontDirty()); 1478 } 1479 1480 void StyleResolver::applyCallbackSelectors(StyleResolverState& state) 1481 { 1482 if (!m_watchedSelectorsRules) 1483 return; 1484 1485 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); 1486 collector.setMode(SelectorChecker::CollectingStyleRules); 1487 1488 MatchRequest matchRequest(m_watchedSelectorsRules.get(), true); 1489 RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); 1490 collector.collectMatchingRules(matchRequest, ruleRange); 1491 collector.sortAndTransferMatchedRules(); 1492 1493 RefPtrWillBeRawPtr<StyleRuleList> rules = collector.matchedStyleRuleList(); 1494 if (!rules) 1495 return; 1496 for (size_t i = 0; i < rules->m_list.size(); i++) 1497 state.style()->addCallbackSelector(rules->m_list[i]->selectorList().selectorsText()); 1498 } 1499 1500 CSSPropertyValue::CSSPropertyValue(CSSPropertyID id, const StylePropertySet& propertySet) 1501 : property(id), value(propertySet.getPropertyCSSValue(id).get()) 1502 { } 1503 1504 void StyleResolver::enableStats(StatsReportType reportType) 1505 { 1506 if (m_styleResolverStats) 1507 return; 1508 m_styleResolverStats = StyleResolverStats::create(); 1509 m_styleResolverStatsTotals = StyleResolverStats::create(); 1510 if (reportType == ReportSlowStats) { 1511 m_styleResolverStats->printMissedCandidateCount = true; 1512 m_styleResolverStatsTotals->printMissedCandidateCount = true; 1513 } 1514 } 1515 1516 void StyleResolver::disableStats() 1517 { 1518 m_styleResolverStatsSequence = 0; 1519 m_styleResolverStats.clear(); 1520 m_styleResolverStatsTotals.clear(); 1521 } 1522 1523 void StyleResolver::printStats() 1524 { 1525 if (!m_styleResolverStats) 1526 return; 1527 fprintf(stderr, "=== Style Resolver Stats (resolve #%u) (%s) ===\n", ++m_styleResolverStatsSequence, document().url().string().utf8().data()); 1528 fprintf(stderr, "%s\n", m_styleResolverStats->report().utf8().data()); 1529 fprintf(stderr, "== Totals ==\n"); 1530 fprintf(stderr, "%s\n", m_styleResolverStatsTotals->report().utf8().data()); 1531 } 1532 1533 void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle* style) 1534 { 1535 StyleResolverState state(document(), document().documentElement(), style); 1536 state.setStyle(style); 1537 1538 state.fontBuilder().initForStyleResolve(document(), style); 1539 1540 for (size_t i = 0; i < count; ++i) { 1541 if (properties[i].value) { 1542 // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call, 1543 // which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122). 1544 // The updateFont() call below updates the fontMetrics and ensure the proper setting of font-size and line-height. 1545 switch (properties[i].property) { 1546 case CSSPropertyFontSize: 1547 case CSSPropertyLineHeight: 1548 updateFont(state); 1549 break; 1550 default: 1551 break; 1552 } 1553 StyleBuilder::applyProperty(properties[i].property, state, properties[i].value); 1554 } 1555 } 1556 } 1557 1558 void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list) 1559 { 1560 for (size_t i = 0; i < list.size(); ++i) 1561 m_viewportDependentMediaQueryResults.append(list[i]); 1562 } 1563 1564 bool StyleResolver::mediaQueryAffectedByViewportChange() const 1565 { 1566 for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) { 1567 if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) != m_viewportDependentMediaQueryResults[i]->result()) 1568 return true; 1569 } 1570 return false; 1571 } 1572 1573 void StyleResolver::trace(Visitor* visitor) 1574 { 1575 #if ENABLE(OILPAN) 1576 visitor->trace(m_keyframesRuleMap); 1577 visitor->trace(m_matchedPropertiesCache); 1578 visitor->trace(m_viewportDependentMediaQueryResults); 1579 visitor->trace(m_selectorFilter); 1580 visitor->trace(m_viewportStyleResolver); 1581 visitor->trace(m_features); 1582 visitor->trace(m_siblingRuleSet); 1583 visitor->trace(m_uncommonAttributeRuleSet); 1584 visitor->trace(m_watchedSelectorsRules); 1585 visitor->trace(m_treeBoundaryCrossingRules); 1586 visitor->trace(m_styleSharingLists); 1587 visitor->trace(m_pendingStyleSheets); 1588 visitor->trace(m_document); 1589 #endif 1590 } 1591 1592 } // namespace blink 1593