1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@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@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@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 * Copyright (C) 2014 Igalia S.L. 13 * 14 * This library is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU Library General Public 16 * License as published by the Free Software Foundation; either 17 * version 2 of the License, or (at your option) any later version. 18 * 19 * This library is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * Library General Public License for more details. 23 * 24 * You should have received a copy of the GNU Library General Public License 25 * along with this library; see the file COPYING.LIB. If not, write to 26 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27 * Boston, MA 02110-1301, USA. 28 */ 29 30#include "config.h" 31#include "StyleResolver.h" 32 33#include "Attribute.h" 34#include "CSSBorderImage.h" 35#include "CSSCalculationValue.h" 36#include "CSSCursorImageValue.h" 37#include "CSSDefaultStyleSheets.h" 38#include "CSSFilterImageValue.h" 39#include "CSSFontFaceRule.h" 40#include "CSSFontFeatureValue.h" 41#include "CSSFontSelector.h" 42#include "CSSFontValue.h" 43#include "CSSFunctionValue.h" 44#include "CSSLineBoxContainValue.h" 45#include "CSSPageRule.h" 46#include "CSSParser.h" 47#include "CSSPrimitiveValueMappings.h" 48#include "CSSPropertyNames.h" 49#include "CSSReflectValue.h" 50#include "CSSSelector.h" 51#include "CSSSelectorList.h" 52#include "CSSShadowValue.h" 53#include "CSSStyleRule.h" 54#include "CSSSupportsRule.h" 55#include "CSSTimingFunctionValue.h" 56#include "CSSValueList.h" 57#include "CachedImage.h" 58#include "CachedResourceLoader.h" 59#include "CachedSVGDocument.h" 60#include "CachedSVGDocumentReference.h" 61#include "CalculationValue.h" 62#include "ContentData.h" 63#include "Counter.h" 64#include "CounterContent.h" 65#include "CursorList.h" 66#include "DeprecatedStyleBuilder.h" 67#include "DocumentStyleSheetCollection.h" 68#include "ElementRuleCollector.h" 69#include "Frame.h" 70#include "FrameSelection.h" 71#include "FrameView.h" 72#include "HTMLDocument.h" 73#include "HTMLIFrameElement.h" 74#include "HTMLInputElement.h" 75#include "HTMLNames.h" 76#include "HTMLOptGroupElement.h" 77#include "HTMLOptionElement.h" 78#include "HTMLProgressElement.h" 79#include "HTMLStyleElement.h" 80#include "HTMLTableElement.h" 81#include "HTMLTextAreaElement.h" 82#include "InsertionPoint.h" 83#include "InspectorInstrumentation.h" 84#include "KeyframeList.h" 85#include "LinkHash.h" 86#include "LocaleToScriptMapping.h" 87#include "MathMLNames.h" 88#include "MediaList.h" 89#include "MediaQueryEvaluator.h" 90#include "NodeRenderStyle.h" 91#include "Page.h" 92#include "PageRuleCollector.h" 93#include "Pair.h" 94#include "PseudoElement.h" 95#include "QuotesData.h" 96#include "Rect.h" 97#include "RenderGrid.h" 98#include "RenderRegion.h" 99#include "RenderScrollbar.h" 100#include "RenderScrollbarTheme.h" 101#include "RenderStyleConstants.h" 102#include "RenderTheme.h" 103#include "RenderView.h" 104#include "RuleSet.h" 105#include "SVGDocument.h" 106#include "SVGDocumentExtensions.h" 107#include "SVGElement.h" 108#include "SVGFontFaceElement.h" 109#include "SVGNames.h" 110#include "SVGURIReference.h" 111#include "SecurityOrigin.h" 112#include "Settings.h" 113#include "ShadowData.h" 114#include "ShadowRoot.h" 115#include "StyleCachedImage.h" 116#include "StyleFontSizeFunctions.h" 117#include "StyleGeneratedImage.h" 118#include "StylePendingImage.h" 119#include "StyleProperties.h" 120#include "StylePropertyShorthand.h" 121#include "StyleRule.h" 122#include "StyleRuleImport.h" 123#include "StyleSheetContents.h" 124#include "StyleSheetList.h" 125#include "Text.h" 126#include "TransformFunctions.h" 127#include "TransformOperations.h" 128#include "UserAgentStyleSheets.h" 129#include "ViewportStyleResolver.h" 130#include "VisitedLinkState.h" 131#include "WebKitCSSKeyframeRule.h" 132#include "WebKitCSSKeyframesRule.h" 133#include "WebKitCSSRegionRule.h" 134#include "WebKitCSSTransformValue.h" 135#include "WebKitFontFamilyNames.h" 136#include "XMLNames.h" 137#include <bitset> 138#include <wtf/StdLibExtras.h> 139#include <wtf/Vector.h> 140 141#if ENABLE(CSS_FILTERS) 142#include "FilterOperation.h" 143#include "WebKitCSSFilterValue.h" 144#endif 145 146#if ENABLE(CSS_GRID_LAYOUT) 147#include "CSSGridLineNamesValue.h" 148#include "CSSGridTemplateAreasValue.h" 149#endif 150 151#if ENABLE(CSS_IMAGE_SET) 152#include "CSSImageSetValue.h" 153#include "StyleCachedImageSet.h" 154#endif 155 156#if ENABLE(DASHBOARD_SUPPORT) 157#include "DashboardRegion.h" 158#endif 159 160#if ENABLE(VIDEO_TRACK) 161#include "WebVTTElement.h" 162#endif 163 164namespace WebCore { 165 166using namespace HTMLNames; 167 168class StyleResolver::CascadedProperties { 169public: 170 CascadedProperties(TextDirection, WritingMode); 171 172 struct Property { 173 void apply(StyleResolver&); 174 175 CSSPropertyID id; 176 CSSValue* cssValue[3]; 177 }; 178 179 bool hasProperty(CSSPropertyID id) const; 180 Property& property(CSSPropertyID); 181 bool addMatches(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly = false); 182 183 void set(CSSPropertyID, CSSValue&, unsigned linkMatchType); 184 void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType); 185 186 void applyDeferredProperties(StyleResolver&); 187 188private: 189 bool addStyleProperties(const StyleProperties&, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType); 190 static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType); 191 192 Property m_properties[numCSSProperties + 1]; 193 std::bitset<numCSSProperties + 1> m_propertyIsPresent; 194 195 Vector<Property, 8> m_deferredProperties; 196 197 TextDirection m_direction; 198 WritingMode m_writingMode; 199}; 200 201static void extractDirectionAndWritingMode(const RenderStyle&, const StyleResolver::MatchResult&, TextDirection&, WritingMode&); 202 203#define HANDLE_INHERIT(prop, Prop) \ 204if (isInherit) { \ 205 m_state.style()->set##Prop(m_state.parentStyle()->prop()); \ 206 return; \ 207} 208 209#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ 210HANDLE_INHERIT(prop, Prop) \ 211if (isInitial) { \ 212 m_state.style()->set##Prop(RenderStyle::initial##Prop()); \ 213 return; \ 214} 215 216RenderStyle* StyleResolver::s_styleNotYetAvailable; 217 218inline void StyleResolver::State::cacheBorderAndBackground() 219{ 220 m_hasUAAppearance = m_style->hasAppearance(); 221 if (m_hasUAAppearance) { 222 m_borderData = m_style->border(); 223 m_backgroundData = *m_style->backgroundLayers(); 224 m_backgroundColor = m_style->backgroundColor(); 225 } 226} 227 228inline void StyleResolver::State::clear() 229{ 230 m_element = nullptr; 231 m_styledElement = nullptr; 232 m_parentStyle = nullptr; 233 m_regionForStyling = nullptr; 234 m_pendingImageProperties.clear(); 235#if ENABLE(CSS_FILTERS) 236 m_filtersWithPendingSVGDocuments.clear(); 237#endif 238 m_cssToLengthConversionData = CSSToLengthConversionData(); 239} 240 241void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType) 242{ 243 matchedProperties.grow(matchedProperties.size() + 1); 244 StyleResolver::MatchedProperties& newProperties = matchedProperties.last(); 245 newProperties.properties = const_cast<StyleProperties*>(&properties); 246 newProperties.linkMatchType = linkMatchType; 247 newProperties.whitelistType = propertyWhitelistType; 248 matchedRules.append(rule); 249} 250 251StyleResolver::StyleResolver(Document& document, bool matchAuthorAndUserStyles) 252 : m_matchedPropertiesCacheAdditionsSinceLastSweep(0) 253 , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache) 254 , m_document(document) 255 , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles) 256 , m_fontSelector(CSSFontSelector::create(&m_document)) 257#if ENABLE(CSS_DEVICE_ADAPTATION) 258 , m_viewportStyleResolver(ViewportStyleResolver::create(&document)) 259#endif 260 , m_deprecatedStyleBuilder(DeprecatedStyleBuilder::sharedStyleBuilder()) 261 , m_styleMap(this) 262{ 263 Element* root = m_document.documentElement(); 264 265 CSSDefaultStyleSheets::initDefaultStyle(root); 266 267 // construct document root element default style. this is needed 268 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" 269 // This is here instead of constructor, because when constructor is run, 270 // document doesn't have documentElement 271 // NOTE: this assumes that element that gets passed to styleForElement -call 272 // is always from the document that owns the style selector 273 FrameView* view = m_document.view(); 274 if (view) 275 m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType()); 276 else 277 m_medium = std::make_unique<MediaQueryEvaluator>("all"); 278 279 if (root) 280 m_rootDefaultStyle = styleForElement(root, m_document.renderStyle(), DisallowStyleSharing, MatchOnlyUserAgentRules); 281 282 if (m_rootDefaultStyle && view) 283 m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType(), &view->frame(), m_rootDefaultStyle.get()); 284 285 m_ruleSets.resetAuthorStyle(); 286 287 DocumentStyleSheetCollection& styleSheetCollection = m_document.styleSheetCollection(); 288 m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this); 289 290#if ENABLE(SVG_FONTS) 291 if (m_document.svgExtensions()) { 292 const HashSet<SVGFontFaceElement*>& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements(); 293 HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end(); 294 for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it) 295 fontSelector()->addFontFaceRule((*it)->fontFaceRule()); 296 } 297#endif 298 299 appendAuthorStyleSheets(0, styleSheetCollection.activeAuthorStyleSheets()); 300} 301 302void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet>>& styleSheets) 303{ 304 m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, this); 305 if (auto renderView = document().renderView()) 306 renderView->style().font().update(fontSelector()); 307 308#if ENABLE(CSS_DEVICE_ADAPTATION) 309 viewportStyleResolver()->resolve(); 310#endif 311} 312 313void StyleResolver::pushParentElement(Element* parent) 314{ 315 const ContainerNode* parentsParent = parent->parentOrShadowHostElement(); 316 317 // We are not always invoked consistently. For example, script execution can cause us to enter 318 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree. 319 // Reset the stack in this case, or if we see a new root element. 320 // Otherwise just push the new parent. 321 if (!parentsParent || m_selectorFilter.parentStackIsEmpty()) 322 m_selectorFilter.setupParentStack(parent); 323 else 324 m_selectorFilter.pushParent(parent); 325} 326 327void StyleResolver::popParentElement(Element* parent) 328{ 329 // Note that we may get invoked for some random elements in some wacky cases during style resolve. 330 // Pause maintaining the stack in this case. 331 if (m_selectorFilter.parentStackIsConsistent(parent)) 332 m_selectorFilter.popParent(); 333} 334 335// This is a simplified style setting function for keyframe styles 336void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule) 337{ 338 AtomicString s(rule->name()); 339 m_keyframesRuleMap.set(s.impl(), rule); 340} 341 342StyleResolver::~StyleResolver() 343{ 344 m_fontSelector->clearDocument(); 345 346#if ENABLE(CSS_DEVICE_ADAPTATION) 347 m_viewportStyleResolver->clearDocument(); 348#endif 349} 350 351void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*) 352{ 353 // Look for cache entries containing a style declaration with a single ref and remove them. 354 // This may happen when an element attribute mutation causes it to generate a new inlineStyle() 355 // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one. 356 Vector<unsigned, 16> toRemove; 357 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin(); 358 MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end(); 359 for (; it != end; ++it) { 360 Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties; 361 for (size_t i = 0; i < matchedProperties.size(); ++i) { 362 if (matchedProperties[i].properties->hasOneRef()) { 363 toRemove.append(it->key); 364 break; 365 } 366 } 367 } 368 for (size_t i = 0; i < toRemove.size(); ++i) 369 m_matchedPropertiesCache.remove(toRemove[i]); 370 371 m_matchedPropertiesCacheAdditionsSinceLastSweep = 0; 372} 373 374bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const 375{ 376 for (unsigned i = 0; i < classNames.size(); ++i) { 377 if (m_ruleSets.features().classesInRules.contains(classNames[i].impl())) 378 return true; 379 } 380 return false; 381} 382 383inline void StyleResolver::State::updateConversionData() 384{ 385 m_cssToLengthConversionData = CSSToLengthConversionData(m_style.get(), m_rootElementStyle, m_element ? document().renderView() : nullptr); 386} 387 388inline void StyleResolver::State::initElement(Element* e) 389{ 390 m_element = e; 391 m_styledElement = e && e->isStyledElement() ? toStyledElement(e) : nullptr; 392 m_elementLinkState = e ? e->document().visitedLinkState().determineLinkState(e) : NotInsideLink; 393 updateConversionData(); 394} 395 396inline void StyleResolver::initElement(Element* e) 397{ 398 if (m_state.element() != e) { 399 m_state.initElement(e); 400 if (e && e == e->document().documentElement()) { 401 e->document().setDirectionSetOnDocumentElement(false); 402 e->document().setWritingModeSetOnDocumentElement(false); 403 } 404 } 405} 406 407inline void StyleResolver::State::initForStyleResolve(Document& document, Element* e, RenderStyle* parentStyle, RenderRegion* regionForStyling) 408{ 409 m_regionForStyling = regionForStyling; 410 411 if (e) { 412 bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance(); 413 m_parentStyle = resetStyleInheritance ? nullptr : parentStyle; 414 } else 415 m_parentStyle = parentStyle; 416 417 Node* docElement = e ? e->document().documentElement() : 0; 418 RenderStyle* docStyle = document.renderStyle(); 419 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle; 420 421 m_style = nullptr; 422 m_pendingImageProperties.clear(); 423 m_fontDirty = false; 424 425 updateConversionData(); 426} 427 428inline void StyleResolver::State::setStyle(PassRef<RenderStyle> style) 429{ 430 m_style = WTF::move(style); 431 updateConversionData(); 432} 433 434static const unsigned cStyleSearchThreshold = 10; 435static const unsigned cStyleSearchLevelThreshold = 10; 436 437static inline bool parentElementPreventsSharing(const Element* parentElement) 438{ 439 if (!parentElement) 440 return false; 441 return parentElement->hasFlagsSetDuringStylingOfChildren(); 442} 443 444Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const 445{ 446 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold) 447 return 0; 448 if (!parent || !parent->isStyledElement()) 449 return 0; 450 StyledElement* p = toStyledElement(parent); 451 if (p->inlineStyle()) 452 return 0; 453 if (p->isSVGElement() && toSVGElement(p)->animatedSMILStyleProperties()) 454 return 0; 455 if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleResolution().impl())) 456 return 0; 457 458 RenderStyle* parentStyle = p->renderStyle(); 459 unsigned subcount = 0; 460 Node* thisCousin = p; 461 Node* currentNode = p->previousSibling(); 462 463 // Reserve the tries for this level. This effectively makes sure that the algorithm 464 // will never go deeper than cStyleSearchLevelThreshold levels into recursion. 465 visitedNodeCount += cStyleSearchThreshold; 466 while (thisCousin) { 467 while (currentNode) { 468 ++subcount; 469 if (currentNode->renderStyle() == parentStyle && currentNode->lastChild() 470 && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode)) 471 ) { 472 // Adjust for unused reserved tries. 473 visitedNodeCount -= cStyleSearchThreshold - subcount; 474 return currentNode->lastChild(); 475 } 476 if (subcount >= cStyleSearchThreshold) 477 return 0; 478 currentNode = currentNode->previousSibling(); 479 } 480 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount); 481 thisCousin = currentNode; 482 } 483 484 return 0; 485} 486 487bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet) 488{ 489 if (!ruleSet) 490 return false; 491 492 ElementRuleCollector collector(*m_state.element(), m_state.style(), m_ruleSets, m_selectorFilter); 493 return collector.hasAnyMatchingRules(ruleSet); 494} 495 496bool StyleResolver::canShareStyleWithControl(StyledElement* element) const 497{ 498 const State& state = m_state; 499 HTMLInputElement* thisInputElement = element->toInputElement(); 500 HTMLInputElement* otherInputElement = state.element()->toInputElement(); 501 502 if (!thisInputElement || !otherInputElement) 503 return false; 504 505 if (thisInputElement->elementData() != otherInputElement->elementData()) { 506 if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr)) 507 return false; 508 if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr)) 509 return false; 510 } 511 512 if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) 513 return false; 514 if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked()) 515 return false; 516 if (thisInputElement->shouldAppearIndeterminate() != otherInputElement->shouldAppearIndeterminate()) 517 return false; 518 if (thisInputElement->isRequired() != otherInputElement->isRequired()) 519 return false; 520 521 if (element->isDisabledFormControl() != state.element()->isDisabledFormControl()) 522 return false; 523 524 if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonForForm()) 525 return false; 526 527 if (state.document().containsValidityStyleRules()) { 528 bool willValidate = element->willValidate(); 529 530 if (willValidate != state.element()->willValidate()) 531 return false; 532 533 if (willValidate && (element->isValidFormControlElement() != state.element()->isValidFormControlElement())) 534 return false; 535 536 if (element->isInRange() != state.element()->isInRange()) 537 return false; 538 539 if (element->isOutOfRange() != state.element()->isOutOfRange()) 540 return false; 541 } 542 543 return true; 544} 545 546static inline bool elementHasDirectionAuto(Element* element) 547{ 548 // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver. 549 return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto(); 550} 551 552bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement* sharingCandidate) const 553{ 554 const State& state = m_state; 555 if (state.element()->elementData() == sharingCandidate->elementData()) 556 return true; 557 if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate->fastGetAttribute(XMLNames::langAttr)) 558 return false; 559 if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGetAttribute(langAttr)) 560 return false; 561 562 if (!state.elementAffectedByClassRules()) { 563 if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCandidate->classNames())) 564 return false; 565 } else if (sharingCandidate->hasClass()) { 566 // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG. 567 if (state.element()->isSVGElement()) { 568 if (state.element()->getAttribute(classAttr) != sharingCandidate->getAttribute(classAttr)) 569 return false; 570 } else { 571 if (state.element()->classNames() != sharingCandidate->classNames()) 572 return false; 573 } 574 } else 575 return false; 576 577 if (state.styledElement()->presentationAttributeStyle() != sharingCandidate->presentationAttributeStyle()) 578 return false; 579 580 if (state.element()->hasTagName(progressTag)) { 581 if (state.element()->shouldAppearIndeterminate() != sharingCandidate->shouldAppearIndeterminate()) 582 return false; 583 } 584 585 return true; 586} 587 588bool StyleResolver::canShareStyleWithElement(StyledElement* element) const 589{ 590 RenderStyle* style = element->renderStyle(); 591 const State& state = m_state; 592 593 if (!style) 594 return false; 595 if (style->unique()) 596 return false; 597 if (style->hasUniquePseudoStyle()) 598 return false; 599 if (element->tagQName() != state.element()->tagQName()) 600 return false; 601 if (element->inlineStyle()) 602 return false; 603 if (element->needsStyleRecalc()) 604 return false; 605 if (element->isSVGElement() && toSVGElement(element)->animatedSMILStyleProperties()) 606 return false; 607 if (element->isLink() != state.element()->isLink()) 608 return false; 609 if (element->hovered() != state.element()->hovered()) 610 return false; 611 if (element->active() != state.element()->active()) 612 return false; 613 if (element->focused() != state.element()->focused()) 614 return false; 615 if (element->shadowPseudoId() != state.element()->shadowPseudoId()) 616 return false; 617 if (element == element->document().cssTarget()) 618 return false; 619 if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element)) 620 return false; 621 if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle()) 622 return false; 623 624 if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl())) 625 return false; 626 627 // FIXME: We should share style for option and optgroup whenever possible. 628 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems 629 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405 630 if (isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) 631 return false; 632 633 bool isControl = element->isFormControlElement(); 634 635 if (isControl != state.element()->isFormControlElement()) 636 return false; 637 638 if (isControl && !canShareStyleWithControl(element)) 639 return false; 640 641 if (style->transitions() || style->animations()) 642 return false; 643 644 // Turn off style sharing for elements that can gain layers for reasons outside of the style system. 645 // See comments in RenderObject::setStyle(). 646 if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag)) 647 return false; 648 649 if (elementHasDirectionAuto(element)) 650 return false; 651 652 if (element->isLink() && state.elementLinkState() != style->insideLink()) 653 return false; 654 655#if ENABLE(VIDEO_TRACK) 656 // Deny sharing styles between WebVTT and non-WebVTT nodes. 657 if (element->isWebVTTElement() != state.element()->isWebVTTElement()) 658 return false; 659 660 if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWebVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNode()) 661 return false; 662#endif 663 664#if ENABLE(FULLSCREEN_API) 665 if (element == element->document().webkitCurrentFullScreenElement() || state.element() == state.document().webkitCurrentFullScreenElement()) 666 return false; 667#endif 668 return true; 669} 670 671inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const 672{ 673 for (; node; node = node->previousSibling()) { 674 if (!node->isStyledElement()) 675 continue; 676 if (canShareStyleWithElement(toStyledElement(node))) 677 break; 678 if (count++ == cStyleSearchThreshold) 679 return 0; 680 } 681 return toStyledElement(node); 682} 683 684RenderStyle* StyleResolver::locateSharedStyle() 685{ 686 State& state = m_state; 687 if (!state.styledElement() || !state.parentStyle()) 688 return 0; 689 690 // If the element has inline style it is probably unique. 691 if (state.styledElement()->inlineStyle()) 692 return 0; 693 if (state.styledElement()->isSVGElement() && toSVGElement(state.styledElement())->animatedSMILStyleProperties()) 694 return 0; 695 // Ids stop style sharing if they show up in the stylesheets. 696 if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl())) 697 return 0; 698 if (parentElementPreventsSharing(state.element()->parentElement())) 699 return 0; 700 if (state.element() == state.document().cssTarget()) 701 return 0; 702 if (elementHasDirectionAuto(state.element())) 703 return 0; 704 705 // Cache whether state.element is affected by any known class selectors. 706 // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver. 707 state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames())); 708 709 // Check previous siblings and their cousins. 710 unsigned count = 0; 711 unsigned visitedNodeCount = 0; 712 StyledElement* shareElement = 0; 713 Node* cousinList = state.styledElement()->previousSibling(); 714 while (cousinList) { 715 shareElement = findSiblingForStyleSharing(cousinList, count); 716 if (shareElement) 717 break; 718 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount); 719 } 720 721 // If we have exhausted all our budget or our cousins. 722 if (!shareElement) 723 return 0; 724 725 // Can't share if sibling rules apply. This is checked at the end as it should rarely fail. 726 if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling())) 727 return 0; 728 // Can't share if attribute rules apply. 729 if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute())) 730 return 0; 731 // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. 732 if (parentElementPreventsSharing(state.element()->parentElement())) 733 return 0; 734 return shareElement->renderStyle(); 735} 736 737static inline bool isAtShadowBoundary(const Element* element) 738{ 739 if (!element) 740 return false; 741 ContainerNode* parentNode = element->parentNode(); 742 return parentNode && parentNode->isShadowRoot(); 743} 744 745PassRef<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, 746 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) 747{ 748 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer 749 // will vanish if a style recalc happens during loading. 750 if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) { 751 if (!s_styleNotYetAvailable) { 752 s_styleNotYetAvailable = &RenderStyle::create().leakRef(); 753 s_styleNotYetAvailable->setDisplay(NONE); 754 s_styleNotYetAvailable->font().update(m_fontSelector); 755 } 756 element->document().setHasNodesWithPlaceholderStyle(); 757 return *s_styleNotYetAvailable; 758 } 759 760 State& state = m_state; 761 initElement(element); 762 state.initForStyleResolve(document(), element, defaultParent, regionForStyling); 763 if (sharingBehavior == AllowStyleSharing) { 764 if (RenderStyle* sharedStyle = locateSharedStyle()) { 765 state.clear(); 766 return *sharedStyle; 767 } 768 } 769 770 if (state.parentStyle()) { 771 state.setStyle(RenderStyle::create()); 772 state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary); 773 } else { 774 state.setStyle(defaultStyleForElement()); 775 state.setParentStyle(RenderStyle::clone(state.style())); 776 } 777 778 if (element->isLink()) { 779 state.style()->setIsLink(true); 780 EInsideLink linkState = state.elementLinkState(); 781 if (linkState != NotInsideLink) { 782 bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoClassVisited); 783 if (forceVisited) 784 linkState = InsideVisitedLink; 785 } 786 state.style()->setInsideLink(linkState); 787 } 788 789 bool needsCollection = false; 790 CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection); 791 if (needsCollection) 792 m_ruleSets.collectFeatures(); 793 794 ElementRuleCollector collector(*element, state.style(), m_ruleSets, m_selectorFilter); 795 collector.setRegionForStyling(regionForStyling); 796 collector.setMedium(m_medium.get()); 797 798 if (matchingBehavior == MatchOnlyUserAgentRules) 799 collector.matchUARules(); 800 else 801 collector.matchAllRules(m_matchAuthorAndUserStyles, matchingBehavior != MatchAllRulesExcludingSMIL); 802 803 applyMatchedProperties(collector.matchedResult(), element); 804 805 // Clean up our style object's display and text decorations (among other fixups). 806 adjustRenderStyle(*state.style(), *state.parentStyle(), element); 807 808 if (state.style()->hasViewportUnits()) 809 document().setHasStyleWithViewportUnits(); 810 811 state.clear(); // Clear out for the next resolve. 812 813 // Now return the style. 814 return state.takeStyle(); 815} 816 817PassRef<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue) 818{ 819 MatchResult result; 820 result.addMatchedProperties(keyframe->properties()); 821 822 ASSERT(!m_state.style()); 823 824 State& state = m_state; 825 826 // Create the style 827 state.setStyle(RenderStyle::clone(elementStyle)); 828 state.setParentStyle(RenderStyle::clone(elementStyle)); 829 state.setLineHeightValue(0); 830 831 TextDirection direction; 832 WritingMode writingMode; 833 extractDirectionAndWritingMode(*state.style(), result, direction, writingMode); 834 835 // We don't need to bother with !important. Since there is only ever one 836 // decl, there's nothing to override. So just add the first properties. 837 CascadedProperties cascade(direction, writingMode); 838 cascade.addMatches(result, false, 0, result.matchedProperties.size() - 1); 839 840 applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight); 841 842 // If our font got dirtied, go ahead and update it now. 843 updateFont(); 844 845 // Line-height is set when we are sure we decided on the font-size 846 if (state.lineHeightValue()) 847 applyProperty(CSSPropertyLineHeight, state.lineHeightValue()); 848 849 // Now do rest of the properties. 850 applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty); 851 852 // If our font got dirtied by one of the non-essential font props, 853 // go ahead and update it a second time. 854 updateFont(); 855 856 cascade.applyDeferredProperties(*this); 857 858 // Start loading resources referenced by this style. 859 loadPendingResources(); 860 861 // Add all the animating properties to the keyframe. 862 unsigned propertyCount = keyframe->properties().propertyCount(); 863 for (unsigned i = 0; i < propertyCount; ++i) { 864 CSSPropertyID property = keyframe->properties().propertyAt(i).id(); 865 // Timing-function within keyframes is special, because it is not animated; it just 866 // describes the timing function between this keyframe and the next. 867 if (property != CSSPropertyWebkitAnimationTimingFunction) 868 keyframeValue.addProperty(property); 869 } 870 871 return state.takeStyle(); 872} 873 874void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list) 875{ 876 list.clear(); 877 878 // Get the keyframesRule for this name 879 if (!e || list.animationName().isEmpty()) 880 return; 881 882 m_keyframesRuleMap.checkConsistency(); 883 884 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl()); 885 if (it == m_keyframesRuleMap.end()) 886 return; 887 888 const StyleRuleKeyframes* keyframesRule = it->value.get(); 889 890 // Construct and populate the style for each keyframe 891 const Vector<RefPtr<StyleKeyframe>>& keyframes = keyframesRule->keyframes(); 892 for (unsigned i = 0; i < keyframes.size(); ++i) { 893 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement 894 initElement(e); 895 m_state.initForStyleResolve(document(), e, nullptr); 896 897 const StyleKeyframe* keyframe = keyframes[i].get(); 898 899 KeyframeValue keyframeValue(0, 0); 900 keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue)); 901 902 // Add this keyframe style to all the indicated key times 903 Vector<double> keys; 904 keyframe->getKeys(keys); 905 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) { 906 keyframeValue.setKey(keys[keyIndex]); 907 list.insert(keyframeValue); 908 } 909 } 910 911 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe) 912 int initialListSize = list.size(); 913 if (initialListSize > 0 && list[0].key()) { 914 static StyleKeyframe* zeroPercentKeyframe; 915 if (!zeroPercentKeyframe) { 916 zeroPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef(); 917 zeroPercentKeyframe->setKeyText("0%"); 918 } 919 KeyframeValue keyframeValue(0, 0); 920 keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue)); 921 list.insert(keyframeValue); 922 } 923 924 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe) 925 if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) { 926 static StyleKeyframe* hundredPercentKeyframe; 927 if (!hundredPercentKeyframe) { 928 hundredPercentKeyframe = StyleKeyframe::create(MutableStyleProperties::create()).leakRef(); 929 hundredPercentKeyframe->setKeyText("100%"); 930 } 931 KeyframeValue keyframeValue(1, 0); 932 keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue)); 933 list.insert(keyframeValue); 934 } 935} 936 937PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle) 938{ 939 ASSERT(parentStyle); 940 if (!element) 941 return 0; 942 943 State& state = m_state; 944 945 initElement(element); 946 947 state.initForStyleResolve(document(), element, parentStyle); 948 949 if (m_state.parentStyle()) { 950 state.setStyle(RenderStyle::create()); 951 state.style()->inheritFrom(m_state.parentStyle()); 952 } else { 953 state.setStyle(defaultStyleForElement()); 954 state.setParentStyle(RenderStyle::clone(state.style())); 955 } 956 957 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking 958 // those rules. 959 960 // Check UA, user and author rules. 961 ElementRuleCollector collector(*element, m_state.style(), m_ruleSets, m_selectorFilter); 962 collector.setPseudoStyleRequest(pseudoStyleRequest); 963 collector.setMedium(m_medium.get()); 964 collector.matchUARules(); 965 966 if (m_matchAuthorAndUserStyles) { 967 collector.matchUserRules(false); 968 collector.matchAuthorRules(false); 969 } 970 971 if (collector.matchedResult().matchedProperties.isEmpty()) 972 return 0; 973 974 state.style()->setStyleType(pseudoStyleRequest.pseudoId); 975 976 applyMatchedProperties(collector.matchedResult(), element); 977 978 // Clean up our style object's display and text decorations (among other fixups). 979 adjustRenderStyle(*state.style(), *m_state.parentStyle(), 0); 980 981 if (state.style()->hasViewportUnits()) 982 document().setHasStyleWithViewportUnits(); 983 984 // Start loading resources referenced by this style. 985 loadPendingResources(); 986 987 // Now return the style. 988 return state.takeStyle(); 989} 990 991PassRef<RenderStyle> StyleResolver::styleForPage(int pageIndex) 992{ 993 m_state.initForStyleResolve(m_document, m_document.documentElement(), m_document.renderStyle()); 994 995 m_state.setStyle(RenderStyle::create()); 996 m_state.style()->inheritFrom(m_state.rootElementStyle()); 997 998 PageRuleCollector collector(m_state, m_ruleSets); 999 collector.matchAllPageRules(pageIndex); 1000 m_state.setLineHeightValue(0); 1001 1002 MatchResult& result = collector.matchedResult(); 1003 1004 TextDirection direction; 1005 WritingMode writingMode; 1006 extractDirectionAndWritingMode(*m_state.style(), result, direction, writingMode); 1007 1008 CascadedProperties cascade(direction, writingMode); 1009 cascade.addMatches(result, false, 0, result.matchedProperties.size() - 1); 1010 1011 applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight); 1012 1013 // If our font got dirtied, go ahead and update it now. 1014 updateFont(); 1015 1016 // Line-height is set when we are sure we decided on the font-size. 1017 if (m_state.lineHeightValue()) 1018 applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue()); 1019 1020 applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty); 1021 1022 cascade.applyDeferredProperties(*this); 1023 1024 // Start loading resources referenced by this style. 1025 loadPendingResources(); 1026 1027 // Now return the style. 1028 return m_state.takeStyle(); 1029} 1030 1031PassRef<RenderStyle> StyleResolver::defaultStyleForElement() 1032{ 1033 m_state.setStyle(RenderStyle::create()); 1034 // Make sure our fonts are initialized if we don't inherit them from our parent style. 1035 if (Settings* settings = documentSettings()) { 1036 initializeFontStyle(settings); 1037 m_state.style()->font().update(fontSelector()); 1038 } else 1039 m_state.style()->font().update(0); 1040 1041 return m_state.takeStyle(); 1042} 1043 1044static void addIntrinsicMargins(RenderStyle& style) 1045{ 1046 // Intrinsic margin value. 1047 const int intrinsicMargin = 2 * style.effectiveZoom(); 1048 1049 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. 1050 // FIXME: Using "hasQuirk" to decide the margin wasn't set is kind of lame. 1051 if (style.width().isIntrinsicOrAuto()) { 1052 if (style.marginLeft().hasQuirk()) 1053 style.setMarginLeft(Length(intrinsicMargin, Fixed)); 1054 if (style.marginRight().hasQuirk()) 1055 style.setMarginRight(Length(intrinsicMargin, Fixed)); 1056 } 1057 1058 if (style.height().isAuto()) { 1059 if (style.marginTop().hasQuirk()) 1060 style.setMarginTop(Length(intrinsicMargin, Fixed)); 1061 if (style.marginBottom().hasQuirk()) 1062 style.setMarginBottom(Length(intrinsicMargin, Fixed)); 1063 } 1064} 1065 1066static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing) 1067{ 1068 switch (display) { 1069 case BLOCK: 1070 case TABLE: 1071 case BOX: 1072 case FLEX: 1073#if ENABLE(CSS_GRID_LAYOUT) 1074 case GRID: 1075#endif 1076 return display; 1077 1078 case LIST_ITEM: 1079 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode. 1080 if (!strictParsing && isFloating) 1081 return BLOCK; 1082 return display; 1083 case INLINE_TABLE: 1084 return TABLE; 1085 case INLINE_BOX: 1086 return BOX; 1087 case INLINE_FLEX: 1088 return FLEX; 1089#if ENABLE(CSS_GRID_LAYOUT) 1090 case INLINE_GRID: 1091 return GRID; 1092#endif 1093 1094 case INLINE: 1095 case COMPACT: 1096 case INLINE_BLOCK: 1097 case TABLE_ROW_GROUP: 1098 case TABLE_HEADER_GROUP: 1099 case TABLE_FOOTER_GROUP: 1100 case TABLE_ROW: 1101 case TABLE_COLUMN_GROUP: 1102 case TABLE_COLUMN: 1103 case TABLE_CELL: 1104 case TABLE_CAPTION: 1105 return BLOCK; 1106 case NONE: 1107 ASSERT_NOT_REACHED(); 1108 return NONE; 1109 } 1110 ASSERT_NOT_REACHED(); 1111 return BLOCK; 1112} 1113 1114// CSS requires text-decoration to be reset at each DOM element for tables, 1115// inline blocks, inline tables, shadow DOM crossings, floating elements, 1116// and absolute or relatively positioned elements. 1117static bool doesNotInheritTextDecoration(const RenderStyle& style, Element* e) 1118{ 1119 return style.display() == TABLE || style.display() == INLINE_TABLE 1120 || style.display() == INLINE_BLOCK || style.display() == INLINE_BOX || isAtShadowBoundary(e) 1121 || style.isFloating() || style.hasOutOfFlowPosition(); 1122} 1123 1124static bool isDisplayFlexibleBox(EDisplay display) 1125{ 1126 return display == FLEX || display == INLINE_FLEX; 1127} 1128 1129static inline bool isDisplayGridBox(EDisplay display) 1130{ 1131#if ENABLE(CSS_GRID_LAYOUT) 1132 return display == GRID || display == INLINE_GRID; 1133#else 1134 UNUSED_PARAM(display); 1135 return false; 1136#endif 1137} 1138 1139static bool isDisplayFlexibleOrGridBox(EDisplay display) 1140{ 1141 return isDisplayFlexibleBox(display) || isDisplayGridBox(display); 1142} 1143 1144#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) 1145static bool isScrollableOverflow(EOverflow overflow) 1146{ 1147 return overflow == OSCROLL || overflow == OAUTO || overflow == OOVERLAY; 1148} 1149#endif 1150 1151void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& parentStyle, Element *e) 1152{ 1153 // Cache our original display. 1154 style.setOriginalDisplay(style.display()); 1155 1156 if (style.display() != NONE) { 1157 // If we have a <td> that specifies a float property, in quirks mode we just drop the float 1158 // property. 1159 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force 1160 // these tags to retain their display types. 1161 if (document().inQuirksMode() && e) { 1162 if (e->hasTagName(tdTag)) { 1163 style.setDisplay(TABLE_CELL); 1164 style.setFloating(NoFloat); 1165 } else if (isHTMLTableElement(e)) 1166 style.setDisplay(style.isDisplayInlineType() ? INLINE_TABLE : TABLE); 1167 } 1168 1169 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) { 1170 if (style.whiteSpace() == KHTML_NOWRAP) { 1171 // Figure out if we are really nowrapping or if we should just 1172 // use normal instead. If the width of the cell is fixed, then 1173 // we don't actually use NOWRAP. 1174 if (style.width().isFixed()) 1175 style.setWhiteSpace(NORMAL); 1176 else 1177 style.setWhiteSpace(NOWRAP); 1178 } 1179 } 1180 1181 // Tables never support the -webkit-* values for text-align and will reset back to the default. 1182 if (e && isHTMLTableElement(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT)) 1183 style.setTextAlign(TASTART); 1184 1185 // Frames and framesets never honor position:relative or position:absolute. This is necessary to 1186 // fix a crash where a site tries to position these objects. They also never honor display. 1187 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { 1188 style.setPosition(StaticPosition); 1189 style.setDisplay(BLOCK); 1190 } 1191 1192 // Ruby text does not support float or position. This might change with evolution of the specification. 1193 if (e && e->hasTagName(rtTag)) { 1194 style.setPosition(StaticPosition); 1195 style.setFloating(NoFloat); 1196 } 1197 1198 // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead. 1199 // Table headers with a text-align of -webkit-auto will change the text-align to center. 1200 if (e && e->hasTagName(thTag) && style.textAlign() == TASTART) 1201 style.setTextAlign(CENTER); 1202 1203 if (e && e->hasTagName(legendTag)) 1204 style.setDisplay(BLOCK); 1205 1206 // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display. 1207 if (style.hasOutOfFlowPosition() || style.isFloating() || (e && e->document().documentElement() == e)) 1208 style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode())); 1209 1210 // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely 1211 // clear how that should work. 1212 if (style.display() == INLINE && style.styleType() == NOPSEUDO && style.writingMode() != parentStyle.writingMode()) 1213 style.setDisplay(INLINE_BLOCK); 1214 1215 // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on 1216 // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock() 1217 // on some sites). 1218 if ((style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW_GROUP 1219 || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW) 1220 && style.position() == RelativePosition) 1221 style.setPosition(StaticPosition); 1222 1223 // writing-mode does not apply to table row groups, table column groups, table rows, and table columns. 1224 // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though. 1225 if (style.display() == TABLE_COLUMN || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_FOOTER_GROUP 1226 || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW || style.display() == TABLE_ROW_GROUP 1227 || style.display() == TABLE_CELL) 1228 style.setWritingMode(parentStyle.writingMode()); 1229 1230 // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting 1231 // of block-flow to anything other than TopToBottomWritingMode. 1232 // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support. 1233 if (style.writingMode() != TopToBottomWritingMode && (style.display() == BOX || style.display() == INLINE_BOX)) 1234 style.setWritingMode(TopToBottomWritingMode); 1235 1236 if (isDisplayFlexibleOrGridBox(parentStyle.display())) { 1237 style.setFloating(NoFloat); 1238 style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode())); 1239 } 1240 } 1241 1242 // Make sure our z-index value is only applied if the object is positioned. 1243 if (style.position() == StaticPosition && !isDisplayFlexibleOrGridBox(parentStyle.display())) 1244 style.setHasAutoZIndex(); 1245 1246 // Auto z-index becomes 0 for the root element and transparent objects. This prevents 1247 // cases where objects that should be blended as a single unit end up with a non-transparent 1248 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections. 1249 if (style.hasAutoZIndex() && ((e && e->document().documentElement() == e) 1250 || style.opacity() < 1.0f 1251 || style.hasTransformRelatedProperty() 1252 || style.hasMask() 1253 || style.clipPath() 1254 || style.boxReflect() 1255 || style.hasFilter() 1256 || style.hasBlendMode() 1257 || style.hasIsolation() 1258 || style.position() == StickyPosition 1259 || (style.position() == FixedPosition && e && e->document().page() && e->document().page()->settings().fixedPositionCreatesStackingContext()) 1260 || style.hasFlowFrom() 1261 )) 1262 style.setZIndex(0); 1263 1264 // Textarea considers overflow visible as auto. 1265 if (e && isHTMLTextAreaElement(e)) { 1266 style.setOverflowX(style.overflowX() == OVISIBLE ? OAUTO : style.overflowX()); 1267 style.setOverflowY(style.overflowY() == OVISIBLE ? OAUTO : style.overflowY()); 1268 } 1269 1270 // Disallow -webkit-user-modify on :pseudo and ::pseudo elements. 1271 if (e && !e->shadowPseudoId().isNull()) 1272 style.setUserModify(READ_ONLY); 1273 1274 if (doesNotInheritTextDecoration(style, e)) 1275 style.setTextDecorationsInEffect(style.textDecoration()); 1276 else 1277 style.addToTextDecorationsInEffect(style.textDecoration()); 1278 1279 // If either overflow value is not visible, change to auto. 1280 if (style.overflowX() == OMARQUEE && style.overflowY() != OMARQUEE) 1281 style.setOverflowY(OMARQUEE); 1282 else if (style.overflowY() == OMARQUEE && style.overflowX() != OMARQUEE) 1283 style.setOverflowX(OMARQUEE); 1284 else if (style.overflowX() == OVISIBLE && style.overflowY() != OVISIBLE) { 1285 // FIXME: Once we implement pagination controls, overflow-x should default to hidden 1286 // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it 1287 // default to auto so we can at least scroll through the pages. 1288 style.setOverflowX(OAUTO); 1289 } else if (style.overflowY() == OVISIBLE && style.overflowX() != OVISIBLE) 1290 style.setOverflowY(OAUTO); 1291 1292 // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these 1293 // styles are specified on a root element, then they will be incorporated in 1294 // Style::createForDocument(). 1295 if ((style.overflowY() == OPAGEDX || style.overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag)))) 1296 style.setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style)); 1297 1298 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. 1299 // FIXME: Eventually table sections will support auto and scroll. 1300 if (style.display() == TABLE || style.display() == INLINE_TABLE 1301 || style.display() == TABLE_ROW_GROUP || style.display() == TABLE_ROW) { 1302 if (style.overflowX() != OVISIBLE && style.overflowX() != OHIDDEN) 1303 style.setOverflowX(OVISIBLE); 1304 if (style.overflowY() != OVISIBLE && style.overflowY() != OHIDDEN) 1305 style.setOverflowY(OVISIBLE); 1306 } 1307 1308 // Menulists should have visible overflow 1309 if (style.appearance() == MenulistPart) { 1310 style.setOverflowX(OVISIBLE); 1311 style.setOverflowY(OVISIBLE); 1312 } 1313 1314#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) 1315 // Touch overflow scrolling creates a stacking context. 1316 if (style.hasAutoZIndex() && style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY()))) 1317 style.setZIndex(0); 1318#endif 1319 1320 // Cull out any useless layers and also repeat patterns into additional layers. 1321 style.adjustBackgroundLayers(); 1322 style.adjustMaskLayers(); 1323 1324 // Do the same for animations and transitions. 1325 style.adjustAnimations(); 1326 style.adjustTransitions(); 1327 1328 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will 1329 // alter fonts and heights/widths. 1330 if (e && e->isFormControlElement() && style.fontSize() >= 11) { 1331 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, 1332 // so we have to treat all image buttons as though they were explicitly sized. 1333 if (!isHTMLInputElement(e) || !toHTMLInputElement(e)->isImageButton()) 1334 addIntrinsicMargins(style); 1335 } 1336 1337 // Let the theme also have a crack at adjusting the style. 1338 if (style.hasAppearance()) { 1339 ASSERT(e); 1340 RenderTheme::defaultTheme()->adjustStyle(*this, style, *e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor()); 1341 } 1342 1343 // If we have first-letter pseudo style, do not share this style. 1344 if (style.hasPseudoStyle(FIRST_LETTER)) 1345 style.setUnique(); 1346 1347 // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening. 1348 if (style.preserves3D() && (style.overflowX() != OVISIBLE 1349 || style.overflowY() != OVISIBLE 1350 || style.hasFilter() 1351 || style.hasBlendMode())) 1352 style.setTransformStyle3D(TransformStyle3DFlat); 1353 1354 if (e && e->isSVGElement()) { 1355 // Only the root <svg> element in an SVG document fragment tree honors css position 1356 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) 1357 style.setPosition(RenderStyle::NonInheritedFlags::initialPosition()); 1358 1359 // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should 1360 // not be scaled again. 1361 if (e->hasTagName(SVGNames::foreignObjectTag)) 1362 style.setEffectiveZoom(RenderStyle::initialZoom()); 1363 1364 // SVG text layout code expects us to be a block-level style element. 1365 if ((e->hasTagName(SVGNames::foreignObjectTag) || e->hasTagName(SVGNames::textTag)) && style.isDisplayInlineType()) 1366 style.setDisplay(BLOCK); 1367 } 1368} 1369 1370bool StyleResolver::checkRegionStyle(Element* regionElement) 1371{ 1372 unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size(); 1373 for (unsigned i = 0; i < rulesSize; ++i) { 1374 ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get()); 1375 if (checkRegionSelector(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement)) 1376 return true; 1377 } 1378 1379 if (m_ruleSets.userStyle()) { 1380 rulesSize = m_ruleSets.userStyle()->regionSelectorsAndRuleSets().size(); 1381 for (unsigned i = 0; i < rulesSize; ++i) { 1382 ASSERT(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get()); 1383 if (checkRegionSelector(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement)) 1384 return true; 1385 } 1386 } 1387 1388 return false; 1389} 1390 1391static void checkForOrientationChange(RenderStyle* style) 1392{ 1393 FontOrientation fontOrientation; 1394 NonCJKGlyphOrientation glyphOrientation; 1395 style->getFontAndGlyphOrientation(fontOrientation, glyphOrientation); 1396 1397 const FontDescription& fontDescription = style->fontDescription(); 1398 if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation) 1399 return; 1400 1401 FontDescription newFontDescription(fontDescription); 1402 newFontDescription.setNonCJKGlyphOrientation(glyphOrientation); 1403 newFontDescription.setOrientation(fontOrientation); 1404 style->setFontDescription(newFontDescription); 1405} 1406 1407void StyleResolver::updateFont() 1408{ 1409 if (!m_state.fontDirty()) 1410 return; 1411 1412 RenderStyle* style = m_state.style(); 1413#if ENABLE(IOS_TEXT_AUTOSIZING) 1414 checkForTextSizeAdjust(style); 1415#endif 1416 checkForGenericFamilyChange(style, m_state.parentStyle()); 1417 checkForZoomChange(style, m_state.parentStyle()); 1418 checkForOrientationChange(style); 1419 style->font().update(m_fontSelector); 1420 if (m_state.fontSizeHasViewportUnits()) 1421 style->setHasViewportUnits(true); 1422 m_state.setFontDirty(false); 1423} 1424 1425Vector<RefPtr<StyleRule>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude) 1426{ 1427 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude); 1428} 1429 1430Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude) 1431{ 1432 if (!element || !element->document().haveStylesheetsLoaded()) 1433 return Vector<RefPtr<StyleRule>>(); 1434 1435 initElement(element); 1436 m_state.initForStyleResolve(document(), element, 0); 1437 1438 ElementRuleCollector collector(*element, m_state.style(), m_ruleSets, m_selectorFilter); 1439 collector.setMode(SelectorChecker::Mode::CollectingRules); 1440 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId)); 1441 collector.setMedium(m_medium.get()); 1442 1443 if (rulesToInclude & UAAndUserCSSRules) { 1444 // First we match rules from the user agent sheet. 1445 collector.matchUARules(); 1446 1447 // Now we check user sheet rules. 1448 if (m_matchAuthorAndUserStyles) 1449 collector.matchUserRules(rulesToInclude & EmptyCSSRules); 1450 } 1451 1452 if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) { 1453 collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules)); 1454 1455 // Check the rules in author sheets. 1456 collector.matchAuthorRules(rulesToInclude & EmptyCSSRules); 1457 } 1458 1459 return collector.matchedRuleList(); 1460} 1461 1462// ------------------------------------------------------------------------------------- 1463// this is mostly boring stuff on how to apply a certain rule to the renderstyle... 1464 1465Length StyleResolver::convertToIntLength(const CSSPrimitiveValue* primitiveValue, const CSSToLengthConversionData& conversionData) 1466{ 1467 return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | FractionConversion>(conversionData) : Length(Undefined); 1468} 1469 1470Length StyleResolver::convertToFloatLength(const CSSPrimitiveValue* primitiveValue, const CSSToLengthConversionData& conversionData) 1471{ 1472 return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion | FractionConversion>(conversionData) : Length(Undefined); 1473} 1474 1475static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID) 1476{ 1477 switch (propertyID) { 1478 case CSSPropertyWebkitBackgroundClip: 1479 case CSSPropertyBackgroundClip: 1480 case CSSPropertyWebkitBackgroundOrigin: 1481 case CSSPropertyBackgroundOrigin: 1482 case CSSPropertyWebkitBackgroundSize: 1483 case CSSPropertyBackgroundSize: 1484 case CSSPropertyWebkitBorderImage: 1485 case CSSPropertyBorderImage: 1486 case CSSPropertyBorderImageSlice: 1487 case CSSPropertyBorderImageSource: 1488 case CSSPropertyBorderImageOutset: 1489 case CSSPropertyBorderImageRepeat: 1490 case CSSPropertyBorderImageWidth: 1491 case CSSPropertyWebkitBoxShadow: 1492 case CSSPropertyBoxShadow: 1493 case CSSPropertyWebkitTextDecoration: 1494 case CSSPropertyWebkitTextDecorationLine: 1495 case CSSPropertyWebkitTextDecorationStyle: 1496 case CSSPropertyWebkitTextDecorationColor: 1497 case CSSPropertyWebkitTextDecorationSkip: 1498 case CSSPropertyWebkitTextUnderlinePosition: 1499 case CSSPropertyTextDecoration: 1500 return true; 1501 default: 1502 return false; 1503 } 1504} 1505 1506static bool elementTypeHasAppearanceFromUAStyle(const Element& element) 1507{ 1508 // NOTE: This is just a hard-coded list of elements that have some -webkit-appearance value in html.css 1509 const auto& localName = element.localName(); 1510 return localName == HTMLNames::inputTag 1511 || localName == HTMLNames::textareaTag 1512 || localName == HTMLNames::buttonTag 1513 || localName == HTMLNames::progressTag 1514 || localName == HTMLNames::selectTag 1515 || localName == HTMLNames::meterTag 1516 || localName == HTMLNames::isindexTag; 1517} 1518 1519unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size) 1520{ 1521 return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size); 1522} 1523 1524bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b) 1525{ 1526 return a.firstUARule == b.firstUARule 1527 && a.lastUARule == b.lastUARule 1528 && a.firstAuthorRule == b.firstAuthorRule 1529 && a.lastAuthorRule == b.lastAuthorRule 1530 && a.firstUserRule == b.firstUserRule 1531 && a.lastUserRule == b.lastUserRule; 1532} 1533 1534bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b) 1535{ 1536 return !(a == b); 1537} 1538 1539bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b) 1540{ 1541 return a.properties == b.properties && a.linkMatchType == b.linkMatchType; 1542} 1543 1544bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b) 1545{ 1546 return !(a == b); 1547} 1548 1549const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult) 1550{ 1551 ASSERT(hash); 1552 1553 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash); 1554 if (it == m_matchedPropertiesCache.end()) 1555 return 0; 1556 MatchedPropertiesCacheItem& cacheItem = it->value; 1557 1558 size_t size = matchResult.matchedProperties.size(); 1559 if (size != cacheItem.matchedProperties.size()) 1560 return 0; 1561 for (size_t i = 0; i < size; ++i) { 1562 if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i]) 1563 return 0; 1564 } 1565 if (cacheItem.ranges != matchResult.ranges) 1566 return 0; 1567 return &cacheItem; 1568} 1569 1570void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult) 1571{ 1572 static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100; 1573 if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps 1574 && !m_matchedPropertiesCacheSweepTimer.isActive()) { 1575 static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60; 1576 m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds); 1577 } 1578 1579 ASSERT(hash); 1580 MatchedPropertiesCacheItem cacheItem; 1581 cacheItem.matchedProperties.appendVector(matchResult.matchedProperties); 1582 cacheItem.ranges = matchResult.ranges; 1583 // Note that we don't cache the original RenderStyle instance. It may be further modified. 1584 // The RenderStyle in the cache is really just a holder for the substructures and never used as-is. 1585 cacheItem.renderStyle = RenderStyle::clone(style); 1586 cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle); 1587 m_matchedPropertiesCache.add(hash, WTF::move(cacheItem)); 1588} 1589 1590void StyleResolver::invalidateMatchedPropertiesCache() 1591{ 1592 m_matchedPropertiesCache.clear(); 1593} 1594 1595void StyleResolver::clearCachedPropertiesAffectedByViewportUnits() 1596{ 1597 Vector<unsigned, 16> toRemove; 1598 for (auto& cacheKeyValue : m_matchedPropertiesCache) { 1599 if (cacheKeyValue.value.renderStyle->hasViewportUnits()) 1600 toRemove.append(cacheKeyValue.key); 1601 } 1602 for (auto key : toRemove) 1603 m_matchedPropertiesCache.remove(key); 1604} 1605 1606static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle) 1607{ 1608 // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching. 1609 if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement()) 1610 return false; 1611 if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique())) 1612 return false; 1613 if (style->hasAppearance()) 1614 return false; 1615 if (style->zoom() != RenderStyle::initialZoom()) 1616 return false; 1617 if (style->writingMode() != RenderStyle::initialWritingMode()) 1618 return false; 1619 // The cache assumes static knowledge about which properties are inherited. 1620 if (parentStyle->hasExplicitlyInheritedProperties()) 1621 return false; 1622 return true; 1623} 1624 1625void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolver::MatchResult& matchResult, TextDirection& direction, WritingMode& writingMode) 1626{ 1627 direction = style.direction(); 1628 writingMode = style.writingMode(); 1629 1630 bool hadImportantWebkitWritingMode = false; 1631 bool hadImportantDirection = false; 1632 1633 for (auto& matchedProperties : matchResult.matchedProperties) { 1634 for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) { 1635 auto property = matchedProperties.properties->propertyAt(i); 1636 if (!property.value()->isPrimitiveValue()) 1637 continue; 1638 switch (property.id()) { 1639 case CSSPropertyWebkitWritingMode: 1640 if (!hadImportantWebkitWritingMode || property.isImportant()) { 1641 writingMode = toCSSPrimitiveValue(*property.value()); 1642 hadImportantWebkitWritingMode = property.isImportant(); 1643 } 1644 break; 1645 case CSSPropertyDirection: 1646 if (!hadImportantDirection || property.isImportant()) { 1647 direction = toCSSPrimitiveValue(*property.value()); 1648 hadImportantDirection = property.isImportant(); 1649 } 1650 break; 1651 default: 1652 break; 1653 } 1654 } 1655 } 1656} 1657 1658void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache) 1659{ 1660 ASSERT(element); 1661 State& state = m_state; 1662 unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0; 1663 bool applyInheritedOnly = false; 1664 const MatchedPropertiesCacheItem* cacheItem = 0; 1665 if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult)) 1666 && isCacheableInMatchedPropertiesCache(element, state.style(), state.parentStyle())) { 1667 // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact 1668 // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 1669 // element context. This is fast and saves memory by reusing the style data structures. 1670 state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get()); 1671 if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) { 1672 EInsideLink linkStatus = state.style()->insideLink(); 1673 // If the cache item parent style has identical inherited properties to the current parent style then the 1674 // resulting style will be identical too. We copy the inherited properties over from the cache and are done. 1675 state.style()->inheritFrom(cacheItem->renderStyle.get()); 1676 1677 // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it. 1678 state.style()->setInsideLink(linkStatus); 1679 return; 1680 } 1681 applyInheritedOnly = true; 1682 } 1683 1684 // Directional properties (*-before/after) are aliases that depend on the TextDirection and WritingMode. 1685 // These must be resolved before we can begin the property cascade. 1686 TextDirection direction; 1687 WritingMode writingMode; 1688 extractDirectionAndWritingMode(*state.style(), matchResult, direction, writingMode); 1689 1690 if (elementTypeHasAppearanceFromUAStyle(*state.element())) { 1691 // FIXME: This is such a hack. 1692 // Find out if there's a -webkit-appearance property in effect from the UA sheet. 1693 // If so, we cache the border and background styles so that RenderTheme::adjustStyle() 1694 // can look at them later to figure out if this is a styled form control or not. 1695 state.setLineHeightValue(nullptr); 1696 CascadedProperties cascade(direction, writingMode); 1697 if (!cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly) 1698 || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly)) 1699 return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache); 1700 1701 applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight); 1702 updateFont(); 1703 applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty); 1704 1705 state.cacheBorderAndBackground(); 1706 } 1707 1708 CascadedProperties cascade(direction, writingMode); 1709 if (!cascade.addMatches(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly) 1710 || !cascade.addMatches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly) 1711 || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly) 1712 || !cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly)) 1713 return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache); 1714 1715 state.setLineHeightValue(nullptr); 1716 1717 // Start by applying properties that other properties may depend on. 1718 applyCascadedProperties(cascade, firstCSSProperty, CSSPropertyLineHeight); 1719 1720 // If the effective zoom value changes, we can't use the matched properties cache. Start over. 1721 if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) 1722 return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache); 1723 1724 // If our font got dirtied, go ahead and update it now. 1725 updateFont(); 1726 1727 // Line-height is set when we are sure we decided on the font-size. 1728 if (state.lineHeightValue()) 1729 applyProperty(CSSPropertyLineHeight, state.lineHeightValue()); 1730 1731 // If the font changed, we can't use the matched properties cache. Start over. 1732 if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription()) 1733 return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache); 1734 1735 // Apply properties that no other properties depend on. 1736 applyCascadedProperties(cascade, CSSPropertyBackground, lastCSSProperty); 1737 1738 // Finally, some properties must be applied in the order they were parsed. 1739 // There are some CSS properties that affect the same RenderStyle values, 1740 // so to preserve behavior, we queue them up during cascade and flush here. 1741 cascade.applyDeferredProperties(*this); 1742 1743 // Start loading resources referenced by this style. 1744 loadPendingResources(); 1745 1746 ASSERT(!state.fontDirty()); 1747 1748 if (cacheItem || !cacheHash) 1749 return; 1750 if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle())) 1751 return; 1752 addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult); 1753} 1754 1755void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style) 1756{ 1757 initElement(0); 1758 m_state.initForStyleResolve(document(), nullptr, style); 1759 m_state.setStyle(*style); 1760 applyPropertyToCurrentStyle(id, value); 1761} 1762 1763void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value) 1764{ 1765 if (value) 1766 applyProperty(id, value); 1767} 1768 1769inline bool isValidVisitedLinkProperty(CSSPropertyID id) 1770{ 1771 switch (id) { 1772 case CSSPropertyBackgroundColor: 1773 case CSSPropertyBorderLeftColor: 1774 case CSSPropertyBorderRightColor: 1775 case CSSPropertyBorderTopColor: 1776 case CSSPropertyBorderBottomColor: 1777 case CSSPropertyColor: 1778 case CSSPropertyOutlineColor: 1779 case CSSPropertyWebkitColumnRuleColor: 1780 case CSSPropertyWebkitTextDecorationColor: 1781 case CSSPropertyWebkitTextEmphasisColor: 1782 case CSSPropertyWebkitTextFillColor: 1783 case CSSPropertyWebkitTextStrokeColor: 1784 case CSSPropertyFill: 1785 case CSSPropertyStroke: 1786 return true; 1787 default: 1788 break; 1789 } 1790 1791 return false; 1792} 1793 1794// http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule 1795// FIXME: add incremental support for other region styling properties. 1796inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id) 1797{ 1798 switch (id) { 1799 case CSSPropertyBackgroundColor: 1800 case CSSPropertyColor: 1801 return true; 1802 default: 1803 break; 1804 } 1805 1806 return false; 1807} 1808 1809#if ENABLE(VIDEO_TRACK) 1810inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id) 1811{ 1812 switch (id) { 1813 case CSSPropertyBackground: 1814 case CSSPropertyBackgroundAttachment: 1815 case CSSPropertyBackgroundClip: 1816 case CSSPropertyBackgroundColor: 1817 case CSSPropertyBackgroundImage: 1818 case CSSPropertyBackgroundOrigin: 1819 case CSSPropertyBackgroundPosition: 1820 case CSSPropertyBackgroundPositionX: 1821 case CSSPropertyBackgroundPositionY: 1822 case CSSPropertyBackgroundRepeat: 1823 case CSSPropertyBackgroundRepeatX: 1824 case CSSPropertyBackgroundRepeatY: 1825 case CSSPropertyBackgroundSize: 1826 case CSSPropertyColor: 1827 case CSSPropertyFont: 1828 case CSSPropertyFontFamily: 1829 case CSSPropertyFontSize: 1830 case CSSPropertyFontStyle: 1831 case CSSPropertyFontVariant: 1832 case CSSPropertyFontWeight: 1833 case CSSPropertyLineHeight: 1834 case CSSPropertyOpacity: 1835 case CSSPropertyOutline: 1836 case CSSPropertyOutlineColor: 1837 case CSSPropertyOutlineOffset: 1838 case CSSPropertyOutlineStyle: 1839 case CSSPropertyOutlineWidth: 1840 case CSSPropertyVisibility: 1841 case CSSPropertyWhiteSpace: 1842 case CSSPropertyTextDecoration: 1843 case CSSPropertyTextShadow: 1844 case CSSPropertyBorderStyle: 1845 return true; 1846 default: 1847 break; 1848 } 1849 return false; 1850} 1851#endif 1852// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead 1853// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() 1854// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. 1855// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) 1856// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like 1857// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, 1858// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific 1859// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). 1860bool StyleResolver::useSVGZoomRules() 1861{ 1862 return m_state.element() && m_state.element()->isSVGElement(); 1863} 1864 1865#if ENABLE(CSS_GRID_LAYOUT) 1866static void createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap& namedGridAreas, NamedGridLinesMap& namedGridLines, GridTrackSizingDirection direction) 1867{ 1868 for (auto& area : namedGridAreas) { 1869 GridSpan areaSpan = direction == ForRows ? area.value.rows : area.value.columns; 1870 { 1871 auto& startVector = namedGridLines.add(area.key + "-start", Vector<size_t>()).iterator->value; 1872 startVector.append(areaSpan.resolvedInitialPosition.toInt()); 1873 std::sort(startVector.begin(), startVector.end()); 1874 } 1875 { 1876 auto& endVector = namedGridLines.add(area.key + "-end", Vector<size_t>()).iterator->value; 1877 endVector.append(areaSpan.resolvedFinalPosition.next().toInt()); 1878 std::sort(endVector.begin(), endVector.end()); 1879 } 1880 } 1881} 1882 1883static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, GridLength& workingLength) 1884{ 1885 if (primitiveValue->getValueID() == CSSValueWebkitMinContent) { 1886 workingLength = Length(MinContent); 1887 return true; 1888 } 1889 1890 if (primitiveValue->getValueID() == CSSValueWebkitMaxContent) { 1891 workingLength = Length(MaxContent); 1892 return true; 1893 } 1894 1895 if (primitiveValue->isFlex()) { 1896 // Fractional unit. 1897 workingLength.setFlex(primitiveValue->getDoubleValue()); 1898 return true; 1899 } 1900 1901 workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | AutoConversion>(state.cssToLengthConversionData()); 1902 if (workingLength.length().isUndefined()) 1903 return false; 1904 1905 if (primitiveValue->isLength()) 1906 workingLength.length().setHasQuirk(primitiveValue->isQuirkValue()); 1907 1908 return true; 1909} 1910 1911static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolver::State& state) 1912{ 1913 if (value->isPrimitiveValue()) { 1914 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1915 GridLength workingLength; 1916 if (!createGridTrackBreadth(primitiveValue, state, workingLength)) 1917 return false; 1918 1919 trackSize.setLength(workingLength); 1920 return true; 1921 } 1922 1923 CSSFunctionValue* minmaxFunction = toCSSFunctionValue(value); 1924 CSSValueList* arguments = minmaxFunction->arguments(); 1925 ASSERT_WITH_SECURITY_IMPLICATION(arguments->length() == 2); 1926 GridLength minTrackBreadth; 1927 GridLength maxTrackBreadth; 1928 if (!createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(0)), state, minTrackBreadth) || !createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(1)), state, maxTrackBreadth)) 1929 return false; 1930 1931 trackSize.setMinMax(minTrackBreadth, maxTrackBreadth); 1932 return true; 1933} 1934 1935static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLinesMap& orderedNamedGridLines, const StyleResolver::State& state) 1936{ 1937 // Handle 'none'. 1938 if (value->isPrimitiveValue()) { 1939 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1940 return primitiveValue->getValueID() == CSSValueNone; 1941 } 1942 1943 if (!value->isValueList()) 1944 return false; 1945 1946 size_t currentNamedGridLine = 0; 1947 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { 1948 CSSValue* currValue = i.value(); 1949 if (currValue->isGridLineNamesValue()) { 1950 CSSGridLineNamesValue* lineNamesValue = toCSSGridLineNamesValue(currValue); 1951 for (CSSValueListIterator j = lineNamesValue; j.hasMore(); j.advance()) { 1952 String namedGridLine = toCSSPrimitiveValue(j.value())->getStringValue(); 1953 NamedGridLinesMap::AddResult result = namedGridLines.add(namedGridLine, Vector<size_t>()); 1954 result.iterator->value.append(currentNamedGridLine); 1955 OrderedNamedGridLinesMap::AddResult orderedResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>()); 1956 orderedResult.iterator->value.append(namedGridLine); 1957 } 1958 continue; 1959 } 1960 1961 ++currentNamedGridLine; 1962 GridTrackSize trackSize; 1963 if (!createGridTrackSize(currValue, trackSize, state)) 1964 return false; 1965 1966 trackSizes.append(trackSize); 1967 } 1968 1969 // The parser should have rejected any <track-list> without any <track-size> as 1970 // this is not conformant to the syntax. 1971 ASSERT(!trackSizes.isEmpty()); 1972 return true; 1973} 1974 1975 1976static bool createGridPosition(CSSValue* value, GridPosition& position) 1977{ 1978 // We accept the specification's grammar: 1979 // auto | <custom-ident> | [ <integer> && <custom-ident>? ] | [ span && [ <integer> || <custom-ident> ] ] 1980 if (value->isPrimitiveValue()) { 1981 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1982 // We translate <ident> to <string> during parsing as it makes handling it simpler. 1983 if (primitiveValue->isString()) { 1984 position.setNamedGridArea(primitiveValue->getStringValue()); 1985 return true; 1986 } 1987 1988 ASSERT(primitiveValue->getValueID() == CSSValueAuto); 1989 return true; 1990 } 1991 1992 CSSValueList* values = toCSSValueList(value); 1993 ASSERT(values->length()); 1994 1995 bool isSpanPosition = false; 1996 int gridLineNumber = 0; 1997 String gridLineName; 1998 1999 CSSValueListIterator it = values; 2000 CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value()); 2001 if (currentValue->getValueID() == CSSValueSpan) { 2002 isSpanPosition = true; 2003 it.advance(); 2004 currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; 2005 } 2006 2007 if (currentValue && currentValue->isNumber()) { 2008 gridLineNumber = currentValue->getIntValue(); 2009 it.advance(); 2010 currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; 2011 } 2012 2013 if (currentValue && currentValue->isString()) { 2014 gridLineName = currentValue->getStringValue(); 2015 it.advance(); 2016 } 2017 2018 ASSERT(!it.hasMore()); 2019 if (isSpanPosition) 2020 position.setSpanPosition(gridLineNumber ? gridLineNumber : 1, gridLineName); 2021 else 2022 position.setExplicitPosition(gridLineNumber, gridLineName); 2023 2024 return true; 2025} 2026#endif /* ENABLE(CSS_GRID_LAYOUT) */ 2027 2028void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value) 2029{ 2030 ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id); 2031 2032 State& state = m_state; 2033 2034 if (CSSProperty::isDirectionAwareProperty(id)) { 2035 CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode()); 2036 ASSERT(newId != id); 2037 return applyProperty(newId, value); 2038 } 2039 2040 bool isInherit = state.parentStyle() && value->isInheritedValue(); 2041 bool isInitial = value->isInitialValue() || (!state.parentStyle() && value->isInheritedValue()); 2042 2043 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit 2044 2045 if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) { 2046 // Limit the properties that can be applied to only the ones honored by :visited. 2047 return; 2048 } 2049 2050 if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id)) 2051 state.parentStyle()->setHasExplicitlyInheritedProperties(); 2052 2053 // Check lookup table for implementations and use when available. 2054 const PropertyHandler& handler = m_deprecatedStyleBuilder.propertyHandler(id); 2055 if (handler.isValid()) { 2056 if (isInherit) 2057 handler.applyInheritValue(id, this); 2058 else if (isInitial) 2059 handler.applyInitialValue(id, this); 2060 else 2061 handler.applyValue(id, this, value); 2062 return; 2063 } 2064 2065 CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0; 2066 2067 // What follows is a list that maps the CSS properties into their corresponding front-end 2068 // RenderStyle values. 2069 switch (id) { 2070 // lists 2071 case CSSPropertyContent: 2072 // list of string, uri, counter, attr, i 2073 { 2074 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This 2075 // note is a reminder that eventually "inherit" needs to be supported. 2076 2077 if (isInitial) { 2078 state.style()->clearContent(); 2079 return; 2080 } 2081 2082 if (!value->isValueList()) 2083 return; 2084 2085 bool didSet = false; 2086 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { 2087 CSSValue* item = i.value(); 2088 if (item->isImageGeneratorValue()) { 2089 if (item->isGradientValue()) 2090 state.style()->setContent(StyleGeneratedImage::create(*toCSSGradientValue(item)->gradientWithStylesResolved(this)), didSet); 2091 else 2092 state.style()->setContent(StyleGeneratedImage::create(*toCSSImageGeneratorValue(item)), didSet); 2093 didSet = true; 2094#if ENABLE(CSS_IMAGE_SET) 2095 } else if (item->isImageSetValue()) { 2096 state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet); 2097 didSet = true; 2098#endif 2099 } 2100 2101 if (item->isImageValue()) { 2102 state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, toCSSImageValue(item)), didSet); 2103 didSet = true; 2104 continue; 2105 } 2106 2107 if (!item->isPrimitiveValue()) 2108 continue; 2109 2110 CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); 2111 2112 if (contentValue->isString()) { 2113 state.style()->setContent(contentValue->getStringValue().impl(), didSet); 2114 didSet = true; 2115 } else if (contentValue->isAttr()) { 2116 // FIXME: Can a namespace be specified for an attr(foo)? 2117 if (state.style()->styleType() == NOPSEUDO) 2118 state.style()->setUnique(); 2119 else 2120 state.parentStyle()->setUnique(); 2121 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom); 2122 const AtomicString& value = state.element()->getAttribute(attr); 2123 state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet); 2124 didSet = true; 2125 // Register the fact that the attribute value affects the style. 2126 m_ruleSets.features().attrsInRules.add(attr.localName().impl()); 2127 } else if (contentValue->isCounter()) { 2128 Counter* counterValue = contentValue->getCounterValue(); 2129 EListStyleType listStyleType = NoneListStyle; 2130 CSSValueID listStyleIdent = counterValue->listStyleIdent(); 2131 if (listStyleIdent != CSSValueNone) 2132 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); 2133 auto counter = std::make_unique<CounterContent>(counterValue->identifier(), listStyleType, counterValue->separator()); 2134 state.style()->setContent(WTF::move(counter), didSet); 2135 didSet = true; 2136 } else { 2137 switch (contentValue->getValueID()) { 2138 case CSSValueOpenQuote: 2139 state.style()->setContent(OPEN_QUOTE, didSet); 2140 didSet = true; 2141 break; 2142 case CSSValueCloseQuote: 2143 state.style()->setContent(CLOSE_QUOTE, didSet); 2144 didSet = true; 2145 break; 2146 case CSSValueNoOpenQuote: 2147 state.style()->setContent(NO_OPEN_QUOTE, didSet); 2148 didSet = true; 2149 break; 2150 case CSSValueNoCloseQuote: 2151 state.style()->setContent(NO_CLOSE_QUOTE, didSet); 2152 didSet = true; 2153 break; 2154 default: 2155 // normal and none do not have any effect. 2156 { } 2157 } 2158 } 2159 } 2160 if (!didSet) 2161 state.style()->clearContent(); 2162 return; 2163 } 2164 case CSSPropertyWebkitAlt: 2165 { 2166 bool didSet = false; 2167 if (primitiveValue->isString()) { 2168 state.style()->setContentAltText(primitiveValue->getStringValue().impl()); 2169 didSet = true; 2170 } else if (primitiveValue->isAttr()) { 2171 // FIXME: Can a namespace be specified for an attr(foo)? 2172 if (state.style()->styleType() == NOPSEUDO) 2173 state.style()->setUnique(); 2174 else 2175 state.parentStyle()->setUnique(); 2176 QualifiedName attr(nullAtom, primitiveValue->getStringValue().impl(), nullAtom); 2177 const AtomicString& value = state.element()->getAttribute(attr); 2178 state.style()->setContentAltText(value.isNull() ? emptyAtom : value.impl()); 2179 didSet = true; 2180 // Register the fact that the attribute value affects the style. 2181 m_ruleSets.features().attrsInRules.add(attr.localName().impl()); 2182 } 2183 if (!didSet) 2184 state.style()->setContentAltText(emptyAtom); 2185 return; 2186 } 2187 2188 case CSSPropertyQuotes: 2189 if (isInherit) { 2190 state.style()->setQuotes(state.parentStyle()->quotes()); 2191 return; 2192 } 2193 if (isInitial) { 2194 state.style()->setQuotes(0); 2195 return; 2196 } 2197 if (value->isValueList()) { 2198 CSSValueList* list = toCSSValueList(value); 2199 Vector<std::pair<String, String>> quotes; 2200 for (size_t i = 0; i < list->length(); i += 2) { 2201 CSSValue* first = list->itemWithoutBoundsCheck(i); 2202 // item() returns null if out of bounds so this is safe. 2203 CSSValue* second = list->item(i + 1); 2204 if (!second) 2205 continue; 2206 ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue()); 2207 ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue()); 2208 String startQuote = toCSSPrimitiveValue(first)->getStringValue(); 2209 String endQuote = toCSSPrimitiveValue(second)->getStringValue(); 2210 quotes.append(std::make_pair(startQuote, endQuote)); 2211 } 2212 state.style()->setQuotes(QuotesData::create(quotes)); 2213 return; 2214 } 2215 if (primitiveValue) { 2216 if (primitiveValue->getValueID() == CSSValueNone) 2217 state.style()->setQuotes(QuotesData::create(Vector<std::pair<String, String>>())); 2218 } 2219 return; 2220 // Shorthand properties. 2221 case CSSPropertyFont: 2222 if (isInherit) { 2223 FontDescription fontDescription = state.parentStyle()->fontDescription(); 2224 state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight()); 2225 state.setLineHeightValue(0); 2226 setFontDescription(fontDescription); 2227 } else if (isInitial) { 2228 Settings* settings = documentSettings(); 2229 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings 2230 if (!settings) 2231 return; 2232 initializeFontStyle(settings); 2233 } else if (primitiveValue) { 2234 state.style()->setLineHeight(RenderStyle::initialLineHeight()); 2235 state.setLineHeightValue(0); 2236 2237 FontDescription fontDescription; 2238 RenderTheme::defaultTheme()->systemFont(primitiveValue->getValueID(), fontDescription); 2239 2240 // Double-check and see if the theme did anything. If not, don't bother updating the font. 2241 if (fontDescription.isAbsoluteSize()) { 2242 // Make sure the rendering mode and printer font settings are updated. 2243 Settings* settings = documentSettings(); 2244 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings 2245 if (!settings) 2246 return; 2247 fontDescription.setRenderingMode(settings->fontRenderingMode()); 2248 fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled()); 2249 2250 // Handle the zoom factor. 2251 fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(fontDescription.specifiedSize(), fontDescription.isAbsoluteSize(), useSVGZoomRules(), state.style(), document())); 2252 setFontDescription(fontDescription); 2253 } 2254 } else if (value->isFontValue()) { 2255 CSSFontValue* font = toCSSFontValue(value); 2256 if (!font->style || !font->variant || !font->weight 2257 || !font->size || !font->lineHeight || !font->family) 2258 return; 2259 applyProperty(CSSPropertyFontStyle, font->style.get()); 2260 applyProperty(CSSPropertyFontVariant, font->variant.get()); 2261 applyProperty(CSSPropertyFontWeight, font->weight.get()); 2262 // The previous properties can dirty our font but they don't try to read the font's 2263 // properties back, which is safe. However if font-size is using the 'ex' unit, it will 2264 // need query the dirtied font's x-height to get the computed size. To be safe in this 2265 // case, let's just update the font now. 2266 updateFont(); 2267 applyProperty(CSSPropertyFontSize, font->size.get()); 2268 2269 state.setLineHeightValue(font->lineHeight.get()); 2270 2271 applyProperty(CSSPropertyFontFamily, font->family.get()); 2272 } 2273 return; 2274 2275 case CSSPropertyBackground: 2276 case CSSPropertyBackgroundPosition: 2277 case CSSPropertyBackgroundRepeat: 2278 case CSSPropertyBorder: 2279 case CSSPropertyBorderBottom: 2280 case CSSPropertyBorderColor: 2281 case CSSPropertyBorderImage: 2282 case CSSPropertyBorderLeft: 2283 case CSSPropertyBorderRadius: 2284 case CSSPropertyBorderRight: 2285 case CSSPropertyBorderSpacing: 2286 case CSSPropertyBorderStyle: 2287 case CSSPropertyBorderTop: 2288 case CSSPropertyBorderWidth: 2289 case CSSPropertyListStyle: 2290 case CSSPropertyMargin: 2291 case CSSPropertyOutline: 2292 case CSSPropertyOverflow: 2293 case CSSPropertyPadding: 2294 case CSSPropertyTransition: 2295 case CSSPropertyWebkitAnimation: 2296 case CSSPropertyWebkitBorderAfter: 2297 case CSSPropertyWebkitBorderBefore: 2298 case CSSPropertyWebkitBorderEnd: 2299 case CSSPropertyWebkitBorderStart: 2300 case CSSPropertyWebkitBorderRadius: 2301 case CSSPropertyWebkitColumns: 2302 case CSSPropertyWebkitColumnRule: 2303 case CSSPropertyWebkitFlex: 2304 case CSSPropertyWebkitFlexFlow: 2305#if ENABLE(CSS_GRID_LAYOUT) 2306 case CSSPropertyWebkitGridTemplate: 2307 case CSSPropertyWebkitGridArea: 2308 case CSSPropertyWebkitGridColumn: 2309 case CSSPropertyWebkitGridRow: 2310#endif 2311 case CSSPropertyWebkitMarginCollapse: 2312 case CSSPropertyWebkitMarquee: 2313 case CSSPropertyWebkitMask: 2314 case CSSPropertyWebkitMaskPosition: 2315 case CSSPropertyWebkitMaskRepeat: 2316 case CSSPropertyWebkitTextEmphasis: 2317 case CSSPropertyWebkitTextStroke: 2318 case CSSPropertyWebkitTransition: 2319 case CSSPropertyWebkitTransformOrigin: 2320 ASSERT(isExpandedShorthand(id)); 2321 ASSERT_NOT_REACHED(); 2322 break; 2323 2324 // CSS3 Properties 2325 case CSSPropertyTextShadow: 2326 case CSSPropertyBoxShadow: 2327 case CSSPropertyWebkitBoxShadow: { 2328 if (isInherit) { 2329 if (id == CSSPropertyTextShadow) 2330 return state.style()->setTextShadow(state.parentStyle()->textShadow() ? std::make_unique<ShadowData>(*state.parentStyle()->textShadow()) : nullptr); 2331 return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? std::make_unique<ShadowData>(*state.parentStyle()->boxShadow()) : nullptr); 2332 } 2333 if (isInitial || primitiveValue) // initial | none 2334 return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr); 2335 2336 if (!value->isValueList()) 2337 return; 2338 2339 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { 2340 CSSValue* currValue = i.value(); 2341 if (!currValue->isShadowValue()) 2342 continue; 2343 CSSShadowValue* item = toCSSShadowValue(currValue); 2344 int x = item->x->computeLength<int>(state.cssToLengthConversionData()); 2345 int y = item->y->computeLength<int>(state.cssToLengthConversionData()); 2346 int blur = item->blur ? item->blur->computeLength<int>(state.cssToLengthConversionData()) : 0; 2347 int spread = item->spread ? item->spread->computeLength<int>(state.cssToLengthConversionData()) : 0; 2348 ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal; 2349 Color color; 2350 if (item->color) 2351 color = colorFromPrimitiveValue(item->color.get()); 2352 else if (state.style()) 2353 color = state.style()->color(); 2354 2355 auto shadowData = std::make_unique<ShadowData>(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent); 2356 if (id == CSSPropertyTextShadow) 2357 state.style()->setTextShadow(WTF::move(shadowData), i.index()); // add to the list if this is not the first entry 2358 else 2359 state.style()->setBoxShadow(WTF::move(shadowData), i.index()); // add to the list if this is not the first entry 2360 } 2361 return; 2362 } 2363 case CSSPropertyWebkitBoxReflect: { 2364 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect) 2365 if (primitiveValue) { 2366 state.style()->setBoxReflect(RenderStyle::initialBoxReflect()); 2367 return; 2368 } 2369 2370 if (!value->isReflectValue()) 2371 return; 2372 2373 CSSReflectValue* reflectValue = toCSSReflectValue(value); 2374 RefPtr<StyleReflection> reflection = StyleReflection::create(); 2375 reflection->setDirection(*reflectValue->direction()); 2376 if (reflectValue->offset()) 2377 reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.cssToLengthConversionData())); 2378 NinePieceImage mask; 2379 mask.setMaskDefaults(); 2380 m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask); 2381 reflection->setMask(mask); 2382 2383 state.style()->setBoxReflect(reflection.release()); 2384 return; 2385 } 2386 case CSSPropertySrc: // Only used in @font-face rules. 2387 return; 2388 case CSSPropertyUnicodeRange: // Only used in @font-face rules. 2389 return; 2390 case CSSPropertyWebkitLocale: { 2391 HANDLE_INHERIT_AND_INITIAL(locale, Locale); 2392 if (!primitiveValue) 2393 return; 2394 if (primitiveValue->getValueID() == CSSValueAuto) 2395 state.style()->setLocale(nullAtom); 2396 else 2397 state.style()->setLocale(primitiveValue->getStringValue()); 2398 FontDescription fontDescription = state.style()->fontDescription(); 2399 fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale())); 2400 setFontDescription(fontDescription); 2401 return; 2402 } 2403#if ENABLE(IOS_TEXT_AUTOSIZING) 2404 case CSSPropertyWebkitTextSizeAdjust: { 2405 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust) 2406 if (!primitiveValue) 2407 return; 2408 2409 if (primitiveValue->getValueID() == CSSValueAuto) 2410 state.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment)); 2411 else if (primitiveValue->getValueID() == CSSValueNone) 2412 state.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment)); 2413 else 2414 state.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue->getFloatValue())); 2415 2416 state.setFontDirty(true); 2417 return; 2418 } 2419#endif 2420#if ENABLE(DASHBOARD_SUPPORT) 2421 case CSSPropertyWebkitDashboardRegion: 2422 { 2423 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions) 2424 if (!primitiveValue) 2425 return; 2426 2427 if (primitiveValue->getValueID() == CSSValueNone) { 2428 state.style()->setDashboardRegions(RenderStyle::noneDashboardRegions()); 2429 return; 2430 } 2431 2432 DashboardRegion* region = primitiveValue->getDashboardRegionValue(); 2433 if (!region) 2434 return; 2435 2436 DashboardRegion* first = region; 2437 while (region) { 2438 Length top = convertToIntLength(region->top(), state.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)); 2439 Length right = convertToIntLength(region->right(), state.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)); 2440 Length bottom = convertToIntLength(region->bottom(), state.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)); 2441 Length left = convertToIntLength(region->left(), state.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)); 2442 2443 if (top.isUndefined()) 2444 top = Length(); 2445 if (right.isUndefined()) 2446 right = Length(); 2447 if (bottom.isUndefined()) 2448 bottom = Length(); 2449 if (left.isUndefined()) 2450 left = Length(); 2451 2452 if (region->m_isCircle) 2453 state.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); 2454 else if (region->m_isRectangle) 2455 state.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true); 2456 region = region->m_next.get(); 2457 } 2458 2459 state.document().setHasAnnotatedRegions(true); 2460 2461 return; 2462 } 2463#endif 2464 case CSSPropertyWebkitTextStrokeWidth: { 2465 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) 2466 float width = 0; 2467 switch (primitiveValue->getValueID()) { 2468 case CSSValueThin: 2469 case CSSValueMedium: 2470 case CSSValueThick: { 2471 double result = 1.0 / 48; 2472 if (primitiveValue->getValueID() == CSSValueMedium) 2473 result *= 3; 2474 else if (primitiveValue->getValueID() == CSSValueThick) 2475 result *= 5; 2476 Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)); 2477 width = value.get().computeLength<float>(state.cssToLengthConversionData()); 2478 break; 2479 } 2480 default: 2481 width = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); 2482 break; 2483 } 2484 state.style()->setTextStrokeWidth(width); 2485 return; 2486 } 2487 case CSSPropertyWebkitTransform: { 2488 HANDLE_INHERIT_AND_INITIAL(transform, Transform); 2489 TransformOperations operations; 2490 transformsForValue(value, state.cssToLengthConversionData(), operations); 2491 state.style()->setTransform(operations); 2492 return; 2493 } 2494 case CSSPropertyWebkitPerspective: { 2495 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective) 2496 2497 if (!primitiveValue) 2498 return; 2499 2500 if (primitiveValue->getValueID() == CSSValueNone) { 2501 state.style()->setPerspective(0); 2502 return; 2503 } 2504 2505 float perspectiveValue; 2506 if (primitiveValue->isLength()) 2507 perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); 2508 else if (primitiveValue->isNumber()) { 2509 // For backward compatibility, treat valueless numbers as px. 2510 Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)); 2511 perspectiveValue = value.get().computeLength<float>(state.cssToLengthConversionData()); 2512 } else 2513 return; 2514 2515 if (perspectiveValue >= 0.0f) 2516 state.style()->setPerspective(perspectiveValue); 2517 return; 2518 } 2519#if PLATFORM(IOS) 2520 case CSSPropertyWebkitTouchCallout: { 2521 HANDLE_INHERIT_AND_INITIAL(touchCalloutEnabled, TouchCalloutEnabled); 2522 if (!primitiveValue) 2523 break; 2524 2525 state.style()->setTouchCalloutEnabled(primitiveValue->getStringValue().lower() != "none"); 2526 return; 2527 } 2528 2529 // FIXME: CSSPropertyWebkitCompositionFillColor shouldn't be iOS-specific. Once we fix up its usage in 2530 // InlineTextBox::paintCompositionBackground() we should move it outside the PLATFORM(IOS)-guard. 2531 // See <https://bugs.webkit.org/show_bug.cgi?id=126296>. 2532 case CSSPropertyWebkitCompositionFillColor: { 2533 HANDLE_INHERIT_AND_INITIAL(compositionFillColor, CompositionFillColor); 2534 if (!primitiveValue) 2535 break; 2536 state.style()->setCompositionFillColor(colorFromPrimitiveValue(primitiveValue)); 2537 return; 2538 } 2539#endif 2540#if ENABLE(TOUCH_EVENTS) 2541 case CSSPropertyWebkitTapHighlightColor: { 2542 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); 2543 if (!primitiveValue) 2544 break; 2545 2546 Color col = colorFromPrimitiveValue(primitiveValue); 2547 state.style()->setTapHighlightColor(col); 2548 return; 2549 } 2550#endif 2551#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) 2552 case CSSPropertyWebkitOverflowScrolling: { 2553 HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling); 2554 if (!primitiveValue) 2555 break; 2556 state.style()->setUseTouchOverflowScrolling(primitiveValue->getValueID() == CSSValueTouch); 2557 return; 2558 } 2559#endif 2560 case CSSPropertyInvalid: 2561 return; 2562 case CSSPropertyFontStretch: 2563 case CSSPropertyPage: 2564 case CSSPropertyTextLineThrough: 2565 case CSSPropertyTextLineThroughColor: 2566 case CSSPropertyTextLineThroughMode: 2567 case CSSPropertyTextLineThroughStyle: 2568 case CSSPropertyTextLineThroughWidth: 2569 case CSSPropertyTextOverline: 2570 case CSSPropertyTextOverlineColor: 2571 case CSSPropertyTextOverlineMode: 2572 case CSSPropertyTextOverlineStyle: 2573 case CSSPropertyTextOverlineWidth: 2574 case CSSPropertyTextUnderline: 2575 case CSSPropertyTextUnderlineColor: 2576 case CSSPropertyTextUnderlineMode: 2577 case CSSPropertyTextUnderlineStyle: 2578 case CSSPropertyTextUnderlineWidth: 2579 case CSSPropertyWebkitFontSizeDelta: 2580 case CSSPropertyWebkitTextDecorationsInEffect: 2581 return; 2582 2583 // CSS Text Layout Module Level 3: Vertical writing support 2584 case CSSPropertyWebkitWritingMode: { 2585 HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode); 2586 2587 if (primitiveValue) 2588 setWritingMode(*primitiveValue); 2589 2590 // FIXME: It is not ok to modify document state while applying style. 2591 if (state.element() && state.element() == state.document().documentElement()) 2592 state.document().setWritingModeSetOnDocumentElement(true); 2593 return; 2594 } 2595 2596 case CSSPropertyWebkitTextOrientation: { 2597 HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation); 2598 2599 if (primitiveValue) 2600 setTextOrientation(*primitiveValue); 2601 2602 return; 2603 } 2604 2605 case CSSPropertyWebkitLineBoxContain: { 2606 HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain) 2607 if (primitiveValue && primitiveValue->getValueID() == CSSValueNone) { 2608 state.style()->setLineBoxContain(LineBoxContainNone); 2609 return; 2610 } 2611 2612 if (!value->isLineBoxContainValue()) 2613 return; 2614 2615 state.style()->setLineBoxContain(toCSSLineBoxContainValue(value)->value()); 2616 return; 2617 } 2618 2619 // CSS Fonts Module Level 3 2620 case CSSPropertyWebkitFontFeatureSettings: { 2621 if (primitiveValue && primitiveValue->getValueID() == CSSValueNormal) { 2622 setFontDescription(state.style()->fontDescription().makeNormalFeatureSettings()); 2623 return; 2624 } 2625 2626 if (!value->isValueList()) 2627 return; 2628 2629 FontDescription fontDescription = state.style()->fontDescription(); 2630 CSSValueList* list = toCSSValueList(value); 2631 RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create(); 2632 int len = list->length(); 2633 for (int i = 0; i < len; ++i) { 2634 CSSValue* item = list->itemWithoutBoundsCheck(i); 2635 if (!item->isFontFeatureValue()) 2636 continue; 2637 CSSFontFeatureValue* feature = toCSSFontFeatureValue(item); 2638 settings->append(FontFeature(feature->tag(), feature->value())); 2639 } 2640 fontDescription.setFeatureSettings(settings.release()); 2641 setFontDescription(fontDescription); 2642 return; 2643 } 2644 2645#if ENABLE(CSS_FILTERS) 2646 case CSSPropertyWebkitFilter: { 2647 HANDLE_INHERIT_AND_INITIAL(filter, Filter); 2648 FilterOperations operations; 2649 if (createFilterOperations(value, operations)) 2650 state.style()->setFilter(operations); 2651 return; 2652 } 2653#endif 2654#if ENABLE(CSS_GRID_LAYOUT) 2655 case CSSPropertyWebkitGridAutoColumns: { 2656 HANDLE_INHERIT_AND_INITIAL(gridAutoColumns, GridAutoColumns); 2657 GridTrackSize trackSize; 2658 if (!createGridTrackSize(value, trackSize, state)) 2659 return; 2660 state.style()->setGridAutoColumns(trackSize); 2661 return; 2662 } 2663 case CSSPropertyWebkitGridAutoRows: { 2664 HANDLE_INHERIT_AND_INITIAL(gridAutoRows, GridAutoRows); 2665 GridTrackSize trackSize; 2666 if (!createGridTrackSize(value, trackSize, state)) 2667 return; 2668 state.style()->setGridAutoRows(trackSize); 2669 return; 2670 } 2671 case CSSPropertyWebkitGridTemplateColumns: { 2672 if (isInherit) { 2673 m_state.style()->setGridColumns(m_state.parentStyle()->gridColumns()); 2674 m_state.style()->setNamedGridColumnLines(m_state.parentStyle()->namedGridColumnLines()); 2675 m_state.style()->setOrderedNamedGridColumnLines(m_state.parentStyle()->orderedNamedGridColumnLines()); 2676 return; 2677 } 2678 if (isInitial) { 2679 m_state.style()->setGridColumns(RenderStyle::initialGridColumns()); 2680 m_state.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines()); 2681 m_state.style()->setOrderedNamedGridColumnLines(RenderStyle::initialOrderedNamedGridColumnLines()); 2682 return; 2683 } 2684 Vector<GridTrackSize> trackSizes; 2685 NamedGridLinesMap namedGridLines; 2686 OrderedNamedGridLinesMap orderedNamedGridLines; 2687 if (!createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, state)) 2688 return; 2689 const NamedGridAreaMap& namedGridAreas = state.style()->namedGridArea(); 2690 if (!namedGridAreas.isEmpty()) 2691 createImplicitNamedGridLinesFromGridArea(namedGridAreas, namedGridLines, ForColumns); 2692 2693 state.style()->setGridColumns(trackSizes); 2694 state.style()->setNamedGridColumnLines(namedGridLines); 2695 state.style()->setOrderedNamedGridColumnLines(orderedNamedGridLines); 2696 return; 2697 } 2698 case CSSPropertyWebkitGridTemplateRows: { 2699 if (isInherit) { 2700 m_state.style()->setGridRows(m_state.parentStyle()->gridRows()); 2701 m_state.style()->setNamedGridRowLines(m_state.parentStyle()->namedGridRowLines()); 2702 m_state.style()->setOrderedNamedGridRowLines(m_state.parentStyle()->orderedNamedGridRowLines()); 2703 return; 2704 } 2705 if (isInitial) { 2706 m_state.style()->setGridRows(RenderStyle::initialGridRows()); 2707 m_state.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines()); 2708 m_state.style()->setOrderedNamedGridRowLines(RenderStyle::initialOrderedNamedGridRowLines()); 2709 return; 2710 } 2711 Vector<GridTrackSize> trackSizes; 2712 NamedGridLinesMap namedGridLines; 2713 OrderedNamedGridLinesMap orderedNamedGridLines; 2714 if (!createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, state)) 2715 return; 2716 const NamedGridAreaMap& namedGridAreas = state.style()->namedGridArea(); 2717 if (!namedGridAreas.isEmpty()) 2718 createImplicitNamedGridLinesFromGridArea(namedGridAreas, namedGridLines, ForRows); 2719 2720 state.style()->setGridRows(trackSizes); 2721 state.style()->setNamedGridRowLines(namedGridLines); 2722 state.style()->setOrderedNamedGridRowLines(orderedNamedGridLines); 2723 return; 2724 } 2725 2726 case CSSPropertyWebkitGridColumnStart: { 2727 HANDLE_INHERIT_AND_INITIAL(gridItemColumnStart, GridItemColumnStart); 2728 GridPosition columnStartPosition; 2729 if (!createGridPosition(value, columnStartPosition)) 2730 return; 2731 state.style()->setGridItemColumnStart(columnStartPosition); 2732 return; 2733 } 2734 case CSSPropertyWebkitGridColumnEnd: { 2735 HANDLE_INHERIT_AND_INITIAL(gridItemColumnEnd, GridItemColumnEnd); 2736 GridPosition columnEndPosition; 2737 if (!createGridPosition(value, columnEndPosition)) 2738 return; 2739 state.style()->setGridItemColumnEnd(columnEndPosition); 2740 return; 2741 } 2742 2743 case CSSPropertyWebkitGridRowStart: { 2744 HANDLE_INHERIT_AND_INITIAL(gridItemRowStart, GridItemRowStart); 2745 GridPosition rowStartPosition; 2746 if (!createGridPosition(value, rowStartPosition)) 2747 return; 2748 state.style()->setGridItemRowStart(rowStartPosition); 2749 return; 2750 } 2751 case CSSPropertyWebkitGridRowEnd: { 2752 HANDLE_INHERIT_AND_INITIAL(gridItemRowEnd, GridItemRowEnd); 2753 GridPosition rowEndPosition; 2754 if (!createGridPosition(value, rowEndPosition)) 2755 return; 2756 state.style()->setGridItemRowEnd(rowEndPosition); 2757 return; 2758 } 2759 case CSSPropertyWebkitGridTemplateAreas: { 2760 if (isInherit) { 2761 state.style()->setNamedGridArea(state.parentStyle()->namedGridArea()); 2762 state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount()); 2763 state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount()); 2764 return; 2765 } 2766 if (isInitial) { 2767 state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea()); 2768 state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount()); 2769 state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount()); 2770 return; 2771 } 2772 2773 if (value->isPrimitiveValue()) { 2774 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); 2775 return; 2776 } 2777 2778 CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value); 2779 const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap(); 2780 2781 NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); 2782 NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines(); 2783 createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns); 2784 createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows); 2785 state.style()->setNamedGridColumnLines(namedGridColumnLines); 2786 state.style()->setNamedGridRowLines(namedGridRowLines); 2787 2788 state.style()->setNamedGridArea(gridTemplateAreasValue->gridAreaMap()); 2789 state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount()); 2790 state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount()); 2791 return; 2792 } 2793 case CSSPropertyWebkitGridAutoFlow: { 2794 HANDLE_INHERIT_AND_INITIAL(gridAutoFlow, GridAutoFlow); 2795 if (!value->isValueList()) 2796 return; 2797 CSSValueList* list = toCSSValueList(value); 2798 2799 if (!list->length()) { 2800 state.style()->setGridAutoFlow(RenderStyle::initialGridAutoFlow()); 2801 return; 2802 } 2803 2804 CSSPrimitiveValue* first = toCSSPrimitiveValue(list->item(0)); 2805 CSSPrimitiveValue* second = list->length() == 2 ? toCSSPrimitiveValue(list->item(1)) : nullptr; 2806 2807 GridAutoFlow autoFlow = RenderStyle::initialGridAutoFlow(); 2808 switch (first->getValueID()) { 2809 case CSSValueRow: 2810 if (second) 2811 autoFlow = second->getValueID() == CSSValueDense ? AutoFlowRowDense : AutoFlowStackRow; 2812 else 2813 autoFlow = AutoFlowRow; 2814 break; 2815 case CSSValueColumn: 2816 if (second) 2817 autoFlow = second->getValueID() == CSSValueDense ? AutoFlowColumnDense : AutoFlowStackColumn; 2818 else 2819 autoFlow = AutoFlowColumn; 2820 break; 2821 default: 2822 ASSERT_NOT_REACHED(); 2823 break; 2824 } 2825 2826 state.style()->setGridAutoFlow(autoFlow); 2827 return; 2828 } 2829#endif /* ENABLE(CSS_GRID_LAYOUT) */ 2830 case CSSPropertyWebkitJustifySelf: { 2831 HANDLE_INHERIT_AND_INITIAL(justifySelf, JustifySelf); 2832 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 2833 if (Pair* pairValue = primitiveValue->getPairValue()) { 2834 state.style()->setJustifySelf(*pairValue->first()); 2835 state.style()->setJustifySelfOverflowAlignment(*pairValue->second()); 2836 } else 2837 state.style()->setJustifySelf(*primitiveValue); 2838 return; 2839 } 2840 // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version. 2841 case CSSPropertyTransitionDelay: 2842 case CSSPropertyTransitionDuration: 2843 case CSSPropertyTransitionProperty: 2844 case CSSPropertyTransitionTimingFunction: 2845 return; 2846 // These properties are implemented in the DeprecatedStyleBuilder lookup table. 2847 case CSSPropertyBackgroundAttachment: 2848 case CSSPropertyBackgroundClip: 2849 case CSSPropertyBackgroundColor: 2850 case CSSPropertyBackgroundImage: 2851 case CSSPropertyBackgroundOrigin: 2852 case CSSPropertyBackgroundPositionX: 2853 case CSSPropertyBackgroundPositionY: 2854 case CSSPropertyBackgroundRepeatX: 2855 case CSSPropertyBackgroundRepeatY: 2856 case CSSPropertyBackgroundSize: 2857 case CSSPropertyBorderBottomColor: 2858 case CSSPropertyBorderBottomLeftRadius: 2859 case CSSPropertyBorderBottomRightRadius: 2860 case CSSPropertyBorderBottomStyle: 2861 case CSSPropertyBorderBottomWidth: 2862 case CSSPropertyBorderCollapse: 2863 case CSSPropertyBorderImageOutset: 2864 case CSSPropertyBorderImageRepeat: 2865 case CSSPropertyBorderImageSlice: 2866 case CSSPropertyBorderImageSource: 2867 case CSSPropertyBorderImageWidth: 2868 case CSSPropertyBorderLeftColor: 2869 case CSSPropertyBorderLeftStyle: 2870 case CSSPropertyBorderLeftWidth: 2871 case CSSPropertyBorderRightColor: 2872 case CSSPropertyBorderRightStyle: 2873 case CSSPropertyBorderRightWidth: 2874 case CSSPropertyBorderTopColor: 2875 case CSSPropertyBorderTopLeftRadius: 2876 case CSSPropertyBorderTopRightRadius: 2877 case CSSPropertyBorderTopStyle: 2878 case CSSPropertyBorderTopWidth: 2879 case CSSPropertyBottom: 2880 case CSSPropertyBoxSizing: 2881 case CSSPropertyCaptionSide: 2882 case CSSPropertyClear: 2883 case CSSPropertyClip: 2884 case CSSPropertyColor: 2885 case CSSPropertyCounterIncrement: 2886 case CSSPropertyCounterReset: 2887 case CSSPropertyCursor: 2888 case CSSPropertyDirection: 2889 case CSSPropertyDisplay: 2890 case CSSPropertyEmptyCells: 2891 case CSSPropertyFloat: 2892 case CSSPropertyFontSize: 2893 case CSSPropertyFontStyle: 2894 case CSSPropertyFontVariant: 2895 case CSSPropertyFontWeight: 2896 case CSSPropertyHeight: 2897#if ENABLE(CSS_IMAGE_ORIENTATION) 2898 case CSSPropertyImageOrientation: 2899#endif 2900 case CSSPropertyImageRendering: 2901#if ENABLE(CSS_IMAGE_RESOLUTION) 2902 case CSSPropertyImageResolution: 2903#endif 2904 case CSSPropertyLeft: 2905 case CSSPropertyLetterSpacing: 2906 case CSSPropertyLineHeight: 2907 case CSSPropertyListStyleImage: 2908 case CSSPropertyListStylePosition: 2909 case CSSPropertyListStyleType: 2910 case CSSPropertyMarginBottom: 2911 case CSSPropertyMarginLeft: 2912 case CSSPropertyMarginRight: 2913 case CSSPropertyMarginTop: 2914 case CSSPropertyMaxHeight: 2915 case CSSPropertyMaxWidth: 2916 case CSSPropertyMinHeight: 2917 case CSSPropertyMinWidth: 2918 case CSSPropertyObjectFit: 2919 case CSSPropertyOpacity: 2920 case CSSPropertyOrphans: 2921 case CSSPropertyOutlineColor: 2922 case CSSPropertyOutlineOffset: 2923 case CSSPropertyOutlineStyle: 2924 case CSSPropertyOutlineWidth: 2925 case CSSPropertyOverflowWrap: 2926 case CSSPropertyOverflowX: 2927 case CSSPropertyOverflowY: 2928 case CSSPropertyPaddingBottom: 2929 case CSSPropertyPaddingLeft: 2930 case CSSPropertyPaddingRight: 2931 case CSSPropertyPaddingTop: 2932 case CSSPropertyPageBreakAfter: 2933 case CSSPropertyPageBreakBefore: 2934 case CSSPropertyPageBreakInside: 2935 case CSSPropertyPointerEvents: 2936 case CSSPropertyPosition: 2937 case CSSPropertyResize: 2938 case CSSPropertyRight: 2939 case CSSPropertySize: 2940 case CSSPropertySpeak: 2941 case CSSPropertyTabSize: 2942 case CSSPropertyTableLayout: 2943 case CSSPropertyTextAlign: 2944 case CSSPropertyTextDecoration: 2945 case CSSPropertyTextIndent: 2946 case CSSPropertyTextOverflow: 2947 case CSSPropertyTextRendering: 2948 case CSSPropertyTextTransform: 2949 case CSSPropertyTop: 2950 case CSSPropertyUnicodeBidi: 2951 case CSSPropertyVerticalAlign: 2952 case CSSPropertyVisibility: 2953 case CSSPropertyWebkitAnimationDelay: 2954 case CSSPropertyWebkitAnimationDirection: 2955 case CSSPropertyWebkitAnimationDuration: 2956 case CSSPropertyWebkitAnimationFillMode: 2957 case CSSPropertyWebkitAnimationIterationCount: 2958 case CSSPropertyWebkitAnimationName: 2959 case CSSPropertyWebkitAnimationPlayState: 2960 case CSSPropertyWebkitAnimationTimingFunction: 2961 case CSSPropertyWebkitAppearance: 2962 case CSSPropertyWebkitAspectRatio: 2963 case CSSPropertyWebkitBackfaceVisibility: 2964 case CSSPropertyWebkitBackgroundClip: 2965 case CSSPropertyWebkitBackgroundComposite: 2966 case CSSPropertyWebkitBackgroundOrigin: 2967 case CSSPropertyWebkitBackgroundSize: 2968 case CSSPropertyWebkitBorderFit: 2969 case CSSPropertyWebkitBorderHorizontalSpacing: 2970 case CSSPropertyWebkitBorderImage: 2971 case CSSPropertyWebkitBorderVerticalSpacing: 2972 case CSSPropertyWebkitBoxAlign: 2973#if ENABLE(CSS_BOX_DECORATION_BREAK) 2974 case CSSPropertyWebkitBoxDecorationBreak: 2975#endif 2976 case CSSPropertyWebkitBoxDirection: 2977 case CSSPropertyWebkitBoxFlex: 2978 case CSSPropertyWebkitBoxFlexGroup: 2979 case CSSPropertyWebkitBoxLines: 2980 case CSSPropertyWebkitBoxOrdinalGroup: 2981 case CSSPropertyWebkitBoxOrient: 2982 case CSSPropertyWebkitBoxPack: 2983 case CSSPropertyWebkitColorCorrection: 2984 case CSSPropertyWebkitColumnAxis: 2985 case CSSPropertyWebkitColumnBreakAfter: 2986 case CSSPropertyWebkitColumnBreakBefore: 2987 case CSSPropertyWebkitColumnBreakInside: 2988 case CSSPropertyWebkitColumnCount: 2989 case CSSPropertyWebkitColumnGap: 2990 case CSSPropertyWebkitColumnProgression: 2991 case CSSPropertyWebkitColumnRuleColor: 2992 case CSSPropertyWebkitColumnRuleStyle: 2993 case CSSPropertyWebkitColumnRuleWidth: 2994 case CSSPropertyWebkitColumnSpan: 2995 case CSSPropertyWebkitColumnWidth: 2996#if ENABLE(CURSOR_VISIBILITY) 2997 case CSSPropertyWebkitCursorVisibility: 2998#endif 2999 case CSSPropertyWebkitAlignContent: 3000 case CSSPropertyWebkitAlignItems: 3001 case CSSPropertyWebkitAlignSelf: 3002 case CSSPropertyWebkitFlexBasis: 3003 case CSSPropertyWebkitFlexDirection: 3004 case CSSPropertyWebkitFlexGrow: 3005 case CSSPropertyWebkitFlexShrink: 3006 case CSSPropertyWebkitFlexWrap: 3007 case CSSPropertyWebkitJustifyContent: 3008 case CSSPropertyWebkitOrder: 3009#if ENABLE(CSS_REGIONS) 3010 case CSSPropertyWebkitFlowFrom: 3011 case CSSPropertyWebkitFlowInto: 3012#endif 3013 case CSSPropertyWebkitFontKerning: 3014 case CSSPropertyWebkitFontSmoothing: 3015 case CSSPropertyWebkitFontVariantLigatures: 3016 case CSSPropertyWebkitHyphenateCharacter: 3017 case CSSPropertyWebkitHyphenateLimitAfter: 3018 case CSSPropertyWebkitHyphenateLimitBefore: 3019 case CSSPropertyWebkitHyphenateLimitLines: 3020 case CSSPropertyWebkitHyphens: 3021 case CSSPropertyWebkitLineAlign: 3022 case CSSPropertyWebkitLineBreak: 3023 case CSSPropertyWebkitLineClamp: 3024 case CSSPropertyWebkitLineGrid: 3025 case CSSPropertyWebkitLineSnap: 3026 case CSSPropertyWebkitMarqueeDirection: 3027 case CSSPropertyWebkitMarqueeIncrement: 3028 case CSSPropertyWebkitMarqueeRepetition: 3029 case CSSPropertyWebkitMarqueeSpeed: 3030 case CSSPropertyWebkitMarqueeStyle: 3031 case CSSPropertyWebkitMaskBoxImage: 3032 case CSSPropertyWebkitMaskBoxImageOutset: 3033 case CSSPropertyWebkitMaskBoxImageRepeat: 3034 case CSSPropertyWebkitMaskBoxImageSlice: 3035 case CSSPropertyWebkitMaskBoxImageSource: 3036 case CSSPropertyWebkitMaskBoxImageWidth: 3037 case CSSPropertyWebkitMaskClip: 3038 case CSSPropertyWebkitMaskComposite: 3039 case CSSPropertyWebkitMaskImage: 3040 case CSSPropertyWebkitMaskOrigin: 3041 case CSSPropertyWebkitMaskPositionX: 3042 case CSSPropertyWebkitMaskPositionY: 3043 case CSSPropertyWebkitMaskRepeatX: 3044 case CSSPropertyWebkitMaskRepeatY: 3045 case CSSPropertyWebkitMaskSize: 3046 case CSSPropertyWebkitMaskSourceType: 3047 case CSSPropertyWebkitNbspMode: 3048 case CSSPropertyWebkitPerspectiveOrigin: 3049 case CSSPropertyWebkitPerspectiveOriginX: 3050 case CSSPropertyWebkitPerspectiveOriginY: 3051 case CSSPropertyWebkitPrintColorAdjust: 3052#if ENABLE(CSS_REGIONS) 3053 case CSSPropertyWebkitRegionBreakAfter: 3054 case CSSPropertyWebkitRegionBreakBefore: 3055 case CSSPropertyWebkitRegionBreakInside: 3056 case CSSPropertyWebkitRegionFragment: 3057#endif 3058 case CSSPropertyWebkitRtlOrdering: 3059 case CSSPropertyWebkitRubyPosition: 3060 case CSSPropertyWebkitTextCombine: 3061#if ENABLE(CSS3_TEXT) 3062 case CSSPropertyWebkitTextAlignLast: 3063 case CSSPropertyWebkitTextJustify: 3064#endif // CSS3_TEXT 3065 case CSSPropertyWebkitTextDecorationLine: 3066 case CSSPropertyWebkitTextDecorationStyle: 3067 case CSSPropertyWebkitTextDecorationColor: 3068 case CSSPropertyWebkitTextDecorationSkip: 3069 case CSSPropertyWebkitTextUnderlinePosition: 3070 case CSSPropertyWebkitTextEmphasisColor: 3071 case CSSPropertyWebkitTextEmphasisPosition: 3072 case CSSPropertyWebkitTextEmphasisStyle: 3073 case CSSPropertyWebkitTextFillColor: 3074 case CSSPropertyWebkitTextSecurity: 3075 case CSSPropertyWebkitTextStrokeColor: 3076 case CSSPropertyWebkitTransformOriginX: 3077 case CSSPropertyWebkitTransformOriginY: 3078 case CSSPropertyWebkitTransformOriginZ: 3079 case CSSPropertyWebkitTransformStyle: 3080 case CSSPropertyWebkitTransitionDelay: 3081 case CSSPropertyWebkitTransitionDuration: 3082 case CSSPropertyWebkitTransitionProperty: 3083 case CSSPropertyWebkitTransitionTimingFunction: 3084 case CSSPropertyWebkitUserDrag: 3085 case CSSPropertyWebkitUserModify: 3086 case CSSPropertyWebkitUserSelect: 3087 case CSSPropertyWebkitClipPath: 3088#if ENABLE(CSS_SHAPES) 3089 case CSSPropertyWebkitShapeMargin: 3090 case CSSPropertyWebkitShapeImageThreshold: 3091 case CSSPropertyWebkitShapeOutside: 3092#endif 3093 case CSSPropertyWhiteSpace: 3094 case CSSPropertyWidows: 3095 case CSSPropertyWidth: 3096 case CSSPropertyWordBreak: 3097 case CSSPropertyWordSpacing: 3098 case CSSPropertyWordWrap: 3099 case CSSPropertyZIndex: 3100 case CSSPropertyZoom: 3101#if ENABLE(CSS_DEVICE_ADAPTATION) 3102 case CSSPropertyMaxZoom: 3103 case CSSPropertyMinZoom: 3104 case CSSPropertyOrientation: 3105 case CSSPropertyUserZoom: 3106#endif 3107 ASSERT_NOT_REACHED(); 3108 return; 3109 default: 3110 // Try the SVG properties 3111 applySVGProperty(id, value); 3112 return; 3113 } 3114} 3115 3116PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value) 3117{ 3118 if (value->isImageValue()) 3119 return cachedOrPendingFromValue(property, toCSSImageValue(value)); 3120 3121 if (value->isImageGeneratorValue()) { 3122 if (value->isGradientValue()) 3123 return generatedOrPendingFromValue(property, *toCSSGradientValue(value)->gradientWithStylesResolved(this)); 3124 return generatedOrPendingFromValue(property, toCSSImageGeneratorValue(*value)); 3125 } 3126 3127#if ENABLE(CSS_IMAGE_SET) 3128 if (value->isImageSetValue()) 3129 return setOrPendingFromValue(property, toCSSImageSetValue(value)); 3130#endif 3131 3132 if (value->isCursorImageValue()) 3133 return cursorOrPendingFromValue(property, toCSSCursorImageValue(value)); 3134 3135 return 0; 3136} 3137 3138PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value) 3139{ 3140 RefPtr<StyleImage> image = value->cachedOrPendingImage(); 3141 if (image && image->isPendingImage()) 3142 m_state.pendingImageProperties().set(property, value); 3143 return image.release(); 3144} 3145 3146PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value) 3147{ 3148#if ENABLE(CSS_FILTERS) 3149 if (value.isFilterImageValue()) { 3150 // FilterImage needs to calculate FilterOperations. 3151 toCSSFilterImageValue(value).createFilterOperations(this); 3152 } 3153#endif 3154 if (value.isPending()) { 3155 m_state.pendingImageProperties().set(property, &value); 3156 return StylePendingImage::create(&value); 3157 } 3158 return StyleGeneratedImage::create(value); 3159} 3160 3161#if ENABLE(CSS_IMAGE_SET) 3162PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value) 3163{ 3164 RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document()); 3165 if (image && image->isPendingImage()) 3166 m_state.pendingImageProperties().set(property, value); 3167 return image.release(); 3168} 3169#endif 3170 3171PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue* value) 3172{ 3173 RefPtr<StyleImage> image = value->cachedOrPendingImage(document()); 3174 if (image && image->isPendingImage()) 3175 m_state.pendingImageProperties().set(property, value); 3176 return image.release(); 3177} 3178 3179#if ENABLE(IOS_TEXT_AUTOSIZING) 3180void StyleResolver::checkForTextSizeAdjust(RenderStyle* style) 3181{ 3182 if (style->textSizeAdjust().isAuto()) 3183 return; 3184 3185 FontDescription newFontDescription(style->fontDescription()); 3186 if (!style->textSizeAdjust().isNone()) 3187 newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier()); 3188 else 3189 newFontDescription.setComputedSize(newFontDescription.specifiedSize()); 3190 style->setFontDescription(newFontDescription); 3191} 3192#endif 3193 3194void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle) 3195{ 3196 if (!parentStyle) 3197 return; 3198 3199 if (style->effectiveZoom() == parentStyle->effectiveZoom()) 3200 return; 3201 3202 const FontDescription& childFont = style->fontDescription(); 3203 FontDescription newFontDescription(childFont); 3204 setFontSize(newFontDescription, childFont.specifiedSize()); 3205 style->setFontDescription(newFontDescription); 3206} 3207 3208void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle) 3209{ 3210 const FontDescription& childFont = style->fontDescription(); 3211 3212 if (childFont.isAbsoluteSize() || !parentStyle) 3213 return; 3214 3215 const FontDescription& parentFont = parentStyle->fontDescription(); 3216 if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize()) 3217 return; 3218 3219 // For now, lump all families but monospace together. 3220 if (childFont.genericFamily() != FontDescription::MonospaceFamily 3221 && parentFont.genericFamily() != FontDescription::MonospaceFamily) 3222 return; 3223 3224 // We know the parent is monospace or the child is monospace, and that font 3225 // size was unspecified. We want to scale our font size as appropriate. 3226 // If the font uses a keyword size, then we refetch from the table rather than 3227 // multiplying by our scale factor. 3228 float size; 3229 if (childFont.keywordSize()) 3230 size = Style::fontSizeForKeyword(CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize(), document()); 3231 else { 3232 Settings* settings = documentSettings(); 3233 float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize()) 3234 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize() 3235 : 1; 3236 size = parentFont.useFixedDefaultSize() ? 3237 childFont.specifiedSize() / fixedScaleFactor : 3238 childFont.specifiedSize() * fixedScaleFactor; 3239 } 3240 3241 FontDescription newFontDescription(childFont); 3242 setFontSize(newFontDescription, size); 3243 style->setFontDescription(newFontDescription); 3244} 3245 3246void StyleResolver::initializeFontStyle(Settings* settings) 3247{ 3248 FontDescription fontDescription; 3249 fontDescription.setGenericFamily(FontDescription::StandardFamily); 3250 fontDescription.setRenderingMode(settings->fontRenderingMode()); 3251 fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled()); 3252 const AtomicString& standardFontFamily = documentSettings()->standardFontFamily(); 3253 if (!standardFontFamily.isEmpty()) 3254 fontDescription.setOneFamily(standardFontFamily); 3255 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); 3256 setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document())); 3257 m_state.style()->setLineHeight(RenderStyle::initialLineHeight()); 3258 m_state.setLineHeightValue(0); 3259 setFontDescription(fontDescription); 3260} 3261 3262void StyleResolver::setFontSize(FontDescription& fontDescription, float size) 3263{ 3264 fontDescription.setSpecifiedSize(size); 3265 fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document())); 3266} 3267 3268static Color colorForCSSValue(CSSValueID cssValueId) 3269{ 3270 struct ColorValue { 3271 CSSValueID cssValueId; 3272 RGBA32 color; 3273 }; 3274 3275 static const ColorValue colorValues[] = { 3276 { CSSValueAqua, 0xFF00FFFF }, 3277 { CSSValueBlack, 0xFF000000 }, 3278 { CSSValueBlue, 0xFF0000FF }, 3279 { CSSValueFuchsia, 0xFFFF00FF }, 3280 { CSSValueGray, 0xFF808080 }, 3281 { CSSValueGreen, 0xFF008000 }, 3282 { CSSValueGrey, 0xFF808080 }, 3283 { CSSValueLime, 0xFF00FF00 }, 3284 { CSSValueMaroon, 0xFF800000 }, 3285 { CSSValueNavy, 0xFF000080 }, 3286 { CSSValueOlive, 0xFF808000 }, 3287 { CSSValueOrange, 0xFFFFA500 }, 3288 { CSSValuePurple, 0xFF800080 }, 3289 { CSSValueRed, 0xFFFF0000 }, 3290 { CSSValueSilver, 0xFFC0C0C0 }, 3291 { CSSValueTeal, 0xFF008080 }, 3292 { CSSValueTransparent, 0x00000000 }, 3293 { CSSValueWhite, 0xFFFFFFFF }, 3294 { CSSValueYellow, 0xFFFFFF00 }, 3295 { CSSValueInvalid, CSSValueInvalid } 3296 }; 3297 3298 for (const ColorValue* col = colorValues; col->cssValueId; ++col) { 3299 if (col->cssValueId == cssValueId) 3300 return col->color; 3301 } 3302 return RenderTheme::defaultTheme()->systemColor(cssValueId); 3303} 3304 3305bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue* value) 3306{ 3307 int ident = value->getValueID(); 3308 switch (ident) { 3309 case CSSValueWebkitText: 3310 case CSSValueWebkitLink: 3311 case CSSValueWebkitActivelink: 3312 case CSSValueCurrentcolor: 3313 return true; 3314 default: 3315 return false; 3316 } 3317} 3318 3319Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const 3320{ 3321 if (value->isRGBColor()) 3322 return Color(value->getRGBA32Value()); 3323 3324 const State& state = m_state; 3325 CSSValueID ident = value->getValueID(); 3326 switch (ident) { 3327 case 0: 3328 return Color(); 3329 case CSSValueWebkitText: 3330 return state.document().textColor(); 3331 case CSSValueWebkitLink: 3332 return (state.element()->isLink() && forVisitedLink) ? state.document().visitedLinkColor() : state.document().linkColor(); 3333 case CSSValueWebkitActivelink: 3334 return state.document().activeLinkColor(); 3335 case CSSValueWebkitFocusRingColor: 3336 return RenderTheme::focusRingColor(); 3337 case CSSValueCurrentcolor: 3338 return state.style()->color(); 3339 default: 3340 return colorForCSSValue(ident); 3341 } 3342} 3343 3344void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result) 3345{ 3346 m_viewportDependentMediaQueryResults.append(std::make_unique<MediaQueryResult>(*expr, result)); 3347} 3348 3349bool StyleResolver::hasMediaQueriesAffectedByViewportChange() const 3350{ 3351 unsigned s = m_viewportDependentMediaQueryResults.size(); 3352 for (unsigned i = 0; i < s; i++) { 3353 if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result) 3354 return true; 3355 } 3356 return false; 3357} 3358 3359#if ENABLE(CSS_FILTERS) 3360static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type) 3361{ 3362 switch (type) { 3363 case WebKitCSSFilterValue::ReferenceFilterOperation: 3364 return FilterOperation::REFERENCE; 3365 case WebKitCSSFilterValue::GrayscaleFilterOperation: 3366 return FilterOperation::GRAYSCALE; 3367 case WebKitCSSFilterValue::SepiaFilterOperation: 3368 return FilterOperation::SEPIA; 3369 case WebKitCSSFilterValue::SaturateFilterOperation: 3370 return FilterOperation::SATURATE; 3371 case WebKitCSSFilterValue::HueRotateFilterOperation: 3372 return FilterOperation::HUE_ROTATE; 3373 case WebKitCSSFilterValue::InvertFilterOperation: 3374 return FilterOperation::INVERT; 3375 case WebKitCSSFilterValue::OpacityFilterOperation: 3376 return FilterOperation::OPACITY; 3377 case WebKitCSSFilterValue::BrightnessFilterOperation: 3378 return FilterOperation::BRIGHTNESS; 3379 case WebKitCSSFilterValue::ContrastFilterOperation: 3380 return FilterOperation::CONTRAST; 3381 case WebKitCSSFilterValue::BlurFilterOperation: 3382 return FilterOperation::BLUR; 3383 case WebKitCSSFilterValue::DropShadowFilterOperation: 3384 return FilterOperation::DROP_SHADOW; 3385 case WebKitCSSFilterValue::UnknownFilterOperation: 3386 return FilterOperation::NONE; 3387 } 3388 return FilterOperation::NONE; 3389} 3390 3391void StyleResolver::loadPendingSVGDocuments() 3392{ 3393 State& state = m_state; 3394 3395 // Crash reports indicate that we've seen calls to this function when our 3396 // style is NULL. We don't know exactly why this happens. Our guess is 3397 // reentering styleForElement(). 3398 ASSERT(state.style()); 3399 if (!state.style() || !state.style()->hasFilter() || state.filtersWithPendingSVGDocuments().isEmpty()) 3400 return; 3401 3402 CachedResourceLoader* cachedResourceLoader = state.document().cachedResourceLoader(); 3403 for (auto& filterOperation : state.filtersWithPendingSVGDocuments()) 3404 filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader); 3405 3406 state.filtersWithPendingSVGDocuments().clear(); 3407} 3408 3409bool StyleResolver::createFilterOperations(CSSValue* inValue, FilterOperations& outOperations) 3410{ 3411 State& state = m_state; 3412 ASSERT(outOperations.isEmpty()); 3413 3414 if (!inValue) 3415 return false; 3416 3417 if (inValue->isPrimitiveValue()) { 3418 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue); 3419 if (primitiveValue->getValueID() == CSSValueNone) 3420 return true; 3421 } 3422 3423 if (!inValue->isValueList()) 3424 return false; 3425 3426 FilterOperations operations; 3427 for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { 3428 CSSValue* currValue = i.value(); 3429 if (!currValue->isWebKitCSSFilterValue()) 3430 continue; 3431 3432 WebKitCSSFilterValue* filterValue = toWebKitCSSFilterValue(i.value()); 3433 FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType()); 3434 3435 if (operationType == FilterOperation::REFERENCE) { 3436 if (filterValue->length() != 1) 3437 continue; 3438 CSSValue* argument = filterValue->itemWithoutBoundsCheck(0); 3439 3440 if (!argument->isPrimitiveValue()) 3441 continue; 3442 3443 CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(*argument); 3444 String cssUrl = primitiveValue.getStringValue(); 3445 URL url = m_state.document().completeURL(cssUrl); 3446 3447 RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier()); 3448 if (SVGURIReference::isExternalURIReference(cssUrl, m_state.document())) 3449 state.filtersWithPendingSVGDocuments().append(operation); 3450 3451 operations.operations().append(operation); 3452 continue; 3453 } 3454 3455 // Check that all parameters are primitive values, with the 3456 // exception of drop shadow which has a CSSShadowValue parameter. 3457 CSSPrimitiveValue* firstValue = nullptr; 3458 if (operationType != FilterOperation::DROP_SHADOW) { 3459 bool haveNonPrimitiveValue = false; 3460 for (unsigned j = 0; j < filterValue->length(); ++j) { 3461 if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { 3462 haveNonPrimitiveValue = true; 3463 break; 3464 } 3465 } 3466 if (haveNonPrimitiveValue) 3467 continue; 3468 if (filterValue->length()) 3469 firstValue = toCSSPrimitiveValue(filterValue->itemWithoutBoundsCheck(0)); 3470 } 3471 3472 switch (filterValue->operationType()) { 3473 case WebKitCSSFilterValue::GrayscaleFilterOperation: 3474 case WebKitCSSFilterValue::SepiaFilterOperation: 3475 case WebKitCSSFilterValue::SaturateFilterOperation: { 3476 double amount = 1; 3477 if (filterValue->length() == 1) { 3478 amount = firstValue->getDoubleValue(); 3479 if (firstValue->isPercentage()) 3480 amount /= 100; 3481 } 3482 3483 operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType)); 3484 break; 3485 } 3486 case WebKitCSSFilterValue::HueRotateFilterOperation: { 3487 double angle = 0; 3488 if (filterValue->length() == 1) 3489 angle = firstValue->computeDegrees(); 3490 3491 operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType)); 3492 break; 3493 } 3494 case WebKitCSSFilterValue::InvertFilterOperation: 3495 case WebKitCSSFilterValue::BrightnessFilterOperation: 3496 case WebKitCSSFilterValue::ContrastFilterOperation: 3497 case WebKitCSSFilterValue::OpacityFilterOperation: { 3498 double amount = (filterValue->operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1; 3499 if (filterValue->length() == 1) { 3500 amount = firstValue->getDoubleValue(); 3501 if (firstValue->isPercentage()) 3502 amount /= 100; 3503 } 3504 3505 operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType)); 3506 break; 3507 } 3508 case WebKitCSSFilterValue::BlurFilterOperation: { 3509 Length stdDeviation = Length(0, Fixed); 3510 if (filterValue->length() >= 1) 3511 stdDeviation = convertToFloatLength(firstValue, state.cssToLengthConversionData()); 3512 if (stdDeviation.isUndefined()) 3513 return false; 3514 3515 operations.operations().append(BlurFilterOperation::create(stdDeviation)); 3516 break; 3517 } 3518 case WebKitCSSFilterValue::DropShadowFilterOperation: { 3519 if (filterValue->length() != 1) 3520 return false; 3521 3522 CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0); 3523 if (!cssValue->isShadowValue()) 3524 continue; 3525 3526 CSSShadowValue* item = toCSSShadowValue(cssValue); 3527 int x = item->x->computeLength<int>(state.cssToLengthConversionData()); 3528 int y = item->y->computeLength<int>(state.cssToLengthConversionData()); 3529 IntPoint location(x, y); 3530 int blur = item->blur ? item->blur->computeLength<int>(state.cssToLengthConversionData()) : 0; 3531 Color color; 3532 if (item->color) 3533 color = colorFromPrimitiveValue(item->color.get()); 3534 3535 operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent)); 3536 break; 3537 } 3538 case WebKitCSSFilterValue::UnknownFilterOperation: 3539 default: 3540 ASSERT_NOT_REACHED(); 3541 break; 3542 } 3543 } 3544 3545 outOperations = operations; 3546 return true; 3547} 3548 3549#endif 3550 3551PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options) 3552{ 3553 if (auto imageValue = pendingImage.cssImageValue()) 3554 return imageValue->cachedImage(m_state.document().cachedResourceLoader(), options); 3555 3556 if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) { 3557 imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader()); 3558 return StyleGeneratedImage::create(*imageGeneratorValue); 3559 } 3560 3561 if (auto cursorImageValue = pendingImage.cssCursorImageValue()) 3562 return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader()); 3563 3564#if ENABLE(CSS_IMAGE_SET) 3565 if (auto imageSetValue = pendingImage.cssImageSetValue()) 3566 return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader(), options); 3567#endif 3568 3569 return nullptr; 3570} 3571 3572PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage) 3573{ 3574 return loadPendingImage(pendingImage, CachedResourceLoader::defaultCachedResourceOptions()); 3575} 3576 3577#if ENABLE(CSS_SHAPES) 3578void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue) 3579{ 3580 if (!shapeValue) 3581 return; 3582 3583 StyleImage* image = shapeValue->image(); 3584 if (!image || !image->isPendingImage()) 3585 return; 3586 3587 auto& pendingImage = toStylePendingImage(*image); 3588 3589 ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions(); 3590 options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled); 3591 options.setAllowCredentials(DoNotAllowStoredCredentials); 3592 3593 shapeValue->setImage(loadPendingImage(pendingImage, options)); 3594} 3595#endif 3596 3597void StyleResolver::loadPendingImages() 3598{ 3599 if (m_state.pendingImageProperties().isEmpty()) 3600 return; 3601 3602 auto end = m_state.pendingImageProperties().end().keys(); 3603 for (auto it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) { 3604 CSSPropertyID currentProperty = *it; 3605 3606 switch (currentProperty) { 3607 case CSSPropertyBackgroundImage: { 3608 for (FillLayer* backgroundLayer = m_state.style()->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) { 3609 auto styleImage = backgroundLayer->image(); 3610 if (styleImage && styleImage->isPendingImage()) 3611 backgroundLayer->setImage(loadPendingImage(toStylePendingImage(*styleImage))); 3612 } 3613 break; 3614 } 3615 case CSSPropertyContent: { 3616 for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) { 3617 if (contentData->isImage()) { 3618 auto& styleImage = toImageContentData(contentData)->image(); 3619 if (styleImage.isPendingImage()) { 3620 RefPtr<StyleImage> loadedImage = loadPendingImage(toStylePendingImage(styleImage)); 3621 if (loadedImage) 3622 toImageContentData(contentData)->setImage(loadedImage.release()); 3623 } 3624 } 3625 } 3626 break; 3627 } 3628 case CSSPropertyCursor: { 3629 if (CursorList* cursorList = m_state.style()->cursors()) { 3630 for (size_t i = 0; i < cursorList->size(); ++i) { 3631 CursorData& currentCursor = cursorList->at(i); 3632 auto styleImage = currentCursor.image(); 3633 if (styleImage && styleImage->isPendingImage()) 3634 currentCursor.setImage(loadPendingImage(toStylePendingImage(*styleImage))); 3635 } 3636 } 3637 break; 3638 } 3639 case CSSPropertyListStyleImage: { 3640 auto styleImage = m_state.style()->listStyleImage(); 3641 if (styleImage && styleImage->isPendingImage()) 3642 m_state.style()->setListStyleImage(loadPendingImage(toStylePendingImage(*styleImage))); 3643 break; 3644 } 3645 case CSSPropertyBorderImageSource: { 3646 auto styleImage = m_state.style()->borderImageSource(); 3647 if (styleImage && styleImage->isPendingImage()) 3648 m_state.style()->setBorderImageSource(loadPendingImage(toStylePendingImage(*styleImage))); 3649 break; 3650 } 3651 case CSSPropertyWebkitBoxReflect: { 3652 if (StyleReflection* reflection = m_state.style()->boxReflect()) { 3653 const NinePieceImage& maskImage = reflection->mask(); 3654 auto styleImage = maskImage.image(); 3655 if (styleImage && styleImage->isPendingImage()) { 3656 RefPtr<StyleImage> loadedImage = loadPendingImage(toStylePendingImage(*styleImage)); 3657 reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule())); 3658 } 3659 } 3660 break; 3661 } 3662 case CSSPropertyWebkitMaskBoxImageSource: { 3663 auto styleImage = m_state.style()->maskBoxImageSource(); 3664 if (styleImage && styleImage->isPendingImage()) 3665 m_state.style()->setMaskBoxImageSource(loadPendingImage(toStylePendingImage(*styleImage))); 3666 break; 3667 } 3668 case CSSPropertyWebkitMaskImage: { 3669 for (FillLayer* maskLayer = m_state.style()->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) { 3670 auto styleImage = maskLayer->image(); 3671 if (styleImage && styleImage->isPendingImage()) 3672 maskLayer->setImage(loadPendingImage(toStylePendingImage(*styleImage))); 3673 } 3674 break; 3675 } 3676#if ENABLE(CSS_SHAPES) 3677 case CSSPropertyWebkitShapeOutside: 3678 loadPendingShapeImage(m_state.style()->shapeOutside()); 3679 break; 3680#endif 3681 default: 3682 ASSERT_NOT_REACHED(); 3683 } 3684 } 3685 3686 m_state.pendingImageProperties().clear(); 3687} 3688 3689#ifndef NDEBUG 3690static bool inLoadPendingResources = false; 3691#endif 3692 3693void StyleResolver::loadPendingResources() 3694{ 3695 // We've seen crashes in all three of the functions below. Some of them 3696 // indicate that style() is NULL. This NULL check will cut down on total 3697 // crashes, while the ASSERT will help us find the cause in debug builds. 3698 ASSERT(style()); 3699 if (!style()) 3700 return; 3701 3702#ifndef NDEBUG 3703 // Re-entering this function will probably mean trouble. Catch it in debug builds. 3704 ASSERT(!inLoadPendingResources); 3705 inLoadPendingResources = true; 3706#endif 3707 3708 // Start loading images referenced by this style. 3709 loadPendingImages(); 3710 3711#if ENABLE(CSS_FILTERS) 3712 // Start loading the SVG Documents referenced by this style. 3713 loadPendingSVGDocuments(); 3714#endif 3715 3716#ifndef NDEBUG 3717 inLoadPendingResources = false; 3718#endif 3719} 3720 3721inline StyleResolver::MatchedProperties::MatchedProperties() 3722 : possiblyPaddedMember(0) 3723{ 3724} 3725 3726StyleResolver::MatchedProperties::~MatchedProperties() 3727{ 3728} 3729 3730StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode) 3731 : m_direction(direction) 3732 , m_writingMode(writingMode) 3733{ 3734} 3735 3736inline bool StyleResolver::CascadedProperties::hasProperty(CSSPropertyID id) const 3737{ 3738 ASSERT(id < m_propertyIsPresent.size()); 3739 return m_propertyIsPresent[id]; 3740} 3741 3742inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id) 3743{ 3744 return m_properties[id]; 3745} 3746 3747void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType) 3748{ 3749 ASSERT(linkMatchType <= SelectorChecker::MatchAll); 3750 property.id = id; 3751 if (linkMatchType == SelectorChecker::MatchAll) { 3752 property.cssValue[0] = &cssValue; 3753 property.cssValue[SelectorChecker::MatchLink] = &cssValue; 3754 property.cssValue[SelectorChecker::MatchVisited] = &cssValue; 3755 } else 3756 property.cssValue[linkMatchType] = &cssValue; 3757} 3758 3759void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType) 3760{ 3761 if (CSSProperty::isDirectionAwareProperty(id)) 3762 id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode); 3763 3764 ASSERT(!shouldApplyPropertyInParseOrder(id)); 3765 3766 auto& property = m_properties[id]; 3767 ASSERT(id < m_propertyIsPresent.size()); 3768 if (!m_propertyIsPresent[id]) 3769 memset(property.cssValue, 0, sizeof(property.cssValue)); 3770 m_propertyIsPresent.set(id); 3771 setPropertyInternal(property, id, cssValue, linkMatchType); 3772} 3773 3774void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType) 3775{ 3776 ASSERT(!CSSProperty::isDirectionAwareProperty(id)); 3777 ASSERT(shouldApplyPropertyInParseOrder(id)); 3778 3779 Property property; 3780 memset(property.cssValue, 0, sizeof(property.cssValue)); 3781 setPropertyInternal(property, id, cssValue, linkMatchType); 3782 m_deferredProperties.append(property); 3783} 3784 3785bool StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType) 3786{ 3787 for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) { 3788 auto current = properties.propertyAt(i); 3789 if (isImportant != current.isImportant()) 3790 continue; 3791 if (inheritedOnly && !current.isInherited()) { 3792 // If the property value is explicitly inherited, we need to apply further non-inherited properties 3793 // as they might override the value inherited here. For this reason we don't allow declarations with 3794 // explicitly inherited properties to be cached. 3795 if (current.value()->isInheritedValue()) 3796 return false; 3797 continue; 3798 } 3799 CSSPropertyID propertyID = current.id(); 3800 3801 if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(propertyID)) 3802 continue; 3803#if ENABLE(VIDEO_TRACK) 3804 if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(propertyID)) 3805 continue; 3806#endif 3807 3808 if (shouldApplyPropertyInParseOrder(propertyID)) 3809 setDeferred(propertyID, *current.value(), linkMatchType); 3810 else 3811 set(propertyID, *current.value(), linkMatchType); 3812 } 3813 return true; 3814} 3815 3816bool StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly) 3817{ 3818 if (startIndex == -1) 3819 return true; 3820 3821 for (int i = startIndex; i <= endIndex; ++i) { 3822 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i]; 3823 if (!addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType)) 3824 return false; 3825 } 3826 return true; 3827} 3828 3829void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver) 3830{ 3831 for (auto& property : m_deferredProperties) 3832 property.apply(resolver); 3833} 3834 3835void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver) 3836{ 3837 State& state = resolver.state(); 3838 3839 // FIXME: It would be nice if line-height were less of a special snowflake. 3840 if (id == CSSPropertyLineHeight) { 3841 if (auto value = state.style()->insideLink() == NotInsideLink ? cssValue[0] : cssValue[SelectorChecker::MatchLink]) 3842 state.setLineHeightValue(value); 3843 return; 3844 } 3845 3846 if (cssValue[0]) { 3847 state.setApplyPropertyToRegularStyle(true); 3848 state.setApplyPropertyToVisitedLinkStyle(false); 3849 resolver.applyProperty(id, cssValue[0]); 3850 } 3851 3852 if (state.style()->insideLink() == NotInsideLink) 3853 return; 3854 3855 if (cssValue[SelectorChecker::MatchLink]) { 3856 state.setApplyPropertyToRegularStyle(true); 3857 state.setApplyPropertyToVisitedLinkStyle(false); 3858 resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink]); 3859 } 3860 3861 if (cssValue[SelectorChecker::MatchVisited]) { 3862 state.setApplyPropertyToRegularStyle(false); 3863 state.setApplyPropertyToVisitedLinkStyle(true); 3864 resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited]); 3865 } 3866 3867 state.setApplyPropertyToRegularStyle(true); 3868 state.setApplyPropertyToVisitedLinkStyle(false); 3869} 3870 3871void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty) 3872{ 3873 for (int id = firstProperty; id <= lastProperty; ++id) { 3874 CSSPropertyID propertyID = static_cast<CSSPropertyID>(id); 3875 if (!cascade.hasProperty(propertyID)) 3876 continue; 3877 auto& property = cascade.property(propertyID); 3878 ASSERT(!shouldApplyPropertyInParseOrder(propertyID)); 3879 property.apply(*this); 3880 } 3881} 3882 3883} // namespace WebCore 3884