CSSStyleSelector.cpp revision bb0dba49203d72577b8eac34537c9c671ba9bec7
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 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 * 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Library General Public 13 * License as published by the Free Software Foundation; either 14 * version 2 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Library General Public License for more details. 20 * 21 * You should have received a copy of the GNU Library General Public License 22 * along with this library; see the file COPYING.LIB. If not, write to 23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 * Boston, MA 02110-1301, USA. 25 */ 26 27#include "config.h" 28#include "CSSStyleSelector.h" 29 30#include "Attribute.h" 31#include "ContentData.h" 32#include "CounterContent.h" 33#include "CursorList.h" 34#include "CSSBorderImageValue.h" 35#include "CSSCursorImageValue.h" 36#include "CSSFontFaceRule.h" 37#include "CSSImportRule.h" 38#include "CSSLineBoxContainValue.h" 39#include "CSSMediaRule.h" 40#include "CSSPageRule.h" 41#include "CSSParser.h" 42#include "CSSPrimitiveValueMappings.h" 43#include "CSSPropertyNames.h" 44#include "CSSReflectValue.h" 45#include "CSSRuleList.h" 46#include "CSSSelector.h" 47#include "CSSSelectorList.h" 48#include "CSSStyleApplyProperty.h" 49#include "CSSStyleRule.h" 50#include "CSSStyleSheet.h" 51#include "CSSTimingFunctionValue.h" 52#include "CSSValueList.h" 53#include "CachedImage.h" 54#include "Counter.h" 55#include "FocusController.h" 56#include "FontFamilyValue.h" 57#include "FontValue.h" 58#include "Frame.h" 59#include "FrameView.h" 60#include "HTMLDocument.h" 61#include "HTMLElement.h" 62#include "HTMLInputElement.h" 63#include "HTMLNames.h" 64#include "HTMLTextAreaElement.h" 65#include "KeyframeList.h" 66#include "LinkHash.h" 67#include "Matrix3DTransformOperation.h" 68#include "MatrixTransformOperation.h" 69#include "MediaList.h" 70#include "MediaQueryEvaluator.h" 71#include "NodeRenderStyle.h" 72#include "Page.h" 73#include "PageGroup.h" 74#include "Pair.h" 75#include "PerspectiveTransformOperation.h" 76#include "QuotesData.h" 77#include "Rect.h" 78#include "RenderScrollbar.h" 79#include "RenderScrollbarTheme.h" 80#include "RenderStyleConstants.h" 81#include "RenderTheme.h" 82#include "RotateTransformOperation.h" 83#include "ScaleTransformOperation.h" 84#include "SelectionController.h" 85#include "Settings.h" 86#include "ShadowData.h" 87#include "ShadowValue.h" 88#include "SkewTransformOperation.h" 89#include "StyleCachedImage.h" 90#include "StylePendingImage.h" 91#include "StyleGeneratedImage.h" 92#include "StyleSheetList.h" 93#include "Text.h" 94#include "TransformationMatrix.h" 95#include "TranslateTransformOperation.h" 96#include "UserAgentStyleSheets.h" 97#include "WebKitCSSKeyframeRule.h" 98#include "WebKitCSSKeyframesRule.h" 99#include "WebKitCSSTransformValue.h" 100#include "XMLNames.h" 101#include <wtf/StdLibExtras.h> 102#include <wtf/Vector.h> 103 104#if USE(PLATFORM_STRATEGIES) 105#include "PlatformStrategies.h" 106#include "VisitedLinkStrategy.h" 107#endif 108 109#if ENABLE(DASHBOARD_SUPPORT) 110#include "DashboardRegion.h" 111#endif 112 113#if ENABLE(SVG) 114#include "XLinkNames.h" 115#include "SVGNames.h" 116#endif 117 118#if ENABLE(WML) 119#include "WMLNames.h" 120#endif 121 122#if PLATFORM(QT) 123#include <qwebhistoryinterface.h> 124#endif 125 126using namespace std; 127 128namespace WebCore { 129 130using namespace HTMLNames; 131 132#define HANDLE_INHERIT(prop, Prop) \ 133if (isInherit) { \ 134 m_style->set##Prop(m_parentStyle->prop()); \ 135 return; \ 136} 137 138#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ 139HANDLE_INHERIT(prop, Prop) \ 140if (isInitial) { \ 141 m_style->set##Prop(RenderStyle::initial##Prop()); \ 142 return; \ 143} 144 145#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ 146HANDLE_INHERIT(prop, Prop) \ 147if (isInitial) { \ 148 m_style->set##Prop(RenderStyle::initial##Value());\ 149 return;\ 150} 151 152#define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \ 153HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ 154if (primitiveValue) \ 155 m_style->set##Prop(*primitiveValue); 156 157#define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \ 158HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ 159if (primitiveValue) \ 160 m_style->set##Prop(*primitiveValue); 161 162#define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \ 163if (isInherit) { \ 164 AnimationList* list = m_style->accessAnimations(); \ 165 const AnimationList* parentList = m_parentStyle->animations(); \ 166 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \ 167 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \ 168 if (list->size() <= i) \ 169 list->append(Animation::create()); \ 170 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \ 171 } \ 172 \ 173 /* Reset any remaining animations to not have the property set. */ \ 174 for ( ; i < list->size(); ++i) \ 175 list->animation(i)->clear##Prop(); \ 176} else if (isInitial) { \ 177 AnimationList* list = m_style->accessAnimations(); \ 178 if (list->isEmpty()) \ 179 list->append(Animation::create()); \ 180 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \ 181 for (size_t i = 1; i < list->size(); ++i) \ 182 list->animation(0)->clear##Prop(); \ 183} 184 185#define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \ 186HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \ 187if (isInherit || isInitial) \ 188 return; \ 189AnimationList* list = m_style->accessAnimations(); \ 190size_t childIndex = 0; \ 191if (value->isValueList()) { \ 192 /* Walk each value and put it into an animation, creating new animations as needed. */ \ 193 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ 194 for (unsigned int i = 0; i < valueList->length(); i++) { \ 195 if (childIndex <= list->size()) \ 196 list->append(Animation::create()); \ 197 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \ 198 ++childIndex; \ 199 } \ 200} else { \ 201 if (list->isEmpty()) \ 202 list->append(Animation::create()); \ 203 mapAnimation##Prop(list->animation(childIndex), value); \ 204 childIndex = 1; \ 205} \ 206for ( ; childIndex < list->size(); ++childIndex) { \ 207 /* Reset all remaining animations to not have the property set. */ \ 208 list->animation(childIndex)->clear##Prop(); \ 209} \ 210} 211 212#define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ 213if (isInherit) { \ 214 AnimationList* list = m_style->accessTransitions(); \ 215 const AnimationList* parentList = m_parentStyle->transitions(); \ 216 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \ 217 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \ 218 if (list->size() <= i) \ 219 list->append(Animation::create()); \ 220 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \ 221 } \ 222 \ 223 /* Reset any remaining transitions to not have the property set. */ \ 224 for ( ; i < list->size(); ++i) \ 225 list->animation(i)->clear##Prop(); \ 226} else if (isInitial) { \ 227 AnimationList* list = m_style->accessTransitions(); \ 228 if (list->isEmpty()) \ 229 list->append(Animation::create()); \ 230 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \ 231 for (size_t i = 1; i < list->size(); ++i) \ 232 list->animation(0)->clear##Prop(); \ 233} 234 235#define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \ 236HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ 237if (isInherit || isInitial) \ 238 return; \ 239AnimationList* list = m_style->accessTransitions(); \ 240size_t childIndex = 0; \ 241if (value->isValueList()) { \ 242 /* Walk each value and put it into a transition, creating new animations as needed. */ \ 243 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ 244 for (unsigned int i = 0; i < valueList->length(); i++) { \ 245 if (childIndex <= list->size()) \ 246 list->append(Animation::create()); \ 247 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \ 248 ++childIndex; \ 249 } \ 250} else { \ 251 if (list->isEmpty()) \ 252 list->append(Animation::create()); \ 253 mapAnimation##Prop(list->animation(childIndex), value); \ 254 childIndex = 1; \ 255} \ 256for ( ; childIndex < list->size(); ++childIndex) { \ 257 /* Reset all remaining transitions to not have the property set. */ \ 258 list->animation(childIndex)->clear##Prop(); \ 259} \ 260} 261 262#define HANDLE_INHERIT_COND(propID, prop, Prop) \ 263if (id == propID) { \ 264 m_style->set##Prop(m_parentStyle->prop()); \ 265 return; \ 266} 267 268#define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \ 269if (id == propID) { \ 270 if (m_parentStyle->prop().isValid()) \ 271 m_style->set##Prop(m_parentStyle->prop()); \ 272 else \ 273 m_style->set##Prop(m_parentStyle->propAlt()); \ 274 return; \ 275} 276 277#define HANDLE_INITIAL_COND(propID, Prop) \ 278if (id == propID) { \ 279 m_style->set##Prop(RenderStyle::initial##Prop()); \ 280 return; \ 281} 282 283#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ 284if (id == propID) { \ 285 m_style->set##Prop(RenderStyle::initial##Value()); \ 286 return; \ 287} 288 289class RuleData { 290public: 291 RuleData(CSSStyleRule*, CSSSelector*, unsigned position); 292 293 unsigned position() const { return m_position; } 294 CSSStyleRule* rule() const { return m_rule; } 295 CSSSelector* selector() const { return m_selector; } 296 297 bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; } 298 bool hasMultipartSelector() const { return m_hasMultipartSelector; } 299 bool hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; } 300 unsigned specificity() const { return m_specificity; } 301 302 // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance. 303 static const unsigned maximumIdentifierCount = 4; 304 const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; } 305 306private: 307 void collectDescendantSelectorIdentifierHashes(); 308 void collectIdentifierHashes(const CSSSelector*, unsigned& identifierCount); 309 310 CSSStyleRule* m_rule; 311 CSSSelector* m_selector; 312 unsigned m_specificity; 313 unsigned m_position : 29; 314 bool m_hasFastCheckableSelector : 1; 315 bool m_hasMultipartSelector : 1; 316 bool m_hasTopSelectorMatchingHTMLBasedOnRuleHash : 1; 317 // Use plain array instead of a Vector to minimize memory overhead. 318 unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount]; 319}; 320 321class RuleSet { 322 WTF_MAKE_NONCOPYABLE(RuleSet); 323public: 324 RuleSet(); 325 ~RuleSet(); 326 327 typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap; 328 329 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0); 330 331 void addStyleRule(CSSStyleRule* item); 332 void addRule(CSSStyleRule* rule, CSSSelector* sel); 333 void addPageRule(CSSStyleRule* rule, CSSSelector* sel); 334 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, 335 CSSStyleRule* rule, CSSSelector* sel); 336 void shrinkToFit(); 337 void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; } 338 339 void collectFeatures(CSSStyleSelector::Features&) const; 340 341 const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); } 342 const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); } 343 const Vector<RuleData>* getTagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); } 344 const Vector<RuleData>* getPseudoRules(AtomicStringImpl* key) const { return m_pseudoRules.get(key); } 345 const Vector<RuleData>* getUniversalRules() const { return &m_universalRules; } 346 const Vector<RuleData>* getPageRules() const { return &m_pageRules; } 347 348public: 349 AtomRuleMap m_idRules; 350 AtomRuleMap m_classRules; 351 AtomRuleMap m_tagRules; 352 AtomRuleMap m_pseudoRules; 353 Vector<RuleData> m_universalRules; 354 Vector<RuleData> m_pageRules; 355 unsigned m_ruleCount; 356 bool m_autoShrinkToFitEnabled; 357}; 358 359static RuleSet* defaultStyle; 360static RuleSet* defaultQuirksStyle; 361static RuleSet* defaultPrintStyle; 362static RuleSet* defaultViewSourceStyle; 363static CSSStyleSheet* simpleDefaultStyleSheet; 364 365static RuleSet* siblingRulesInDefaultStyle; 366 367RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; 368 369static void loadFullDefaultStyle(); 370static void loadSimpleDefaultStyle(); 371// FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet. 372static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"; 373 374static inline bool elementCanUseSimpleDefaultStyle(Element* e) 375{ 376 return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag); 377} 378 379static inline void collectSiblingRulesInDefaultStyle() 380{ 381 CSSStyleSelector::Features features; 382 defaultStyle->collectFeatures(features); 383 ASSERT(features.idsInRules.isEmpty()); 384 delete siblingRulesInDefaultStyle; 385 siblingRulesInDefaultStyle = features.siblingRules.leakPtr(); 386} 387 388static inline void assertNoSiblingRulesInDefaultStyle() 389{ 390#ifndef NDEBUG 391 if (siblingRulesInDefaultStyle) 392 return; 393 collectSiblingRulesInDefaultStyle(); 394 ASSERT(!siblingRulesInDefaultStyle); 395#endif 396} 397 398static const MediaQueryEvaluator& screenEval() 399{ 400 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen")); 401 return staticScreenEval; 402} 403 404static const MediaQueryEvaluator& printEval() 405{ 406 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print")); 407 return staticPrintEval; 408} 409 410static CSSMutableStyleDeclaration* leftToRightDeclaration() 411{ 412 DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create())); 413 if (!leftToRightDecl->length()) { 414 leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false); 415 leftToRightDecl->setStrictParsing(false); 416 } 417 return leftToRightDecl.get(); 418} 419 420static CSSMutableStyleDeclaration* rightToLeftDeclaration() 421{ 422 DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create())); 423 if (!rightToLeftDecl->length()) { 424 rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false); 425 rightToLeftDecl->setStrictParsing(false); 426 } 427 return rightToLeftDecl.get(); 428} 429 430CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, 431 CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, 432 bool strictParsing, bool matchAuthorAndUserStyles) 433 : m_backgroundData(BackgroundFillLayer) 434 , m_checker(document, strictParsing) 435 , m_element(0) 436 , m_styledElement(0) 437 , m_elementLinkState(NotInsideLink) 438 , m_fontSelector(CSSFontSelector::create(document)) 439 , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty()) 440{ 441 m_matchAuthorAndUserStyles = matchAuthorAndUserStyles; 442 443 Element* root = document->documentElement(); 444 445 if (!defaultStyle) { 446 if (!root || elementCanUseSimpleDefaultStyle(root)) 447 loadSimpleDefaultStyle(); 448 else { 449 loadFullDefaultStyle(); 450 } 451 } 452 453 // construct document root element default style. this is needed 454 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" 455 // This is here instead of constructor, because when constructor is run, 456 // document doesn't have documentElement 457 // NOTE: this assumes that element that gets passed to styleForElement -call 458 // is always from the document that owns the style selector 459 FrameView* view = document->view(); 460 if (view) 461 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType())); 462 else 463 m_medium = adoptPtr(new MediaQueryEvaluator("all")); 464 465 if (root) 466 m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap 467 468 if (m_rootDefaultStyle && view) 469 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get())); 470 471 m_authorStyle = adoptPtr(new RuleSet); 472 // Adding rules from multiple sheets, shrink at the end. 473 m_authorStyle->disableAutoShrinkToFit(); 474 475 // FIXME: This sucks! The user sheet is reparsed every time! 476 OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet); 477 if (pageUserSheet) 478 tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this); 479 if (pageGroupUserSheets) { 480 unsigned length = pageGroupUserSheets->size(); 481 for (unsigned i = 0; i < length; i++) { 482 if (pageGroupUserSheets->at(i)->isUserStyleSheet()) 483 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this); 484 else 485 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this); 486 } 487 } 488 489 if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0) 490 m_userStyle = tempUserStyle.release(); 491 492 // Add rules from elements like SVG's <font-face> 493 if (mappedElementSheet) 494 m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this); 495 496 // add stylesheets from document 497 unsigned length = styleSheets->length(); 498 for (unsigned i = 0; i < length; i++) { 499 StyleSheet* sheet = styleSheets->item(i); 500 if (sheet->isCSSStyleSheet() && !sheet->disabled()) 501 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this); 502 } 503 // Collect all ids and rules using sibling selectors (:first-child and similar) 504 // in the current set of stylesheets. Style sharing code uses this information to reject 505 // sharing candidates. 506 // Usually there are no sibling rules in the default style but the MathML sheet has some. 507 if (siblingRulesInDefaultStyle) 508 siblingRulesInDefaultStyle->collectFeatures(m_features); 509 m_authorStyle->collectFeatures(m_features); 510 if (m_userStyle) 511 m_userStyle->collectFeatures(m_features); 512 513 m_authorStyle->shrinkToFit(); 514 if (m_features.siblingRules) 515 m_features.siblingRules->shrinkToFit(); 516 517 if (document->renderer() && document->renderer()->style()) 518 document->renderer()->style()->font().update(fontSelector()); 519} 520 521// This is a simplified style setting function for keyframe styles 522void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule) 523{ 524 AtomicString s(rule->name()); 525 m_keyframesRuleMap.add(s.impl(), rule); 526} 527 528CSSStyleSelector::~CSSStyleSelector() 529{ 530 m_fontSelector->clearDocument(); 531 deleteAllValues(m_viewportDependentMediaQueryResults); 532} 533 534CSSStyleSelector::Features::Features() 535 : usesFirstLineRules(false) 536 , usesBeforeAfterRules(false) 537 , usesLinkRules(false) 538{ 539} 540 541CSSStyleSelector::Features::~Features() 542{ 543} 544 545static CSSStyleSheet* parseUASheet(const String& str) 546{ 547 CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose 548 sheet->parseString(str); 549 return sheet; 550} 551 552static CSSStyleSheet* parseUASheet(const char* characters, unsigned size) 553{ 554 return parseUASheet(String(characters, size)); 555} 556 557static void loadFullDefaultStyle() 558{ 559 if (simpleDefaultStyleSheet) { 560 ASSERT(defaultStyle); 561 delete defaultStyle; 562 simpleDefaultStyleSheet->deref(); 563 defaultStyle = new RuleSet; 564 simpleDefaultStyleSheet = 0; 565 } else { 566 ASSERT(!defaultStyle); 567 defaultStyle = new RuleSet; 568 defaultPrintStyle = new RuleSet; 569 defaultQuirksStyle = new RuleSet; 570 } 571 572 // Strict-mode rules. 573 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet(); 574 CSSStyleSheet* defaultSheet = parseUASheet(defaultRules); 575 defaultStyle->addRulesFromSheet(defaultSheet, screenEval()); 576 defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval()); 577 578 // Quirks-mode rules. 579 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet(); 580 CSSStyleSheet* quirksSheet = parseUASheet(quirksRules); 581 defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval()); 582} 583 584static void loadSimpleDefaultStyle() 585{ 586 ASSERT(!defaultStyle); 587 ASSERT(!simpleDefaultStyleSheet); 588 589 defaultStyle = new RuleSet; 590 defaultPrintStyle = new RuleSet; 591 defaultQuirksStyle = new RuleSet; 592 593 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet)); 594 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval()); 595 596 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style. 597} 598 599static void loadViewSourceStyle() 600{ 601 ASSERT(!defaultViewSourceStyle); 602 defaultViewSourceStyle = new RuleSet; 603 defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval()); 604} 605 606static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes) 607{ 608 identifierHashes.append(element->localName().impl()->existingHash()); 609 if (element->hasID()) 610 identifierHashes.append(element->idForStyleResolution().impl()->existingHash()); 611 const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0; 612 if (styledElement && styledElement->hasClass()) { 613 const SpaceSplitString& classNames = styledElement->classNames(); 614 size_t count = classNames.size(); 615 for (size_t i = 0; i < count; ++i) 616 identifierHashes.append(classNames[i].impl()->existingHash()); 617 } 618} 619 620void CSSStyleSelector::pushParentStackFrame(Element* parent) 621{ 622 ASSERT(m_ancestorIdentifierFilter); 623 ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentElement()); 624 ASSERT(!m_parentStack.isEmpty() || !parent->parentElement()); 625 m_parentStack.append(ParentStackFrame(parent)); 626 ParentStackFrame& parentFrame = m_parentStack.last(); 627 // Mix tags, class names and ids into some sort of weird bouillabaisse. 628 // The filter is used for fast rejection of child and descendant selectors. 629 collectElementIdentifierHashes(parent, parentFrame.identifierHashes); 630 size_t count = parentFrame.identifierHashes.size(); 631 for (size_t i = 0; i < count; ++i) 632 m_ancestorIdentifierFilter->add(parentFrame.identifierHashes[i]); 633} 634 635void CSSStyleSelector::popParentStackFrame() 636{ 637 ASSERT(!m_parentStack.isEmpty()); 638 ASSERT(m_ancestorIdentifierFilter); 639 const ParentStackFrame& parentFrame = m_parentStack.last(); 640 size_t count = parentFrame.identifierHashes.size(); 641 for (size_t i = 0; i < count; ++i) 642 m_ancestorIdentifierFilter->remove(parentFrame.identifierHashes[i]); 643 m_parentStack.removeLast(); 644 if (m_parentStack.isEmpty()) { 645 ASSERT(m_ancestorIdentifierFilter->likelyEmpty()); 646 m_ancestorIdentifierFilter.clear(); 647 } 648} 649 650void CSSStyleSelector::pushParent(Element* parent) 651{ 652 if (m_parentStack.isEmpty()) { 653 ASSERT(!m_ancestorIdentifierFilter); 654 m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>); 655 // If the element is not the root itself, build the stack starting from the root. 656 if (parent->parentElement()) { 657 Vector<Element*, 30> ancestors; 658 for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentElement()) 659 ancestors.append(ancestor); 660 int count = ancestors.size(); 661 for (int n = count - 1; n >= 0; --n) 662 pushParentStackFrame(ancestors[n]); 663 return; 664 } 665 } else if (!parent->parentElement()) { 666 // We are not always invoked consistently. For example, script execution can cause us to enter 667 // style recalc in the middle of tree building. Reset the stack if we see a new root element. 668 ASSERT(m_ancestorIdentifierFilter); 669 m_ancestorIdentifierFilter->clear(); 670 m_parentStack.resize(0); 671 } else { 672 ASSERT(m_ancestorIdentifierFilter); 673 // We may get invoked for some random elements in some wacky cases during style resolve. 674 // Pause maintaining the stack in this case. 675 if (m_parentStack.last().element != parent->parentElement()) 676 return; 677 } 678 pushParentStackFrame(parent); 679} 680 681void CSSStyleSelector::popParent(Element* parent) 682{ 683 if (m_parentStack.isEmpty() || m_parentStack.last().element != parent) 684 return; 685 popParentStackFrame(); 686} 687 688void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl) 689{ 690 m_matchedDecls.append(decl); 691} 692 693void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) 694{ 695 m_matchedRules.clear(); 696 697 if (!rules || !m_element) 698 return; 699 700 // We need to collect the rules for id, class, tag, and everything else into a buffer and 701 // then sort the buffer. 702 if (m_element->hasID()) 703 matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); 704 if (m_element->hasClass()) { 705 ASSERT(m_styledElement); 706 const SpaceSplitString& classNames = m_styledElement->classNames(); 707 size_t size = classNames.size(); 708 for (size_t i = 0; i < size; ++i) 709 matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); 710 } 711 if (!m_element->shadowPseudoId().isEmpty()) { 712 ASSERT(m_styledElement); 713 matchRulesForList(rules->getPseudoRules(m_element->shadowPseudoId().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); 714 } 715 matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); 716 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); 717 718 // If we didn't match any rules, we're done. 719 if (m_matchedRules.isEmpty()) 720 return; 721 722 // Sort the set of matched rules. 723 sortMatchedRules(); 724 725 // Now transfer the set of matched rules over to our list of decls. 726 if (!m_checker.m_collectRulesOnly) { 727 for (unsigned i = 0; i < m_matchedRules.size(); i++) 728 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); 729 } else { 730 for (unsigned i = 0; i < m_matchedRules.size(); i++) { 731 if (!m_ruleList) 732 m_ruleList = CSSRuleList::create(); 733 m_ruleList->append(m_matchedRules[i]->rule()); 734 } 735 } 736} 737 738inline bool CSSStyleSelector::fastRejectSelector(const RuleData& ruleData) const 739{ 740 ASSERT(m_ancestorIdentifierFilter); 741 const unsigned* descendantSelectorIdentifierHashes = ruleData.descendantSelectorIdentifierHashes(); 742 for (unsigned n = 0; n < RuleData::maximumIdentifierCount && descendantSelectorIdentifierHashes[n]; ++n) { 743 if (!m_ancestorIdentifierFilter->mayContain(descendantSelectorIdentifierHashes[n])) 744 return true; 745 } 746 return false; 747} 748 749void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) 750{ 751 if (!rules) 752 return; 753 // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve. 754 // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path. 755 bool canUseFastReject = !m_parentStack.isEmpty() && m_parentStack.last().element == m_parentNode; 756 757 unsigned size = rules->size(); 758 for (unsigned i = 0; i < size; ++i) { 759 const RuleData& ruleData = rules->at(i); 760 if (canUseFastReject && fastRejectSelector(ruleData)) 761 continue; 762 if (checkSelector(ruleData)) { 763 // If the rule has no properties to apply, then ignore it in the non-debug mode. 764 CSSStyleRule* rule = ruleData.rule(); 765 CSSMutableStyleDeclaration* decl = rule->declaration(); 766 if (!decl || (!decl->length() && !includeEmptyRules)) 767 continue; 768 if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL())) 769 continue; 770 // If we're matching normal rules, set a pseudo bit if 771 // we really just matched a pseudo-element. 772 if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) { 773 if (m_checker.m_collectRulesOnly) 774 continue; 775 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID) 776 m_style->setHasPseudoStyle(m_dynamicPseudo); 777 } else { 778 // Update our first/last rule indices in the matched rules array. 779 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size(); 780 if (firstRuleIndex == -1) 781 firstRuleIndex = lastRuleIndex; 782 783 // Add this rule to our list of matched rules. 784 addMatchedRule(&ruleData); 785 } 786 } 787 } 788} 789 790static inline bool compareRules(const RuleData* r1, const RuleData* r2) 791{ 792 unsigned specificity1 = r1->specificity(); 793 unsigned specificity2 = r2->specificity(); 794 return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2; 795} 796 797void CSSStyleSelector::sortMatchedRules() 798{ 799 std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules); 800} 801 802inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const 803{ 804 if (!element || !element->isLink()) 805 return NotInsideLink; 806 return determineLinkStateSlowCase(element); 807} 808 809inline void CSSStyleSelector::initElement(Element* e) 810{ 811 if (m_element != e) { 812 m_element = e; 813 m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0; 814 m_elementLinkState = m_checker.determineLinkState(m_element); 815 if (e && e == e->document()->documentElement()) { 816 e->document()->setDirectionSetOnDocumentElement(false); 817 e->document()->setWritingModeSetOnDocumentElement(false); 818 } 819 } 820} 821 822inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) 823{ 824 m_checker.m_pseudoStyle = pseudoID; 825 826 m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0; 827 828 if (parentStyle) 829 m_parentStyle = parentStyle; 830 else 831 m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0; 832 833 Node* docElement = e ? e->document()->documentElement() : 0; 834 RenderStyle* docStyle = m_checker.m_document->renderStyle(); 835 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle; 836 837 m_style = 0; 838 839 m_matchedDecls.clear(); 840 841 m_pendingImageProperties.clear(); 842 843 m_ruleList = 0; 844 845 m_fontDirty = false; 846} 847 848static inline const AtomicString* linkAttribute(Node* node) 849{ 850 if (!node->isLink()) 851 return 0; 852 853 ASSERT(node->isElementNode()); 854 Element* element = static_cast<Element*>(node); 855 if (element->isHTMLElement()) 856 return &element->fastGetAttribute(hrefAttr); 857 858#if ENABLE(WML) 859 if (element->isWMLElement()) { 860 // <anchor> elements don't have href attributes, but we still want to 861 // appear as link, so linkAttribute() has to return a non-null value! 862 if (element->hasTagName(WMLNames::anchorTag)) 863 return &emptyAtom; 864 865 return &element->fastGetAttribute(hrefAttr); 866 } 867#endif 868 869#if ENABLE(SVG) 870 if (element->isSVGElement()) 871 return &element->fastGetAttribute(XLinkNames::hrefAttr); 872#endif 873 874 return 0; 875} 876 877CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing) 878 : m_document(document) 879 , m_strictParsing(strictParsing) 880 , m_collectRulesOnly(false) 881 , m_sameOriginOnly(false) 882 , m_pseudoStyle(NOPSEUDO) 883 , m_documentIsHTML(document->isHTMLDocument()) 884 , m_matchVisitedPseudoClass(false) 885{ 886} 887 888EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const 889{ 890 ASSERT(element->isLink()); 891 892 const AtomicString* attr = linkAttribute(element); 893 if (!attr || attr->isNull()) 894 return NotInsideLink; 895 896#if PLATFORM(QT) 897 Vector<UChar, 512> url; 898 visitedURL(m_document->baseURL(), *attr, url); 899 if (url.isEmpty()) 900 return InsideUnvisitedLink; 901 902 // If the Qt4.4 interface for the history is used, we will have to fallback 903 // to the old global history. 904 QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface(); 905 if (iface) 906 return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink; 907 908 LinkHash hash = visitedLinkHash(url.data(), url.size()); 909 if (!hash) 910 return InsideUnvisitedLink; 911#else 912 LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr); 913 if (!hash) 914 return InsideUnvisitedLink; 915#endif 916 917 Frame* frame = m_document->frame(); 918 if (!frame) 919 return InsideUnvisitedLink; 920 921 Page* page = frame->page(); 922 if (!page) 923 return InsideUnvisitedLink; 924 925 m_linksCheckedForVisitedState.add(hash); 926 927#if USE(PLATFORM_STRATEGIES) 928 return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink; 929#else 930 return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink; 931#endif 932} 933 934bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const 935{ 936 PseudoId dynamicPseudo = NOPSEUDO; 937 return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches; 938} 939 940static const unsigned cStyleSearchThreshold = 10; 941static const unsigned cStyleSearchLevelThreshold = 10; 942 943Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const 944{ 945 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold) 946 return 0; 947 if (!parent || !parent->isStyledElement()) 948 return 0; 949 StyledElement* p = static_cast<StyledElement*>(parent); 950 if (p->inlineStyleDecl()) 951 return 0; 952 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl())) 953 return 0; 954 955 RenderStyle* parentStyle = p->renderStyle(); 956 unsigned subcount = 0; 957 Node* thisCousin = p; 958 Node* currentNode = p->previousSibling(); 959 960 // Reserve the tries for this level. This effectively makes sure that the algorithm 961 // will never go deeper than cStyleSearchLevelThreshold levels into recursion. 962 visitedNodeCount += cStyleSearchThreshold; 963 while (thisCousin) { 964 while (currentNode) { 965 ++subcount; 966 if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) { 967 // Adjust for unused reserved tries. 968 visitedNodeCount -= cStyleSearchThreshold - subcount; 969 return currentNode->lastChild(); 970 } 971 if (subcount >= cStyleSearchThreshold) 972 return 0; 973 currentNode = currentNode->previousSibling(); 974 } 975 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount); 976 thisCousin = currentNode; 977 } 978 979 return 0; 980} 981 982bool CSSStyleSelector::matchesSiblingRules() 983{ 984 int firstSiblingRule = -1, lastSiblingRule = -1; 985 matchRules(m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false); 986 if (m_matchedDecls.isEmpty()) 987 return false; 988 m_matchedDecls.clear(); 989 return true; 990} 991 992bool CSSStyleSelector::canShareStyleWithElement(Node* node) const 993{ 994 if (!node->isStyledElement()) 995 return false; 996 997 StyledElement* element = static_cast<StyledElement*>(node); 998 RenderStyle* style = element->renderStyle(); 999 1000 if (!style) 1001 return false; 1002 if (style->unique()) 1003 return false; 1004 if (element->tagQName() != m_element->tagQName()) 1005 return false; 1006 if (element->hasClass() != m_element->hasClass()) 1007 return false; 1008 if (element->inlineStyleDecl()) 1009 return false; 1010 if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes()) 1011 return false; 1012 if (element->isLink() != m_element->isLink()) 1013 return false; 1014 if (style->affectedByAttributeSelectors()) 1015 return false; 1016 if (element->hovered() != m_element->hovered()) 1017 return false; 1018 if (element->active() != m_element->active()) 1019 return false; 1020 if (element->focused() != m_element->focused()) 1021 return false; 1022 if (element->shadowPseudoId() != m_element->shadowPseudoId()) 1023 return false; 1024 if (element == element->document()->cssTarget()) 1025 return false; 1026 if (m_element == m_element->document()->cssTarget()) 1027 return false; 1028 if (element->fastGetAttribute(typeAttr) != m_element->fastGetAttribute(typeAttr)) 1029 return false; 1030 if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr)) 1031 return false; 1032 if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr)) 1033 return false; 1034 if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr)) 1035 return false; 1036 if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr)) 1037 return false; 1038 1039 if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl())) 1040 return false; 1041 1042 bool isControl = element->isFormControlElement(); 1043 1044 if (isControl != m_element->isFormControlElement()) 1045 return false; 1046 1047 if (isControl) { 1048 InputElement* thisInputElement = element->toInputElement(); 1049 InputElement* otherInputElement = m_element->toInputElement(); 1050 1051 if (!thisInputElement || !otherInputElement) 1052 return false; 1053 1054 if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) 1055 return false; 1056 if (thisInputElement->isChecked() != otherInputElement->isChecked()) 1057 return false; 1058 if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate()) 1059 return false; 1060 1061 if (element->isEnabledFormControl() != m_element->isEnabledFormControl()) 1062 return false; 1063 1064 if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm()) 1065 return false; 1066 1067 if (!m_element->document()->containsValidityStyleRules()) 1068 return false; 1069 1070 bool willValidate = element->willValidate(); 1071 1072 if (willValidate != m_element->willValidate()) 1073 return false; 1074 1075 if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement())) 1076 return false; 1077 1078 if (element->isInRange() != m_element->isInRange()) 1079 return false; 1080 1081 if (element->isOutOfRange() != m_element->isOutOfRange()) 1082 return false; 1083 } 1084 1085 if (style->transitions() || style->animations()) 1086 return false; 1087 1088#if USE(ACCELERATED_COMPOSITING) 1089 // Turn off style sharing for elements that can gain layers for reasons outside of the style system. 1090 // See comments in RenderObject::setStyle(). 1091 if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) 1092 return false; 1093#endif 1094 1095 if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto")) 1096 return false; 1097 1098 if (element->hasClass() && m_element->fastGetAttribute(classAttr) != element->fastGetAttribute(classAttr)) 1099 return false; 1100 1101 if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap())) 1102 return false; 1103 1104 if (element->isLink() && m_elementLinkState != style->insideLink()) 1105 return false; 1106 1107 return true; 1108} 1109 1110inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const 1111{ 1112 for (; node; node = node->previousSibling()) { 1113 if (!node->isElementNode()) 1114 continue; 1115 if (canShareStyleWithElement(node)) 1116 break; 1117 if (count++ == cStyleSearchThreshold) 1118 return 0; 1119 } 1120 return node; 1121} 1122 1123static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle) 1124{ 1125 return parentStyle->childrenAffectedByPositionalRules() 1126 || parentStyle->childrenAffectedByFirstChildRules() 1127 || parentStyle->childrenAffectedByLastChildRules() 1128 || parentStyle->childrenAffectedByDirectAdjacentRules(); 1129} 1130 1131ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() 1132{ 1133 if (!m_styledElement || !m_parentStyle) 1134 return 0; 1135 // If the element has inline style it is probably unique. 1136 if (m_styledElement->inlineStyleDecl()) 1137 return 0; 1138 // Ids stop style sharing if they show up in the stylesheets. 1139 if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl())) 1140 return 0; 1141 if (parentStylePreventsSharing(m_parentStyle)) 1142 return 0; 1143 1144 // Check previous siblings and their cousins. 1145 unsigned count = 0; 1146 unsigned visitedNodeCount = 0; 1147 Node* shareNode = 0; 1148 Node* cousinList = m_styledElement->previousSibling(); 1149 while (cousinList) { 1150 shareNode = findSiblingForStyleSharing(cousinList, count); 1151 if (shareNode) 1152 break; 1153 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount); 1154 } 1155 1156 // If we have exhausted all our budget or our cousins. 1157 if (!shareNode) 1158 return 0; 1159 1160 // Can't share if sibling rules apply. This is checked at the end as it should rarely fail. 1161 if (matchesSiblingRules()) 1162 return 0; 1163 // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. 1164 if (parentStylePreventsSharing(m_parentStyle)) 1165 return 0; 1166 return shareNode->renderStyle(); 1167} 1168 1169void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule) 1170{ 1171 // First we match rules from the user agent sheet. 1172 RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") 1173 ? defaultPrintStyle : defaultStyle; 1174 matchRules(userAgentStyleSheet, firstUARule, lastUARule, false); 1175 1176 // In quirks mode, we match rules from the quirks user agent sheet. 1177 if (!m_checker.m_strictParsing) 1178 matchRules(defaultQuirksStyle, firstUARule, lastUARule, false); 1179 1180 // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet. 1181 if (m_checker.m_document->usesViewSourceStyles()) { 1182 if (!defaultViewSourceStyle) 1183 loadViewSourceStyle(); 1184 matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false); 1185 } 1186} 1187 1188PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) 1189{ 1190 Frame* frame = document->frame(); 1191 1192 RefPtr<RenderStyle> documentStyle = RenderStyle::create(); 1193 documentStyle->setDisplay(BLOCK); 1194 documentStyle->setVisuallyOrdered(document->visuallyOrdered()); 1195 documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1); 1196 documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1); 1197 documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY); 1198 1199 Element* docElement = document->documentElement(); 1200 RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0; 1201 if (docElementRenderer) { 1202 // Use the direction and writing-mode of the body to set the 1203 // viewport's direction and writing-mode unless the property is set on the document element. 1204 // If there is no body, then use the document element. 1205 RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0; 1206 if (bodyRenderer && !document->writingModeSetOnDocumentElement()) 1207 documentStyle->setWritingMode(bodyRenderer->style()->writingMode()); 1208 else 1209 documentStyle->setWritingMode(docElementRenderer->style()->writingMode()); 1210 if (bodyRenderer && !document->directionSetOnDocumentElement()) 1211 documentStyle->setDirection(bodyRenderer->style()->direction()); 1212 else 1213 documentStyle->setDirection(docElementRenderer->style()->direction()); 1214 } 1215 1216 FontDescription fontDescription; 1217 fontDescription.setUsePrinterFont(document->printing()); 1218 if (Settings* settings = document->settings()) { 1219 fontDescription.setRenderingMode(settings->fontRenderingMode()); 1220 if (document->printing() && !settings->shouldPrintBackgrounds()) 1221 documentStyle->setForceBackgroundsToWhite(true); 1222 const AtomicString& stdfont = settings->standardFontFamily(); 1223 if (!stdfont.isEmpty()) { 1224 fontDescription.firstFamily().setFamily(stdfont); 1225 fontDescription.firstFamily().appendFamily(0); 1226 } 1227 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); 1228 int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false); 1229 fontDescription.setSpecifiedSize(size); 1230 bool useSVGZoomRules = document->isSVGDocument(); 1231 fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); 1232 } 1233 1234 documentStyle->setFontDescription(fontDescription); 1235 documentStyle->font().update(0); 1236 1237 return documentStyle.release(); 1238} 1239 1240static inline bool isAtShadowBoundary(Element* element) 1241{ 1242 if (!element) 1243 return false; 1244 1245 ContainerNode* parentNode = element->parentNode(); 1246 return parentNode && parentNode->isShadowBoundary(); 1247} 1248 1249// If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where 1250// relative units are interpreted according to document root element style, styled only with UA stylesheet 1251 1252PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass) 1253{ 1254 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer 1255 // will vanish if a style recalc happens during loading. 1256 if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) { 1257 if (!s_styleNotYetAvailable) { 1258 s_styleNotYetAvailable = RenderStyle::create().releaseRef(); 1259 s_styleNotYetAvailable->ref(); 1260 s_styleNotYetAvailable->setDisplay(NONE); 1261 s_styleNotYetAvailable->font().update(m_fontSelector); 1262 } 1263 s_styleNotYetAvailable->ref(); 1264 e->document()->setHasNodesWithPlaceholderStyle(); 1265 return s_styleNotYetAvailable; 1266 } 1267 1268 initElement(e); 1269 initForStyleResolve(e, defaultParent); 1270 if (allowSharing) { 1271 RenderStyle* sharedStyle = locateSharedStyle(); 1272 if (sharedStyle) 1273 return sharedStyle; 1274 } 1275 1276 // Compute our style allowing :visited to match first. 1277 RefPtr<RenderStyle> visitedStyle; 1278 if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) { 1279 // Fetch our parent style. 1280 RenderStyle* parentStyle = m_parentStyle; 1281 if (!e->isLink()) { 1282 // Use the parent's visited style if one exists. 1283 RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK); 1284 if (parentVisitedStyle) 1285 parentStyle = parentVisitedStyle; 1286 } 1287 visitedStyle = styleForElement(e, parentStyle, false, false, true); 1288 initForStyleResolve(e, defaultParent); 1289 } 1290 1291 // Don't propagate user-modify into shadow DOM 1292 if (isAtShadowBoundary(e)) 1293 m_style->setUserModify(RenderStyle::initialUserModify()); 1294 1295 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; 1296 1297 m_style = RenderStyle::create(); 1298 1299 if (m_parentStyle) 1300 m_style->inheritFrom(m_parentStyle); 1301 else 1302 m_parentStyle = style(); 1303 1304 if (e->isLink()) { 1305 m_style->setIsLink(true); 1306 m_style->setInsideLink(m_elementLinkState); 1307 } 1308 1309 if (visitedStyle) { 1310 // Copy any pseudo bits that the visited style has to the primary style so that 1311 // pseudo element styles will continue to work for pseudo elements inside :visited 1312 // links. 1313 for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) { 1314 if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo))) 1315 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo)); 1316 } 1317 if (m_elementLinkState == InsideUnvisitedLink) 1318 visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it. 1319 else 1320 visitedStyle->setStyleType(VISITED_LINK); 1321 } 1322 1323 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) { 1324 loadFullDefaultStyle(); 1325 assertNoSiblingRulesInDefaultStyle(); 1326 } 1327 1328#if ENABLE(SVG) 1329 static bool loadedSVGUserAgentSheet; 1330 if (e->isSVGElement() && !loadedSVGUserAgentSheet) { 1331 // SVG rules. 1332 loadedSVGUserAgentSheet = true; 1333 CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); 1334 defaultStyle->addRulesFromSheet(svgSheet, screenEval()); 1335 defaultPrintStyle->addRulesFromSheet(svgSheet, printEval()); 1336 assertNoSiblingRulesInDefaultStyle(); 1337 } 1338#endif 1339 1340#if ENABLE(MATHML) 1341 static bool loadedMathMLUserAgentSheet; 1342 if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) { 1343 // MathML rules. 1344 loadedMathMLUserAgentSheet = true; 1345 CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet)); 1346 defaultStyle->addRulesFromSheet(mathMLSheet, screenEval()); 1347 defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval()); 1348 // There are some sibling rules here. 1349 collectSiblingRulesInDefaultStyle(); 1350 } 1351#endif 1352 1353#if ENABLE(WML) 1354 static bool loadedWMLUserAgentSheet; 1355 if (e->isWMLElement() && !loadedWMLUserAgentSheet) { 1356 // WML rules. 1357 loadedWMLUserAgentSheet = true; 1358 CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet)); 1359 defaultStyle->addRulesFromSheet(wmlSheet, screenEval()); 1360 defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval()); 1361 assertNoSiblingRulesInDefaultStyle(); 1362 } 1363#endif 1364 1365#if ENABLE(VIDEO) 1366 static bool loadedMediaStyleSheet; 1367 if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) { 1368 loadedMediaStyleSheet = true; 1369 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(e->document()->page())->extraMediaControlsStyleSheet(); 1370 CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules); 1371 defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval()); 1372 defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval()); 1373 assertNoSiblingRulesInDefaultStyle(); 1374 } 1375#endif 1376 1377#if ENABLE(FULLSCREEN_API) 1378 static bool loadedFullScreenStyleSheet; 1379 if (!loadedFullScreenStyleSheet && e->document()->webkitIsFullScreen()) { 1380 loadedFullScreenStyleSheet = true; 1381 String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet(); 1382 CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules); 1383 defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval()); 1384 defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval()); 1385 } 1386#endif 1387 1388 int firstUARule = -1, lastUARule = -1; 1389 int firstUserRule = -1, lastUserRule = -1; 1390 int firstAuthorRule = -1, lastAuthorRule = -1; 1391 matchUARules(firstUARule, lastUARule); 1392 1393 if (!resolveForRootDefault) { 1394 // 4. Now we check user sheet rules. 1395 if (m_matchAuthorAndUserStyles) 1396 matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false); 1397 1398 // 5. Now check author rules, beginning first with presentational attributes 1399 // mapped from HTML. 1400 if (m_styledElement) { 1401 // Ask if the HTML element has mapped attributes. 1402 if (m_styledElement->hasMappedAttributes()) { 1403 // Walk our attribute list and add in each decl. 1404 const NamedNodeMap* map = m_styledElement->attributeMap(); 1405 for (unsigned i = 0; i < map->length(); i++) { 1406 Attribute* attr = map->attributeItem(i); 1407 if (attr->isMappedAttribute() && attr->decl()) { 1408 lastAuthorRule = m_matchedDecls.size(); 1409 if (firstAuthorRule == -1) 1410 firstAuthorRule = lastAuthorRule; 1411 addMatchedDeclaration(attr->decl()); 1412 } 1413 } 1414 } 1415 1416 // Now we check additional mapped declarations. 1417 // Tables and table cells share an additional mapped rule that must be applied 1418 // after all attributes, since their mapped style depends on the values of multiple attributes. 1419 if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) { 1420 m_additionalAttributeStyleDecls.clear(); 1421 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls); 1422 if (!m_additionalAttributeStyleDecls.isEmpty()) { 1423 unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size(); 1424 if (firstAuthorRule == -1) 1425 firstAuthorRule = m_matchedDecls.size(); 1426 lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1; 1427 for (unsigned i = 0; i < additionalDeclsSize; i++) 1428 addMatchedDeclaration(m_additionalAttributeStyleDecls[i]); 1429 } 1430 } 1431 if (m_styledElement->isHTMLElement()) { 1432 bool isAuto; 1433 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto); 1434 if (isAuto) 1435 addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration()); 1436 } 1437 } 1438 1439 // 6. Check the rules in author sheets next. 1440 if (m_matchAuthorAndUserStyles) 1441 matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false); 1442 1443 // 7. Now check our inline style attribute. 1444 if (m_matchAuthorAndUserStyles && m_styledElement) { 1445 CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl(); 1446 if (inlineDecl) { 1447 lastAuthorRule = m_matchedDecls.size(); 1448 if (firstAuthorRule == -1) 1449 firstAuthorRule = lastAuthorRule; 1450 addMatchedDeclaration(inlineDecl); 1451 } 1452 } 1453 } 1454 1455 // Reset the value back before applying properties, so that -webkit-link knows what color to use. 1456 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; 1457 1458 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply 1459 // high-priority properties first, i.e., those properties that other properties depend on. 1460 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important 1461 // and (4) normal important. 1462 m_lineHeightValue = 0; 1463 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); 1464 if (!resolveForRootDefault) { 1465 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule); 1466 applyDeclarations<true>(true, firstUserRule, lastUserRule); 1467 } 1468 applyDeclarations<true>(true, firstUARule, lastUARule); 1469 1470 // If our font got dirtied, go ahead and update it now. 1471 if (m_fontDirty) 1472 updateFont(); 1473 1474 // Line-height is set when we are sure we decided on the font-size 1475 if (m_lineHeightValue) 1476 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); 1477 1478 // Now do the normal priority UA properties. 1479 applyDeclarations<false>(false, firstUARule, lastUARule); 1480 1481 // Cache our border and background so that we can examine them later. 1482 cacheBorderAndBackground(); 1483 1484 // Now do the author and user normal priority properties and all the !important properties. 1485 if (!resolveForRootDefault) { 1486 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1); 1487 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule); 1488 applyDeclarations<false>(true, firstUserRule, lastUserRule); 1489 } 1490 applyDeclarations<false>(true, firstUARule, lastUARule); 1491 1492 ASSERT(!m_fontDirty); 1493 // If our font got dirtied by one of the non-essential font props, 1494 // go ahead and update it a second time. 1495 if (m_fontDirty) 1496 updateFont(); 1497 1498 // Clean up our style object's display and text decorations (among other fixups). 1499 adjustRenderStyle(style(), m_parentStyle, e); 1500 1501 // Start loading images referenced by this style. 1502 loadPendingImages(); 1503 1504 // If we have first-letter pseudo style, do not share this style 1505 if (m_style->hasPseudoStyle(FIRST_LETTER)) 1506 m_style->setUnique(); 1507 1508 if (visitedStyle) { 1509 // Add the visited style off the main style. 1510 m_style->addCachedPseudoStyle(visitedStyle.release()); 1511 } 1512 1513 if (!matchVisitedPseudoClass) 1514 initElement(0); // Clear out for the next resolve. 1515 1516 // Now return the style. 1517 return m_style.release(); 1518} 1519 1520PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe) 1521{ 1522 if (keyframeRule->style()) 1523 addMatchedDeclaration(keyframeRule->style()); 1524 1525 ASSERT(!m_style); 1526 1527 // Create the style 1528 m_style = RenderStyle::clone(elementStyle); 1529 1530 m_lineHeightValue = 0; 1531 1532 // We don't need to bother with !important. Since there is only ever one 1533 // decl, there's nothing to override. So just add the first properties. 1534 if (keyframeRule->style()) 1535 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); 1536 1537 // If our font got dirtied, go ahead and update it now. 1538 if (m_fontDirty) 1539 updateFont(); 1540 1541 // Line-height is set when we are sure we decided on the font-size 1542 if (m_lineHeightValue) 1543 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); 1544 1545 // Now do rest of the properties. 1546 if (keyframeRule->style()) 1547 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1); 1548 1549 // If our font got dirtied by one of the non-essential font props, 1550 // go ahead and update it a second time. 1551 if (m_fontDirty) 1552 updateFont(); 1553 1554 // Start loading images referenced by this style. 1555 loadPendingImages(); 1556 1557 // Add all the animating properties to the keyframe. 1558 if (keyframeRule->style()) { 1559 CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end(); 1560 for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) { 1561 int property = (*it).id(); 1562 // Timing-function within keyframes is special, because it is not animated; it just 1563 // describes the timing function between this keyframe and the next. 1564 if (property != CSSPropertyWebkitAnimationTimingFunction) 1565 keyframe.addProperty(property); 1566 } 1567 } 1568 1569 return m_style.release(); 1570} 1571 1572void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list) 1573{ 1574 list.clear(); 1575 1576 // Get the keyframesRule for this name 1577 if (!e || list.animationName().isEmpty()) 1578 return; 1579 1580 m_keyframesRuleMap.checkConsistency(); 1581 1582 if (!m_keyframesRuleMap.contains(list.animationName().impl())) 1583 return; 1584 1585 const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get(); 1586 1587 // Construct and populate the style for each keyframe 1588 for (unsigned i = 0; i < rule->length(); ++i) { 1589 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement 1590 initElement(e); 1591 initForStyleResolve(e); 1592 1593 const WebKitCSSKeyframeRule* keyframeRule = rule->item(i); 1594 1595 KeyframeValue keyframe(0, 0); 1596 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe)); 1597 1598 // Add this keyframe style to all the indicated key times 1599 Vector<float> keys; 1600 keyframeRule->getKeys(keys); 1601 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) { 1602 keyframe.setKey(keys[keyIndex]); 1603 list.insert(keyframe); 1604 } 1605 } 1606 1607 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe) 1608 int initialListSize = list.size(); 1609 if (initialListSize > 0 && list[0].key() != 0) { 1610 RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create(); 1611 keyframeRule->setKeyText("0%"); 1612 KeyframeValue keyframe(0, 0); 1613 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe)); 1614 list.insert(keyframe); 1615 } 1616 1617 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe) 1618 if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) { 1619 RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create(); 1620 keyframeRule->setKeyText("100%"); 1621 KeyframeValue keyframe(1, 0); 1622 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe)); 1623 list.insert(keyframe); 1624 } 1625} 1626 1627PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass) 1628{ 1629 if (!e) 1630 return 0; 1631 1632 initElement(e); 1633 1634 // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it 1635 // off of. 1636 RefPtr<RenderStyle> visitedStyle; 1637 if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) { 1638 // Fetch our parent style with :visited in effect. 1639 RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK); 1640 visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true); 1641 if (visitedStyle) 1642 visitedStyle->setStyleType(VISITED_LINK); 1643 } 1644 1645 initForStyleResolve(e, parentStyle, pseudo); 1646 m_style = RenderStyle::create(); 1647 if (parentStyle) 1648 m_style->inheritFrom(parentStyle); 1649 1650 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; 1651 1652 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking 1653 // those rules. 1654 1655 // Check UA, user and author rules. 1656 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1; 1657 matchUARules(firstUARule, lastUARule); 1658 1659 if (m_matchAuthorAndUserStyles) { 1660 matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false); 1661 matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false); 1662 } 1663 1664 if (m_matchedDecls.isEmpty() && !visitedStyle) 1665 return 0; 1666 1667 m_style->setStyleType(pseudo); 1668 1669 m_lineHeightValue = 0; 1670 1671 // Reset the value back before applying properties, so that -webkit-link knows what color to use. 1672 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass; 1673 1674 // High-priority properties. 1675 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); 1676 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule); 1677 applyDeclarations<true>(true, firstUserRule, lastUserRule); 1678 applyDeclarations<true>(true, firstUARule, lastUARule); 1679 1680 // If our font got dirtied, go ahead and update it now. 1681 if (m_fontDirty) 1682 updateFont(); 1683 1684 // Line-height is set when we are sure we decided on the font-size 1685 if (m_lineHeightValue) 1686 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); 1687 1688 // Now do the normal priority properties. 1689 applyDeclarations<false>(false, firstUARule, lastUARule); 1690 1691 // Cache our border and background so that we can examine them later. 1692 cacheBorderAndBackground(); 1693 1694 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1); 1695 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule); 1696 applyDeclarations<false>(true, firstUserRule, lastUserRule); 1697 applyDeclarations<false>(true, firstUARule, lastUARule); 1698 1699 // If our font got dirtied by one of the non-essential font props, 1700 // go ahead and update it a second time. 1701 if (m_fontDirty) 1702 updateFont(); 1703 1704 // Clean up our style object's display and text decorations (among other fixups). 1705 adjustRenderStyle(style(), parentStyle, 0); 1706 1707 // Start loading images referenced by this style. 1708 loadPendingImages(); 1709 1710 // Hang our visited style off m_style. 1711 if (visitedStyle) 1712 m_style->addCachedPseudoStyle(visitedStyle.release()); 1713 1714 // Now return the style. 1715 return m_style.release(); 1716} 1717 1718PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex) 1719{ 1720 initForStyleResolve(m_checker.m_document->documentElement()); // m_rootElementStyle will be set to the document style. 1721 1722 m_style = RenderStyle::create(); 1723 m_style->inheritFrom(m_rootElementStyle); 1724 1725 const bool isLeft = isLeftPage(pageIndex); 1726 const bool isFirst = isFirstPage(pageIndex); 1727 const String page = pageName(pageIndex); 1728 matchPageRules(defaultPrintStyle, isLeft, isFirst, page); 1729 matchPageRules(m_userStyle.get(), isLeft, isFirst, page); 1730 matchPageRules(m_authorStyle.get(), isLeft, isFirst, page); 1731 m_lineHeightValue = 0; 1732 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); 1733 1734 // If our font got dirtied, go ahead and update it now. 1735 if (m_fontDirty) 1736 updateFont(); 1737 1738 // Line-height is set when we are sure we decided on the font-size 1739 if (m_lineHeightValue) 1740 applyProperty(CSSPropertyLineHeight, m_lineHeightValue); 1741 1742 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1); 1743 1744 // Start loading images referenced by this style. 1745 loadPendingImages(); 1746 1747 // Now return the style. 1748 return m_style.release(); 1749} 1750 1751#if ENABLE(DATAGRID) 1752 1753PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*) 1754{ 1755 // FIXME: Implement 1756 return 0; 1757} 1758 1759PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*) 1760{ 1761 // FIXME: Implement 1762 return 0; 1763} 1764 1765#endif 1766 1767static void addIntrinsicMargins(RenderStyle* style) 1768{ 1769 // Intrinsic margin value. 1770 const int intrinsicMargin = 2 * style->effectiveZoom(); 1771 1772 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. 1773 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame. 1774 if (style->width().isIntrinsicOrAuto()) { 1775 if (style->marginLeft().quirk()) 1776 style->setMarginLeft(Length(intrinsicMargin, Fixed)); 1777 if (style->marginRight().quirk()) 1778 style->setMarginRight(Length(intrinsicMargin, Fixed)); 1779 } 1780 1781 if (style->height().isAuto()) { 1782 if (style->marginTop().quirk()) 1783 style->setMarginTop(Length(intrinsicMargin, Fixed)); 1784 if (style->marginBottom().quirk()) 1785 style->setMarginBottom(Length(intrinsicMargin, Fixed)); 1786 } 1787} 1788 1789void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e) 1790{ 1791 // Cache our original display. 1792 style->setOriginalDisplay(style->display()); 1793 1794 if (style->display() != NONE) { 1795 // If we have a <td> that specifies a float property, in quirks mode we just drop the float 1796 // property. 1797 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force 1798 // these tags to retain their display types. 1799 if (!m_checker.m_strictParsing && e) { 1800 if (e->hasTagName(tdTag)) { 1801 style->setDisplay(TABLE_CELL); 1802 style->setFloating(FNONE); 1803 } 1804 else if (e->hasTagName(tableTag)) 1805 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); 1806 } 1807 1808 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) { 1809 if (style->whiteSpace() == KHTML_NOWRAP) { 1810 // Figure out if we are really nowrapping or if we should just 1811 // use normal instead. If the width of the cell is fixed, then 1812 // we don't actually use NOWRAP. 1813 if (style->width().isFixed()) 1814 style->setWhiteSpace(NORMAL); 1815 else 1816 style->setWhiteSpace(NOWRAP); 1817 } 1818 } 1819 1820 // Tables never support the -webkit-* values for text-align and will reset back to the default. 1821 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) 1822 style->setTextAlign(TAAUTO); 1823 1824 // Frames and framesets never honor position:relative or position:absolute. This is necessary to 1825 // fix a crash where a site tries to position these objects. They also never honor display. 1826 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { 1827 style->setPosition(StaticPosition); 1828 style->setDisplay(BLOCK); 1829 } 1830 1831 // Table headers with a text-align of auto will change the text-align to center. 1832 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO) 1833 style->setTextAlign(CENTER); 1834 1835 if (e && e->hasTagName(legendTag)) 1836 style->setDisplay(BLOCK); 1837 1838 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to 1839 // position or float an inline, compact, or run-in. Cache the original display, since it 1840 // may be needed for positioned elements that have to compute their static normal flow 1841 // positions. We also force inline-level roots to be block-level. 1842 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX && 1843 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE || 1844 (e && e->document()->documentElement() == e))) { 1845 if (style->display() == INLINE_TABLE) 1846 style->setDisplay(TABLE); 1847 else if (style->display() == INLINE_BOX) 1848 style->setDisplay(BOX); 1849 else if (style->display() == LIST_ITEM) { 1850 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, 1851 // but only in quirks mode. 1852 if (!m_checker.m_strictParsing && style->floating() != FNONE) 1853 style->setDisplay(BLOCK); 1854 } 1855 else 1856 style->setDisplay(BLOCK); 1857 } 1858 1859 // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely 1860 // clear how that should work. 1861 if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode()) 1862 style->setDisplay(INLINE_BLOCK); 1863 1864 // After performing the display mutation, check table rows. We do not honor position:relative on 1865 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock() 1866 // on some sites). 1867 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP 1868 || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) && 1869 style->position() == RelativePosition) 1870 style->setPosition(StaticPosition); 1871 1872 // writing-mode does not apply to table row groups, table column groups, table rows, and table columns. 1873 // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though. 1874 if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP 1875 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP 1876 || style->display() == TABLE_CELL) 1877 style->setWritingMode(parentStyle->writingMode()); 1878 1879 // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting 1880 // of block-flow to anything other than TopToBottomWritingMode. 1881 // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support. 1882 if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX)) 1883 style->setWritingMode(TopToBottomWritingMode); 1884 } 1885 1886 // Make sure our z-index value is only applied if the object is positioned. 1887 if (style->position() == StaticPosition) 1888 style->setHasAutoZIndex(); 1889 1890 // Auto z-index becomes 0 for the root element and transparent objects. This prevents 1891 // cases where objects that should be blended as a single unit end up with a non-transparent 1892 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections. 1893 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || 1894 style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect())) 1895 style->setZIndex(0); 1896 1897#if ENABLE(WML) 1898 if (e && (e->hasTagName(WMLNames::insertedLegendTag) 1899 || e->hasTagName(WMLNames::inputTag)) 1900 && style->width().isAuto()) 1901 style->setWidth(Length(Intrinsic)); 1902#endif 1903 1904 // Textarea considers overflow visible as auto. 1905 if (e && e->hasTagName(textareaTag)) { 1906 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX()); 1907 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY()); 1908 } 1909 1910 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through 1911 // tables, inline blocks, inline tables, run-ins, or shadow DOM. 1912 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN 1913 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)) 1914 style->setTextDecorationsInEffect(style->textDecoration()); 1915 else 1916 style->addToTextDecorationsInEffect(style->textDecoration()); 1917 1918 // If either overflow value is not visible, change to auto. 1919 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) 1920 style->setOverflowY(OMARQUEE); 1921 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) 1922 style->setOverflowX(OMARQUEE); 1923 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) 1924 style->setOverflowX(OAUTO); 1925 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) 1926 style->setOverflowY(OAUTO); 1927 1928 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. 1929 // FIXME: Eventually table sections will support auto and scroll. 1930 if (style->display() == TABLE || style->display() == INLINE_TABLE || 1931 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { 1932 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) 1933 style->setOverflowX(OVISIBLE); 1934 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) 1935 style->setOverflowY(OVISIBLE); 1936 } 1937 1938 // Menulists should have visible overflow 1939 if (style->appearance() == MenulistPart) { 1940 style->setOverflowX(OVISIBLE); 1941 style->setOverflowY(OVISIBLE); 1942 } 1943 1944 // Cull out any useless layers and also repeat patterns into additional layers. 1945 style->adjustBackgroundLayers(); 1946 style->adjustMaskLayers(); 1947 1948 // Do the same for animations and transitions. 1949 style->adjustAnimations(); 1950 style->adjustTransitions(); 1951 1952 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will 1953 // alter fonts and heights/widths. 1954 if (e && e->isFormControlElement() && style->fontSize() >= 11) { 1955 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, 1956 // so we have to treat all image buttons as though they were explicitly sized. 1957 if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton()) 1958 addIntrinsicMargins(style); 1959 } 1960 1961 // Let the theme also have a crack at adjusting the style. 1962 if (style->hasAppearance()) 1963 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor); 1964 1965#if ENABLE(SVG) 1966 if (e && e->isSVGElement()) { 1967 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty 1968 if (style->overflowY() == OSCROLL) 1969 style->setOverflowY(OHIDDEN); 1970 else if (style->overflowY() == OAUTO) 1971 style->setOverflowY(OVISIBLE); 1972 1973 if (style->overflowX() == OSCROLL) 1974 style->setOverflowX(OHIDDEN); 1975 else if (style->overflowX() == OAUTO) 1976 style->setOverflowX(OVISIBLE); 1977 1978 // Only the root <svg> element in an SVG document fragment tree honors css position 1979 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) 1980 style->setPosition(RenderStyle::initialPosition()); 1981 } 1982#endif 1983} 1984 1985void CSSStyleSelector::updateFont() 1986{ 1987 checkForTextSizeAdjust(); 1988 checkForGenericFamilyChange(style(), m_parentStyle); 1989 checkForZoomChange(style(), m_parentStyle); 1990 m_style->font().update(m_fontSelector); 1991 m_fontDirty = false; 1992} 1993 1994void CSSStyleSelector::cacheBorderAndBackground() 1995{ 1996 m_hasUAAppearance = m_style->hasAppearance(); 1997 if (m_hasUAAppearance) { 1998 m_borderData = m_style->border(); 1999 m_backgroundData = *m_style->backgroundLayers(); 2000 m_backgroundColor = m_style->backgroundColor(); 2001 } 2002} 2003 2004PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter) 2005{ 2006 return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly, includeEmptyRules, filter); 2007} 2008 2009PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly, bool includeEmptyRules, CSSRuleFilter filter) 2010{ 2011 if (!e || !e->document()->haveStylesheetsLoaded()) 2012 return 0; 2013 2014 m_checker.m_collectRulesOnly = true; 2015 2016 initElement(e); 2017 initForStyleResolve(e, 0, pseudoId); 2018 2019 if (!authorOnly) { 2020 int firstUARule = -1, lastUARule = -1; 2021 // First we match rules from the user agent sheet. 2022 matchUARules(firstUARule, lastUARule); 2023 2024 // Now we check user sheet rules. 2025 if (m_matchAuthorAndUserStyles) { 2026 int firstUserRule = -1, lastUserRule = -1; 2027 matchRules(m_userStyle.get(), firstUserRule, lastUserRule, includeEmptyRules); 2028 } 2029 } 2030 2031 if (m_matchAuthorAndUserStyles) { 2032 m_checker.m_sameOriginOnly = (filter == SameOriginCSSRulesOnly); 2033 2034 // Check the rules in author sheets. 2035 int firstAuthorRule = -1, lastAuthorRule = -1; 2036 matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, includeEmptyRules); 2037 2038 m_checker.m_sameOriginOnly = false; 2039 } 2040 2041 m_checker.m_collectRulesOnly = false; 2042 2043 return m_ruleList.release(); 2044} 2045 2046inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData) 2047{ 2048 m_dynamicPseudo = NOPSEUDO; 2049 2050 // Let the slow path handle SVG as it has some additional rules regarding shadow trees. 2051 if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) { 2052 // We know this selector does not include any pseudo selectors. 2053 if (m_checker.m_pseudoStyle != NOPSEUDO) 2054 return false; 2055 // We know a sufficiently simple single part selector matches simply because we found it from the rule hash. 2056 // This is limited to HTML only so we don't need to check the namespace. 2057 if (ruleData.hasTopSelectorMatchingHTMLBasedOnRuleHash() && !ruleData.hasMultipartSelector() && m_element->isHTMLElement()) 2058 return true; 2059 return SelectorChecker::fastCheckSelector(ruleData.selector(), m_element); 2060 } 2061 2062 // Slow path. 2063 SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0); 2064 if (match != SelectorMatches) 2065 return false; 2066 if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo) 2067 return false; 2068 return true; 2069} 2070 2071static inline bool selectorTagMatches(const Element* element, const CSSSelector* selector) 2072{ 2073 if (!selector->hasTag()) 2074 return true; 2075 const AtomicString& localName = selector->tag().localName(); 2076 if (localName != starAtom && localName != element->localName()) 2077 return false; 2078 const AtomicString& namespaceURI = selector->tag().namespaceURI(); 2079 return namespaceURI == starAtom || namespaceURI == element->namespaceURI(); 2080} 2081 2082static inline bool isFastCheckableSelector(const CSSSelector* selector) 2083{ 2084 for (; selector; selector = selector->tagHistory()) { 2085 if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector) 2086 return false; 2087 if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class) 2088 return false; 2089 } 2090 return true; 2091} 2092 2093template <class ValueChecker> 2094inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement) 2095{ 2096 AtomicStringImpl* value = selector->value().impl(); 2097 for (; element; element = element->parentElement()) { 2098 if (ValueChecker::checkValue(element, value) && selectorTagMatches(element, selector)) { 2099 if (selector->relation() == CSSSelector::Descendant) 2100 topChildOrSubselector = 0; 2101 else if (!topChildOrSubselector) { 2102 ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector); 2103 topChildOrSubselector = selector; 2104 topChildOrSubselectorMatchElement = element; 2105 } 2106 if (selector->relation() != CSSSelector::SubSelector) 2107 element = element->parentElement(); 2108 selector = selector->tagHistory(); 2109 return true; 2110 } 2111 if (topChildOrSubselector) { 2112 // Child or subselector check failed. 2113 // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match 2114 // the original element we were checking. 2115 if (!topChildOrSubselectorMatchElement) 2116 return false; 2117 // There may be other matches down the ancestor chain. 2118 // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors. 2119 selector = topChildOrSubselector; 2120 element = topChildOrSubselectorMatchElement->parentElement(); 2121 topChildOrSubselector = 0; 2122 return true; 2123 } 2124 } 2125 return false; 2126} 2127 2128struct ClassCheck { 2129 static bool checkValue(const Element* element, AtomicStringImpl* value) 2130 { 2131 return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value); 2132 } 2133}; 2134struct IdCheck { 2135 static bool checkValue(const Element* element, AtomicStringImpl* value) 2136 { 2137 return element->hasID() && element->idForStyleResolution().impl() == value; 2138 } 2139}; 2140struct TagCheck { 2141 static bool checkValue(const Element*, AtomicStringImpl*) 2142 { 2143 return true; 2144 } 2145}; 2146 2147bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element) 2148{ 2149 ASSERT(isFastCheckableSelector(selector)); 2150 2151 // The top selector requires tag check only as rule hashes have already handled id and class matches. 2152 if (!selectorTagMatches(element, selector)) 2153 return false; 2154 2155 const CSSSelector* topChildOrSubselector = 0; 2156 const Element* topChildOrSubselectorMatchElement = 0; 2157 if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector) 2158 topChildOrSubselector = selector; 2159 2160 if (selector->relation() != CSSSelector::SubSelector) 2161 element = element->parentElement(); 2162 2163 selector = selector->tagHistory(); 2164 2165 // We know this compound selector has descendant, child and subselector combinators only and all components are simple. 2166 while (selector) { 2167 switch (selector->m_match) { 2168 case CSSSelector::Class: 2169 if (!fastCheckSingleSelector<ClassCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 2170 return false; 2171 break; 2172 case CSSSelector::Id: 2173 if (!fastCheckSingleSelector<IdCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 2174 return false; 2175 break; 2176 case CSSSelector::None: 2177 if (!fastCheckSingleSelector<TagCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 2178 return false; 2179 break; 2180 default: 2181 ASSERT_NOT_REACHED(); 2182 } 2183 } 2184 return true; 2185} 2186 2187// Recursive check of selectors and combinators 2188// It can return 3 different values: 2189// * SelectorMatches - the selector matches the element e 2190// * SelectorFailsLocally - the selector fails for the element e 2191// * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e 2192CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const 2193{ 2194#if ENABLE(SVG) 2195 // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree 2196 // because its contents are not part of the formal document structure. 2197 if (e->isSVGElement() && e->isShadowRoot()) 2198 return SelectorFailsCompletely; 2199#endif 2200 2201 // first selector has to match 2202 if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle)) 2203 return SelectorFailsLocally; 2204 2205 // The rest of the selectors has to match 2206 CSSSelector::Relation relation = sel->relation(); 2207 2208 // Prepare next sel 2209 sel = sel->tagHistory(); 2210 if (!sel) 2211 return SelectorMatches; 2212 2213 if (relation != CSSSelector::SubSelector) 2214 // Bail-out if this selector is irrelevant for the pseudoStyle 2215 if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo) 2216 return SelectorFailsCompletely; 2217 2218 // Check for nested links. 2219 if (m_matchVisitedPseudoClass && !isSubSelector) { 2220 RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle(); 2221 if (currentStyle && currentStyle->insideLink() && e->isLink()) { 2222 if (encounteredLink) 2223 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching. 2224 else 2225 encounteredLink = true; 2226 } 2227 } 2228 2229 switch (relation) { 2230 case CSSSelector::Descendant: 2231 while (true) { 2232 ContainerNode* n = e->parentNode(); 2233 if (!n || !n->isElementNode()) 2234 return SelectorFailsCompletely; 2235 e = static_cast<Element*>(n); 2236 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 2237 if (match != SelectorFailsLocally) 2238 return match; 2239 } 2240 break; 2241 case CSSSelector::Child: 2242 { 2243 ContainerNode* n = e->parentNode(); 2244 if (!n || !n->isElementNode()) 2245 return SelectorFailsCompletely; 2246 e = static_cast<Element*>(n); 2247 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 2248 } 2249 case CSSSelector::DirectAdjacent: 2250 { 2251 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { 2252 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 2253 if (parentStyle) 2254 parentStyle->setChildrenAffectedByDirectAdjacentRules(); 2255 } 2256 Node* n = e->previousSibling(); 2257 while (n && !n->isElementNode()) 2258 n = n->previousSibling(); 2259 if (!n) 2260 return SelectorFailsLocally; 2261 e = static_cast<Element*>(n); 2262 m_matchVisitedPseudoClass = false; 2263 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 2264 } 2265 case CSSSelector::IndirectAdjacent: 2266 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { 2267 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 2268 if (parentStyle) 2269 parentStyle->setChildrenAffectedByForwardPositionalRules(); 2270 } 2271 while (true) { 2272 Node* n = e->previousSibling(); 2273 while (n && !n->isElementNode()) 2274 n = n->previousSibling(); 2275 if (!n) 2276 return SelectorFailsLocally; 2277 e = static_cast<Element*>(n); 2278 m_matchVisitedPseudoClass = false; 2279 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 2280 if (match != SelectorFailsLocally) 2281 return match; 2282 }; 2283 break; 2284 case CSSSelector::SubSelector: 2285 // a selector is invalid if something follows a pseudo-element 2286 // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) 2287 // to follow the pseudo elements. 2288 if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION && 2289 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass)) 2290 return SelectorFailsCompletely; 2291 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle); 2292 case CSSSelector::ShadowDescendant: 2293 { 2294 Node* shadowHostNode = e->shadowAncestorNode(); 2295 if (shadowHostNode == e || !shadowHostNode->isElementNode()) 2296 return SelectorFailsCompletely; 2297 e = static_cast<Element*>(shadowHostNode); 2298 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); 2299 } 2300 } 2301 2302 return SelectorFailsCompletely; 2303} 2304 2305static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName) 2306{ 2307 set->add(qName.localName().impl()); 2308} 2309 2310static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet() 2311{ 2312 // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive 2313 // Mozilla treats all other values as case-sensitive, thus so do we. 2314 HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>; 2315 2316 addLocalNameToSet(attrSet, accept_charsetAttr); 2317 addLocalNameToSet(attrSet, acceptAttr); 2318 addLocalNameToSet(attrSet, alignAttr); 2319 addLocalNameToSet(attrSet, alinkAttr); 2320 addLocalNameToSet(attrSet, axisAttr); 2321 addLocalNameToSet(attrSet, bgcolorAttr); 2322 addLocalNameToSet(attrSet, charsetAttr); 2323 addLocalNameToSet(attrSet, checkedAttr); 2324 addLocalNameToSet(attrSet, clearAttr); 2325 addLocalNameToSet(attrSet, codetypeAttr); 2326 addLocalNameToSet(attrSet, colorAttr); 2327 addLocalNameToSet(attrSet, compactAttr); 2328 addLocalNameToSet(attrSet, declareAttr); 2329 addLocalNameToSet(attrSet, deferAttr); 2330 addLocalNameToSet(attrSet, dirAttr); 2331 addLocalNameToSet(attrSet, disabledAttr); 2332 addLocalNameToSet(attrSet, enctypeAttr); 2333 addLocalNameToSet(attrSet, faceAttr); 2334 addLocalNameToSet(attrSet, frameAttr); 2335 addLocalNameToSet(attrSet, hreflangAttr); 2336 addLocalNameToSet(attrSet, http_equivAttr); 2337 addLocalNameToSet(attrSet, langAttr); 2338 addLocalNameToSet(attrSet, languageAttr); 2339 addLocalNameToSet(attrSet, linkAttr); 2340 addLocalNameToSet(attrSet, mediaAttr); 2341 addLocalNameToSet(attrSet, methodAttr); 2342 addLocalNameToSet(attrSet, multipleAttr); 2343 addLocalNameToSet(attrSet, nohrefAttr); 2344 addLocalNameToSet(attrSet, noresizeAttr); 2345 addLocalNameToSet(attrSet, noshadeAttr); 2346 addLocalNameToSet(attrSet, nowrapAttr); 2347 addLocalNameToSet(attrSet, readonlyAttr); 2348 addLocalNameToSet(attrSet, relAttr); 2349 addLocalNameToSet(attrSet, revAttr); 2350 addLocalNameToSet(attrSet, rulesAttr); 2351 addLocalNameToSet(attrSet, scopeAttr); 2352 addLocalNameToSet(attrSet, scrollingAttr); 2353 addLocalNameToSet(attrSet, selectedAttr); 2354 addLocalNameToSet(attrSet, shapeAttr); 2355 addLocalNameToSet(attrSet, targetAttr); 2356 addLocalNameToSet(attrSet, textAttr); 2357 addLocalNameToSet(attrSet, typeAttr); 2358 addLocalNameToSet(attrSet, valignAttr); 2359 addLocalNameToSet(attrSet, valuetypeAttr); 2360 addLocalNameToSet(attrSet, vlinkAttr); 2361 2362 return attrSet; 2363} 2364 2365static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr) 2366{ 2367 static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet(); 2368 bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom); 2369 return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl()); 2370} 2371 2372bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const 2373{ 2374 ASSERT(e); 2375 if (!e) 2376 return false; 2377 2378 if (!selectorTagMatches(e, sel)) 2379 return false; 2380 2381 if (sel->hasAttribute()) { 2382 if (sel->m_match == CSSSelector::Class) 2383 return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value()); 2384 2385 if (sel->m_match == CSSSelector::Id) 2386 return e->hasID() && e->idForStyleResolution() == sel->value(); 2387 2388 const QualifiedName& attr = sel->attribute(); 2389 2390 // FIXME: Handle the case were elementStyle is 0. 2391 if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) { 2392 elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style. 2393 if (selectorAttrs) 2394 selectorAttrs->add(attr.localName().impl()); 2395 } 2396 2397 const AtomicString& value = e->getAttribute(attr); 2398 if (value.isNull()) 2399 return false; // attribute is not set 2400 2401 bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr); 2402 2403 switch (sel->m_match) { 2404 case CSSSelector::Exact: 2405 if (caseSensitive ? sel->value() != value : !equalIgnoringCase(sel->value(), value)) 2406 return false; 2407 break; 2408 case CSSSelector::List: 2409 { 2410 // Ignore empty selectors or selectors containing spaces 2411 if (sel->value().contains(' ') || sel->value().isEmpty()) 2412 return false; 2413 2414 unsigned startSearchAt = 0; 2415 while (true) { 2416 size_t foundPos = value.find(sel->value(), startSearchAt, caseSensitive); 2417 if (foundPos == notFound) 2418 return false; 2419 if (foundPos == 0 || value[foundPos - 1] == ' ') { 2420 unsigned endStr = foundPos + sel->value().length(); 2421 if (endStr == value.length() || value[endStr] == ' ') 2422 break; // We found a match. 2423 } 2424 2425 // No match. Keep looking. 2426 startSearchAt = foundPos + 1; 2427 } 2428 break; 2429 } 2430 case CSSSelector::Contain: 2431 if (!value.contains(sel->value(), caseSensitive) || sel->value().isEmpty()) 2432 return false; 2433 break; 2434 case CSSSelector::Begin: 2435 if (!value.startsWith(sel->value(), caseSensitive) || sel->value().isEmpty()) 2436 return false; 2437 break; 2438 case CSSSelector::End: 2439 if (!value.endsWith(sel->value(), caseSensitive) || sel->value().isEmpty()) 2440 return false; 2441 break; 2442 case CSSSelector::Hyphen: 2443 if (value.length() < sel->value().length()) 2444 return false; 2445 if (!value.startsWith(sel->value(), caseSensitive)) 2446 return false; 2447 // It they start the same, check for exact match or following '-': 2448 if (value.length() != sel->value().length() && value[sel->value().length()] != '-') 2449 return false; 2450 break; 2451 case CSSSelector::PseudoClass: 2452 case CSSSelector::PseudoElement: 2453 default: 2454 break; 2455 } 2456 } 2457 2458 if (sel->m_match == CSSSelector::PseudoClass) { 2459 // Handle :not up front. 2460 if (sel->pseudoType() == CSSSelector::PseudoNot) { 2461 ASSERT(sel->selectorList()); 2462 for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) { 2463 // :not cannot nest. I don't really know why this is a 2464 // restriction in CSS3, but it is, so let's honor it. 2465 // the parser enforces that this never occurs 2466 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot); 2467 2468 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle)) 2469 return true; 2470 } 2471 } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) { 2472 // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each 2473 // (since there are no elements involved). 2474 return checkScrollbarPseudoClass(sel, dynamicPseudo); 2475 } else if (dynamicPseudo == SELECTION) { 2476 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive) 2477 return !m_document->page()->focusController()->isActive(); 2478 } 2479 2480 // Normal element pseudo class checking. 2481 switch (sel->pseudoType()) { 2482 // Pseudo classes: 2483 case CSSSelector::PseudoNot: 2484 break; // Already handled up above. 2485 case CSSSelector::PseudoEmpty: { 2486 bool result = true; 2487 for (Node* n = e->firstChild(); n; n = n->nextSibling()) { 2488 if (n->isElementNode()) { 2489 result = false; 2490 break; 2491 } else if (n->isTextNode()) { 2492 Text* textNode = static_cast<Text*>(n); 2493 if (!textNode->data().isEmpty()) { 2494 result = false; 2495 break; 2496 } 2497 } 2498 } 2499 if (!m_collectRulesOnly) { 2500 if (elementStyle) 2501 elementStyle->setEmptyState(result); 2502 else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique())) 2503 e->renderStyle()->setEmptyState(result); 2504 } 2505 return result; 2506 } 2507 case CSSSelector::PseudoFirstChild: { 2508 // first-child matches the first child that is an element 2509 if (e->parentNode() && e->parentNode()->isElementNode()) { 2510 bool result = false; 2511 Node* n = e->previousSibling(); 2512 while (n && !n->isElementNode()) 2513 n = n->previousSibling(); 2514 if (!n) 2515 result = true; 2516 if (!m_collectRulesOnly) { 2517 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 2518 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 2519 if (parentStyle) 2520 parentStyle->setChildrenAffectedByFirstChildRules(); 2521 if (result && childStyle) 2522 childStyle->setFirstChildState(); 2523 } 2524 return result; 2525 } 2526 break; 2527 } 2528 case CSSSelector::PseudoFirstOfType: { 2529 // first-of-type matches the first element of its type 2530 if (e->parentNode() && e->parentNode()->isElementNode()) { 2531 bool result = false; 2532 const QualifiedName& type = e->tagQName(); 2533 Node* n = e->previousSibling(); 2534 while (n) { 2535 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2536 break; 2537 n = n->previousSibling(); 2538 } 2539 if (!n) 2540 result = true; 2541 if (!m_collectRulesOnly) { 2542 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 2543 if (parentStyle) 2544 parentStyle->setChildrenAffectedByForwardPositionalRules(); 2545 } 2546 return result; 2547 } 2548 break; 2549 } 2550 case CSSSelector::PseudoLastChild: { 2551 // last-child matches the last child that is an element 2552 if (Element* parentElement = e->parentElement()) { 2553 bool result = false; 2554 if (parentElement->isFinishedParsingChildren()) { 2555 Node* n = e->nextSibling(); 2556 while (n && !n->isElementNode()) 2557 n = n->nextSibling(); 2558 if (!n) 2559 result = true; 2560 } 2561 if (!m_collectRulesOnly) { 2562 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 2563 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2564 if (parentStyle) 2565 parentStyle->setChildrenAffectedByLastChildRules(); 2566 if (result && childStyle) 2567 childStyle->setLastChildState(); 2568 } 2569 return result; 2570 } 2571 break; 2572 } 2573 case CSSSelector::PseudoLastOfType: { 2574 // last-of-type matches the last element of its type 2575 if (Element* parentElement = e->parentElement()) { 2576 if (!m_collectRulesOnly) { 2577 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2578 if (parentStyle) 2579 parentStyle->setChildrenAffectedByBackwardPositionalRules(); 2580 } 2581 if (!parentElement->isFinishedParsingChildren()) 2582 return false; 2583 bool result = false; 2584 const QualifiedName& type = e->tagQName(); 2585 Node* n = e->nextSibling(); 2586 while (n) { 2587 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2588 break; 2589 n = n->nextSibling(); 2590 } 2591 if (!n) 2592 result = true; 2593 return result; 2594 } 2595 break; 2596 } 2597 case CSSSelector::PseudoOnlyChild: { 2598 if (Element* parentElement = e->parentElement()) { 2599 bool firstChild = false; 2600 bool lastChild = false; 2601 2602 Node* n = e->previousSibling(); 2603 while (n && !n->isElementNode()) 2604 n = n->previousSibling(); 2605 if (!n) 2606 firstChild = true; 2607 if (firstChild && parentElement->isFinishedParsingChildren()) { 2608 n = e->nextSibling(); 2609 while (n && !n->isElementNode()) 2610 n = n->nextSibling(); 2611 if (!n) 2612 lastChild = true; 2613 } 2614 if (!m_collectRulesOnly) { 2615 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 2616 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2617 if (parentStyle) { 2618 parentStyle->setChildrenAffectedByFirstChildRules(); 2619 parentStyle->setChildrenAffectedByLastChildRules(); 2620 } 2621 if (firstChild && childStyle) 2622 childStyle->setFirstChildState(); 2623 if (lastChild && childStyle) 2624 childStyle->setLastChildState(); 2625 } 2626 return firstChild && lastChild; 2627 } 2628 break; 2629 } 2630 case CSSSelector::PseudoOnlyOfType: { 2631 // FIXME: This selector is very slow. 2632 if (Element* parentElement = e->parentElement()) { 2633 if (!m_collectRulesOnly) { 2634 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2635 if (parentStyle) { 2636 parentStyle->setChildrenAffectedByForwardPositionalRules(); 2637 parentStyle->setChildrenAffectedByBackwardPositionalRules(); 2638 } 2639 } 2640 if (!parentElement->isFinishedParsingChildren()) 2641 return false; 2642 bool firstChild = false; 2643 bool lastChild = false; 2644 const QualifiedName& type = e->tagQName(); 2645 Node* n = e->previousSibling(); 2646 while (n) { 2647 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2648 break; 2649 n = n->previousSibling(); 2650 } 2651 if (!n) 2652 firstChild = true; 2653 if (firstChild) { 2654 n = e->nextSibling(); 2655 while (n) { 2656 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2657 break; 2658 n = n->nextSibling(); 2659 } 2660 if (!n) 2661 lastChild = true; 2662 } 2663 return firstChild && lastChild; 2664 } 2665 break; 2666 } 2667 case CSSSelector::PseudoNthChild: { 2668 if (!sel->parseNth()) 2669 break; 2670 if (Element* parentElement = e->parentElement()) { 2671 int count = 1; 2672 Node* n = e->previousSibling(); 2673 while (n) { 2674 if (n->isElementNode()) { 2675 RenderStyle* s = n->renderStyle(); 2676 unsigned index = s ? s->childIndex() : 0; 2677 if (index) { 2678 count += index; 2679 break; 2680 } 2681 count++; 2682 } 2683 n = n->previousSibling(); 2684 } 2685 2686 if (!m_collectRulesOnly) { 2687 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 2688 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2689 if (childStyle) 2690 childStyle->setChildIndex(count); 2691 if (parentStyle) 2692 parentStyle->setChildrenAffectedByForwardPositionalRules(); 2693 } 2694 2695 if (sel->matchNth(count)) 2696 return true; 2697 } 2698 break; 2699 } 2700 case CSSSelector::PseudoNthOfType: { 2701 if (!sel->parseNth()) 2702 break; 2703 if (Element* parentElement = e->parentElement()) { 2704 int count = 1; 2705 const QualifiedName& type = e->tagQName(); 2706 Node* n = e->previousSibling(); 2707 while (n) { 2708 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2709 count++; 2710 n = n->previousSibling(); 2711 } 2712 2713 if (!m_collectRulesOnly) { 2714 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2715 if (parentStyle) 2716 parentStyle->setChildrenAffectedByForwardPositionalRules(); 2717 } 2718 2719 if (sel->matchNth(count)) 2720 return true; 2721 } 2722 break; 2723 } 2724 case CSSSelector::PseudoNthLastChild: { 2725 if (!sel->parseNth()) 2726 break; 2727 if (Element* parentElement = e->parentElement()) { 2728 if (!m_collectRulesOnly) { 2729 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2730 if (parentStyle) 2731 parentStyle->setChildrenAffectedByBackwardPositionalRules(); 2732 } 2733 if (!parentElement->isFinishedParsingChildren()) 2734 return false; 2735 int count = 1; 2736 Node* n = e->nextSibling(); 2737 while (n) { 2738 if (n->isElementNode()) 2739 count++; 2740 n = n->nextSibling(); 2741 } 2742 if (sel->matchNth(count)) 2743 return true; 2744 } 2745 break; 2746 } 2747 case CSSSelector::PseudoNthLastOfType: { 2748 if (!sel->parseNth()) 2749 break; 2750 if (Element* parentElement = e->parentElement()) { 2751 if (!m_collectRulesOnly) { 2752 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 2753 if (parentStyle) 2754 parentStyle->setChildrenAffectedByBackwardPositionalRules(); 2755 } 2756 if (!parentElement->isFinishedParsingChildren()) 2757 return false; 2758 int count = 1; 2759 const QualifiedName& type = e->tagQName(); 2760 Node* n = e->nextSibling(); 2761 while (n) { 2762 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) 2763 count++; 2764 n = n->nextSibling(); 2765 } 2766 if (sel->matchNth(count)) 2767 return true; 2768 } 2769 break; 2770 } 2771 case CSSSelector::PseudoTarget: 2772 if (e == e->document()->cssTarget()) 2773 return true; 2774 break; 2775 case CSSSelector::PseudoAny: 2776 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) { 2777 if (checkSelector(selector, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches) 2778 return true; 2779 } 2780 break; 2781 case CSSSelector::PseudoAnyLink: 2782 if (e && e->isLink()) 2783 return true; 2784 break; 2785 case CSSSelector::PseudoAutofill: { 2786 if (!e || !e->isFormControlElement()) 2787 break; 2788 if (InputElement* inputElement = e->toInputElement()) 2789 return inputElement->isAutofilled(); 2790 break; 2791 } 2792 case CSSSelector::PseudoLink: 2793 if (e && e->isLink()) 2794 return !m_matchVisitedPseudoClass; 2795 break; 2796 case CSSSelector::PseudoVisited: 2797 if (e && e->isLink()) 2798 return m_matchVisitedPseudoClass; 2799 break; 2800 case CSSSelector::PseudoDrag: { 2801 if (elementStyle) 2802 elementStyle->setAffectedByDragRules(true); 2803 else if (e->renderStyle()) 2804 e->renderStyle()->setAffectedByDragRules(true); 2805 if (e->renderer() && e->renderer()->isDragging()) 2806 return true; 2807 break; 2808 } 2809 case CSSSelector::PseudoFocus: 2810 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive()) 2811 return true; 2812 break; 2813 case CSSSelector::PseudoHover: { 2814 // If we're in quirks mode, then hover should never match anchors with no 2815 // href and *:hover should not match anything. This is important for sites like wsj.com. 2816 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { 2817 if (elementStyle) 2818 elementStyle->setAffectedByHoverRules(true); 2819 else if (e->renderStyle()) 2820 e->renderStyle()->setAffectedByHoverRules(true); 2821 if (e->hovered()) 2822 return true; 2823 } 2824 break; 2825 } 2826 case CSSSelector::PseudoActive: 2827 // If we're in quirks mode, then :active should never match anchors with no 2828 // href and *:active should not match anything. 2829 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { 2830 if (elementStyle) 2831 elementStyle->setAffectedByActiveRules(true); 2832 else if (e->renderStyle()) 2833 e->renderStyle()->setAffectedByActiveRules(true); 2834 if (e->active()) 2835 return true; 2836 } 2837 break; 2838 case CSSSelector::PseudoEnabled: 2839 if (e && e->isFormControlElement()) 2840 return e->isEnabledFormControl(); 2841 break; 2842 case CSSSelector::PseudoFullPageMedia: 2843 return e && e->document() && e->document()->isMediaDocument(); 2844 break; 2845 case CSSSelector::PseudoDefault: 2846 return e && e->isDefaultButtonForForm(); 2847 case CSSSelector::PseudoDisabled: 2848 if (e && e->isFormControlElement()) 2849 return !e->isEnabledFormControl(); 2850 break; 2851 case CSSSelector::PseudoReadOnly: { 2852 if (!e || !e->isFormControlElement()) 2853 return false; 2854 return e->isTextFormControl() && e->isReadOnlyFormControl(); 2855 } 2856 case CSSSelector::PseudoReadWrite: { 2857 if (!e || !e->isFormControlElement()) 2858 return false; 2859 return e->isTextFormControl() && !e->isReadOnlyFormControl(); 2860 } 2861 case CSSSelector::PseudoOptional: 2862 return e && e->isOptionalFormControl(); 2863 case CSSSelector::PseudoRequired: 2864 return e && e->isRequiredFormControl(); 2865 case CSSSelector::PseudoValid: { 2866 if (!e) 2867 return false; 2868 e->document()->setContainsValidityStyleRules(); 2869 return e->willValidate() && e->isValidFormControlElement(); 2870 } case CSSSelector::PseudoInvalid: { 2871 if (!e) 2872 return false; 2873 e->document()->setContainsValidityStyleRules(); 2874 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue(); 2875 } case CSSSelector::PseudoChecked: { 2876 if (!e || !e->isFormControlElement()) 2877 break; 2878 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that 2879 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just 2880 // obey the CSS spec here in the test for matching the pseudo. 2881 InputElement* inputElement = e->toInputElement(); 2882 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate()) 2883 return true; 2884 break; 2885 } 2886 case CSSSelector::PseudoIndeterminate: { 2887 if (!e || !e->isFormControlElement()) 2888 break; 2889 InputElement* inputElement = e->toInputElement(); 2890 if (inputElement && inputElement->isIndeterminate()) 2891 return true; 2892 break; 2893 } 2894 case CSSSelector::PseudoRoot: 2895 if (e == e->document()->documentElement()) 2896 return true; 2897 break; 2898 case CSSSelector::PseudoLang: { 2899 AtomicString value = e->computeInheritedLanguage(); 2900 const AtomicString& argument = sel->argument(); 2901 if (value.isEmpty() || !value.startsWith(argument, false)) 2902 break; 2903 if (value.length() != argument.length() && value[argument.length()] != '-') 2904 break; 2905 return true; 2906 } 2907#if ENABLE(FULLSCREEN_API) 2908 case CSSSelector::PseudoFullScreen: 2909 // While a Document is in the fullscreen state, and the document's current fullscreen 2910 // element is an element in the document, the 'full-screen' pseudoclass applies to 2911 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing 2912 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied. 2913 if (!e->document()->webkitIsFullScreen()) 2914 return false; 2915 if (e != e->document()->webkitCurrentFullScreenElement()) 2916 return false; 2917 return true; 2918 case CSSSelector::PseudoFullScreenDocument: 2919 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies 2920 // to all elements of that Document. 2921 if (!e->document()->webkitIsFullScreen()) 2922 return false; 2923 return true; 2924#endif 2925 case CSSSelector::PseudoInRange: 2926 if (!e) 2927 return false; 2928 e->document()->setContainsValidityStyleRules(); 2929 return e->isInRange(); 2930 case CSSSelector::PseudoOutOfRange: 2931 if (!e) 2932 return false; 2933 e->document()->setContainsValidityStyleRules(); 2934 return e->isOutOfRange(); 2935 case CSSSelector::PseudoUnknown: 2936 case CSSSelector::PseudoNotParsed: 2937 default: 2938 ASSERT_NOT_REACHED(); 2939 break; 2940 } 2941 return false; 2942 } 2943 if (sel->m_match == CSSSelector::PseudoElement) { 2944 if (!elementStyle && !m_collectRulesOnly) 2945 return false; 2946 2947 PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType()); 2948 if (pseudoId == FIRST_LETTER) { 2949 if (Document* document = e->document()) 2950 document->setUsesFirstLetterRules(true); 2951 } 2952 if (pseudoId != NOPSEUDO) 2953 dynamicPseudo = pseudoId; 2954 } 2955 // ### add the rest of the checks... 2956 return true; 2957} 2958 2959bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const 2960{ 2961 RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve(); 2962 ScrollbarPart part = RenderScrollbar::partForStyleResolve(); 2963 2964 // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real 2965 // pseudo class and just apply to everything. 2966 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive) 2967 return !m_document->page()->focusController()->isActive(); 2968 2969 if (!scrollbar) 2970 return false; 2971 2972 ASSERT(sel->m_match == CSSSelector::PseudoClass); 2973 switch (sel->pseudoType()) { 2974 case CSSSelector::PseudoEnabled: 2975 return scrollbar->enabled(); 2976 case CSSSelector::PseudoDisabled: 2977 return !scrollbar->enabled(); 2978 case CSSSelector::PseudoHover: { 2979 ScrollbarPart hoveredPart = scrollbar->hoveredPart(); 2980 if (part == ScrollbarBGPart) 2981 return hoveredPart != NoPart; 2982 if (part == TrackBGPart) 2983 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart; 2984 return part == hoveredPart; 2985 } 2986 case CSSSelector::PseudoActive: { 2987 ScrollbarPart pressedPart = scrollbar->pressedPart(); 2988 if (part == ScrollbarBGPart) 2989 return pressedPart != NoPart; 2990 if (part == TrackBGPart) 2991 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart; 2992 return part == pressedPart; 2993 } 2994 case CSSSelector::PseudoHorizontal: 2995 return scrollbar->orientation() == HorizontalScrollbar; 2996 case CSSSelector::PseudoVertical: 2997 return scrollbar->orientation() == VerticalScrollbar; 2998 case CSSSelector::PseudoDecrement: 2999 return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart; 3000 case CSSSelector::PseudoIncrement: 3001 return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart; 3002 case CSSSelector::PseudoStart: 3003 return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart; 3004 case CSSSelector::PseudoEnd: 3005 return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart; 3006 case CSSSelector::PseudoDoubleButton: { 3007 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); 3008 if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart) 3009 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth; 3010 if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart) 3011 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth; 3012 return false; 3013 } 3014 case CSSSelector::PseudoSingleButton: { 3015 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); 3016 if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart) 3017 return buttonsPlacement == ScrollbarButtonsSingle; 3018 return false; 3019 } 3020 case CSSSelector::PseudoNoButton: { 3021 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement(); 3022 if (part == BackTrackPart) 3023 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd; 3024 if (part == ForwardTrackPart) 3025 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart; 3026 return false; 3027 } 3028 case CSSSelector::PseudoCornerPresent: 3029 return scrollbar->scrollableArea()->isScrollCornerVisible(); 3030 default: 3031 return false; 3032 } 3033} 3034 3035// ----------------------------------------------------------------- 3036 3037static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector) 3038{ 3039 const AtomicString& selectorNamespace = selector->tag().namespaceURI(); 3040 if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) 3041 return false; 3042 if (selector->m_match == CSSSelector::None) 3043 return true; 3044 if (selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class) 3045 return false; 3046 return selector->tag() == starAtom; 3047} 3048 3049RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position) 3050 : m_rule(rule) 3051 , m_selector(selector) 3052 , m_specificity(selector->specificity()) 3053 , m_position(position) 3054 , m_hasFastCheckableSelector(isFastCheckableSelector(selector)) 3055 , m_hasMultipartSelector(selector->tagHistory()) 3056 , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector)) 3057{ 3058 collectDescendantSelectorIdentifierHashes(); 3059} 3060 3061inline void RuleData::collectIdentifierHashes(const CSSSelector* selector, unsigned& identifierCount) 3062{ 3063 if ((selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class) && !selector->value().isEmpty()) 3064 m_descendantSelectorIdentifierHashes[identifierCount++] = selector->value().impl()->existingHash(); 3065 if (identifierCount == maximumIdentifierCount) 3066 return; 3067 const AtomicString& localName = selector->tag().localName(); 3068 if (localName != starAtom) 3069 m_descendantSelectorIdentifierHashes[identifierCount++] = localName.impl()->existingHash(); 3070} 3071 3072inline void RuleData::collectDescendantSelectorIdentifierHashes() 3073{ 3074 unsigned identifierCount = 0; 3075 CSSSelector::Relation relation = m_selector->relation(); 3076 3077 // Skip the topmost selector. It is handled quickly by the rule hashes. 3078 bool skipOverSubselectors = true; 3079 for (const CSSSelector* selector = m_selector->tagHistory(); selector; selector = selector->tagHistory()) { 3080 // Only collect identifiers that match ancestors. 3081 switch (relation) { 3082 case CSSSelector::SubSelector: 3083 if (!skipOverSubselectors) 3084 collectIdentifierHashes(selector, identifierCount); 3085 break; 3086 case CSSSelector::DirectAdjacent: 3087 case CSSSelector::IndirectAdjacent: 3088 case CSSSelector::ShadowDescendant: 3089 skipOverSubselectors = true; 3090 break; 3091 case CSSSelector::Descendant: 3092 case CSSSelector::Child: 3093 skipOverSubselectors = false; 3094 collectIdentifierHashes(selector, identifierCount); 3095 break; 3096 } 3097 if (identifierCount == maximumIdentifierCount) 3098 return; 3099 relation = selector->relation(); 3100 } 3101 m_descendantSelectorIdentifierHashes[identifierCount] = 0; 3102} 3103 3104RuleSet::RuleSet() 3105 : m_ruleCount(0) 3106 , m_autoShrinkToFitEnabled(true) 3107{ 3108} 3109 3110RuleSet::~RuleSet() 3111{ 3112 deleteAllValues(m_idRules); 3113 deleteAllValues(m_classRules); 3114 deleteAllValues(m_pseudoRules); 3115 deleteAllValues(m_tagRules); 3116} 3117 3118 3119void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, 3120 CSSStyleRule* rule, CSSSelector* sel) 3121{ 3122 if (!key) return; 3123 Vector<RuleData>* rules = map.get(key); 3124 if (!rules) { 3125 rules = new Vector<RuleData>; 3126 map.set(key, rules); 3127 } 3128 rules->append(RuleData(rule, sel, m_ruleCount++)); 3129} 3130 3131void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) 3132{ 3133 if (sel->m_match == CSSSelector::Id) { 3134 addToRuleSet(sel->value().impl(), m_idRules, rule, sel); 3135 return; 3136 } 3137 if (sel->m_match == CSSSelector::Class) { 3138 addToRuleSet(sel->value().impl(), m_classRules, rule, sel); 3139 return; 3140 } 3141 3142 if (sel->isUnknownPseudoElement()) { 3143 addToRuleSet(sel->value().impl(), m_pseudoRules, rule, sel); 3144 return; 3145 } 3146 3147 const AtomicString& localName = sel->tag().localName(); 3148 if (localName != starAtom) { 3149 addToRuleSet(localName.impl(), m_tagRules, rule, sel); 3150 return; 3151 } 3152 3153 m_universalRules.append(RuleData(rule, sel, m_ruleCount++)); 3154} 3155 3156void RuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel) 3157{ 3158 m_pageRules.append(RuleData(rule, sel, m_pageRules.size())); 3159} 3160 3161void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector) 3162{ 3163 if (!sheet) 3164 return; 3165 3166 // No media implies "all", but if a media list exists it must 3167 // contain our current medium 3168 if (sheet->media() && !medium.eval(sheet->media(), styleSelector)) 3169 return; // the style sheet doesn't apply 3170 3171 int len = sheet->length(); 3172 3173 for (int i = 0; i < len; i++) { 3174 StyleBase* item = sheet->item(i); 3175 if (item->isStyleRule()) 3176 addStyleRule(static_cast<CSSStyleRule*>(item)); 3177 else if (item->isImportRule()) { 3178 CSSImportRule* import = static_cast<CSSImportRule*>(item); 3179 if (!import->media() || medium.eval(import->media(), styleSelector)) 3180 addRulesFromSheet(import->styleSheet(), medium, styleSelector); 3181 } 3182 else if (item->isMediaRule()) { 3183 CSSMediaRule* r = static_cast<CSSMediaRule*>(item); 3184 CSSRuleList* rules = r->cssRules(); 3185 3186 if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) { 3187 // Traverse child elements of the @media rule. 3188 for (unsigned j = 0; j < rules->length(); j++) { 3189 CSSRule *childItem = rules->item(j); 3190 if (childItem->isStyleRule()) { 3191 // It is a StyleRule, so append it to our list 3192 addStyleRule(static_cast<CSSStyleRule*>(childItem)); 3193 } else if (childItem->isFontFaceRule() && styleSelector) { 3194 // Add this font face to our set. 3195 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem); 3196 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); 3197 } else if (childItem->isKeyframesRule() && styleSelector) { 3198 // Add this keyframe rule to our set. 3199 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem)); 3200 } 3201 } // for rules 3202 } // if rules 3203 } else if (item->isFontFaceRule() && styleSelector) { 3204 // Add this font face to our set. 3205 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item); 3206 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); 3207 } else if (item->isKeyframesRule()) 3208 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item)); 3209 } 3210 if (m_autoShrinkToFitEnabled) 3211 shrinkToFit(); 3212} 3213 3214void RuleSet::addStyleRule(CSSStyleRule* rule) 3215{ 3216 if (rule->isPageRule()) { 3217 CSSPageRule* pageRule = static_cast<CSSPageRule*>(rule); 3218 addPageRule(pageRule, pageRule->selectorList().first()); 3219 } else { 3220 for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s)) 3221 addRule(rule, s); 3222 } 3223} 3224 3225static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector) 3226{ 3227 if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty()) 3228 features.idsInRules.add(selector->value().impl()); 3229 switch (selector->pseudoType()) { 3230 case CSSSelector::PseudoFirstLine: 3231 features.usesFirstLineRules = true; 3232 break; 3233 case CSSSelector::PseudoBefore: 3234 case CSSSelector::PseudoAfter: 3235 features.usesBeforeAfterRules = true; 3236 break; 3237 case CSSSelector::PseudoLink: 3238 case CSSSelector::PseudoVisited: 3239 features.usesLinkRules = true; 3240 break; 3241 default: 3242 break; 3243 } 3244} 3245 3246static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules) 3247{ 3248 unsigned size = rules.size(); 3249 for (unsigned i = 0; i < size; ++i) { 3250 const RuleData& ruleData = rules[i]; 3251 bool foundSiblingSelector = false; 3252 for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { 3253 collectFeaturesFromSelector(features, selector); 3254 3255 if (CSSSelectorList* selectorList = selector->selectorList()) { 3256 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { 3257 if (selector->isSiblingSelector()) 3258 foundSiblingSelector = true; 3259 collectFeaturesFromSelector(features, subSelector); 3260 } 3261 } else if (selector->isSiblingSelector()) 3262 foundSiblingSelector = true; 3263 } 3264 if (foundSiblingSelector) { 3265 if (!features.siblingRules) 3266 features.siblingRules = adoptPtr(new RuleSet); 3267 features.siblingRules->addRule(ruleData.rule(), ruleData.selector()); 3268 } 3269 } 3270} 3271 3272void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const 3273{ 3274 AtomRuleMap::const_iterator end = m_idRules.end(); 3275 for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it) 3276 collectFeaturesFromList(features, *it->second); 3277 end = m_classRules.end(); 3278 for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it) 3279 collectFeaturesFromList(features, *it->second); 3280 end = m_tagRules.end(); 3281 for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it) 3282 collectFeaturesFromList(features, *it->second); 3283 end = m_pseudoRules.end(); 3284 for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it) 3285 collectFeaturesFromList(features, *it->second); 3286 collectFeaturesFromList(features, m_universalRules); 3287} 3288 3289static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) 3290{ 3291 RuleSet::AtomRuleMap::iterator end = map.end(); 3292 for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it) 3293 it->second->shrinkToFit(); 3294} 3295 3296void RuleSet::shrinkToFit() 3297{ 3298 shrinkMapVectorsToFit(m_idRules); 3299 shrinkMapVectorsToFit(m_classRules); 3300 shrinkMapVectorsToFit(m_tagRules); 3301 shrinkMapVectorsToFit(m_pseudoRules); 3302 m_universalRules.shrinkToFit(); 3303 m_pageRules.shrinkToFit(); 3304} 3305 3306// ------------------------------------------------------------------------------------- 3307// this is mostly boring stuff on how to apply a certain rule to the renderstyle... 3308 3309static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0) 3310{ 3311 // This function is tolerant of a null style value. The only place style is used is in 3312 // length measurements, like 'ems' and 'px'. And in those cases style is only used 3313 // when the units are EMS or EXS. So we will just fail in those cases. 3314 Length l; 3315 if (!primitiveValue) { 3316 if (ok) 3317 *ok = false; 3318 } else { 3319 int type = primitiveValue->primitiveType(); 3320 3321 if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) { 3322 if (ok) 3323 *ok = false; 3324 } else if (CSSPrimitiveValue::isUnitTypeLength(type)) { 3325 if (toFloat) 3326 l = Length(primitiveValue->computeLengthDouble(style, rootStyle, multiplier), Fixed); 3327 else 3328 l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed); 3329 } 3330 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 3331 l = Length(primitiveValue->getDoubleValue(), Percent); 3332 else if (type == CSSPrimitiveValue::CSS_NUMBER) 3333 l = Length(primitiveValue->getDoubleValue() * 100.0, Percent); 3334 else if (ok) 3335 *ok = false; 3336 } 3337 return l; 3338} 3339 3340static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) 3341{ 3342 return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok); 3343} 3344 3345static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) 3346{ 3347 return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok); 3348} 3349 3350template <bool applyFirst> 3351void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex) 3352{ 3353 if (startIndex == -1) 3354 return; 3355 3356 for (int i = startIndex; i <= endIndex; i++) { 3357 CSSMutableStyleDeclaration* decl = m_matchedDecls[i]; 3358 CSSMutableStyleDeclaration::const_iterator end = decl->end(); 3359 for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) { 3360 const CSSProperty& current = *it; 3361 if (isImportant == current.isImportant()) { 3362 int property = current.id(); 3363 3364 if (applyFirst) { 3365 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property); 3366 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 14, CSS_zoom_is_end_of_first_prop_range); 3367 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom); 3368 3369 // give special priority to font-xxx, color properties, etc 3370 if (property <= CSSPropertyLineHeight) { 3371 // we apply line-height later 3372 if (property == CSSPropertyLineHeight) 3373 m_lineHeightValue = current.value(); 3374 else 3375 applyProperty(current.id(), current.value()); 3376 } 3377 } else { 3378 if (property > CSSPropertyLineHeight) 3379 applyProperty(current.id(), current.value()); 3380 } 3381 } 3382 } 3383 } 3384} 3385 3386void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName) 3387{ 3388 m_matchedRules.clear(); 3389 3390 if (!rules) 3391 return; 3392 3393 matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName); 3394 3395 // If we didn't match any rules, we're done. 3396 if (m_matchedRules.isEmpty()) 3397 return; 3398 3399 // Sort the set of matched rules. 3400 sortMatchedRules(); 3401 3402 // Now transfer the set of matched rules over to our list of decls. 3403 for (unsigned i = 0; i < m_matchedRules.size(); i++) 3404 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); 3405} 3406 3407void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName) 3408{ 3409 if (!rules) 3410 return; 3411 3412 unsigned size = rules->size(); 3413 for (unsigned i = 0; i < size; ++i) { 3414 const RuleData& ruleData = rules->at(i); 3415 CSSStyleRule* rule = ruleData.rule(); 3416 const AtomicString& selectorLocalName = ruleData.selector()->tag().localName(); 3417 if (selectorLocalName != starAtom && selectorLocalName != pageName) 3418 continue; 3419 CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType(); 3420 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage) 3421 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage) 3422 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage)) 3423 continue; 3424 3425 // If the rule has no properties to apply, then ignore it. 3426 CSSMutableStyleDeclaration* decl = rule->declaration(); 3427 if (!decl || !decl->length()) 3428 continue; 3429 3430 // Add this rule to our list of matched rules. 3431 addMatchedRule(&ruleData); 3432 } 3433} 3434 3435bool CSSStyleSelector::isLeftPage(int pageIndex) const 3436{ 3437 bool isFirstPageLeft = false; 3438 if (!m_rootElementStyle->isLeftToRightDirection()) 3439 isFirstPageLeft = true; 3440 3441 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2; 3442} 3443 3444bool CSSStyleSelector::isFirstPage(int pageIndex) const 3445{ 3446 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page. 3447 return (!pageIndex); 3448} 3449 3450String CSSStyleSelector::pageName(int /* pageIndex */) const 3451{ 3452 // FIXME: Implement page index to page name mapping. 3453 return ""; 3454} 3455 3456static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset) 3457{ 3458 CounterDirectiveMap& map = style->accessCounterDirectives(); 3459 typedef CounterDirectiveMap::iterator Iterator; 3460 3461 Iterator end = map.end(); 3462 for (Iterator it = map.begin(); it != end; ++it) 3463 if (isReset) 3464 it->second.m_reset = false; 3465 else 3466 it->second.m_increment = false; 3467 3468 int length = list ? list->length() : 0; 3469 for (int i = 0; i < length; ++i) { 3470 CSSValue* currValue = list->itemWithoutBoundsCheck(i); 3471 if (!currValue->isPrimitiveValue()) 3472 continue; 3473 3474 Pair* pair = static_cast<CSSPrimitiveValue*>(currValue)->getPairValue(); 3475 if (!pair || !pair->first() || !pair->second()) 3476 continue; 3477 3478 AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue(); 3479 // FIXME: What about overflow? 3480 int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue(); 3481 CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second; 3482 if (isReset) { 3483 directives.m_reset = true; 3484 directives.m_resetValue = value; 3485 } else { 3486 if (directives.m_increment) 3487 directives.m_incrementValue += value; 3488 else { 3489 directives.m_increment = true; 3490 directives.m_incrementValue = value; 3491 } 3492 } 3493 } 3494} 3495 3496void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style) 3497{ 3498 initElement(0); 3499 initForStyleResolve(0, style); 3500 m_style = style; 3501 if (value) 3502 applyProperty(id, value); 3503} 3504 3505inline bool isValidVisitedLinkProperty(int id) 3506{ 3507 switch(static_cast<CSSPropertyID>(id)) { 3508 case CSSPropertyBackgroundColor: 3509 case CSSPropertyBorderLeftColor: 3510 case CSSPropertyBorderRightColor: 3511 case CSSPropertyBorderTopColor: 3512 case CSSPropertyBorderBottomColor: 3513 case CSSPropertyColor: 3514 case CSSPropertyOutlineColor: 3515 case CSSPropertyWebkitColumnRuleColor: 3516 case CSSPropertyWebkitTextEmphasisColor: 3517 case CSSPropertyWebkitTextFillColor: 3518 case CSSPropertyWebkitTextStrokeColor: 3519 // Also allow shorthands so that inherit/initial still work. 3520 case CSSPropertyBackground: 3521 case CSSPropertyBorderLeft: 3522 case CSSPropertyBorderRight: 3523 case CSSPropertyBorderTop: 3524 case CSSPropertyBorderBottom: 3525 case CSSPropertyOutline: 3526 case CSSPropertyWebkitColumnRule: 3527#if ENABLE(SVG) 3528 case CSSPropertyFill: 3529 case CSSPropertyStroke: 3530#endif 3531 return true; 3532 default: 3533 break; 3534 } 3535 3536 return false; 3537} 3538 3539// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead 3540// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() 3541// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. 3542// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) 3543// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like 3544// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, 3545// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific 3546// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). 3547static inline bool useSVGZoomRules(const Element* e) 3548{ 3549 return e && e->isSVGElement(); 3550} 3551 3552void CSSStyleSelector::applyProperty(int id, CSSValue *value) 3553{ 3554 CSSPrimitiveValue* primitiveValue = 0; 3555 if (value->isPrimitiveValue()) 3556 primitiveValue = static_cast<CSSPrimitiveValue*>(value); 3557 3558 float zoomFactor = m_style->effectiveZoom(); 3559 3560 Length l; 3561 bool apply = false; 3562 3563 unsigned short valueType = value->cssValueType(); 3564 3565 bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT; 3566 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT); 3567 3568 id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode()); 3569 3570 if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) { 3571 // Limit the properties that can be applied to only the ones honored by :visited. 3572 return; 3573 } 3574 3575 CSSPropertyID property = static_cast<CSSPropertyID>(id); 3576 3577 // check lookup table for implementations and use when available 3578 if (m_applyProperty.implements(property)) { 3579 if (isInherit) 3580 m_applyProperty.applyInheritValue(property, this); 3581 else if (isInitial) 3582 m_applyProperty.applyInitialValue(property, this); 3583 else 3584 m_applyProperty.applyValue(property, this, value); 3585 return; 3586 } 3587 3588 // What follows is a list that maps the CSS properties into their corresponding front-end 3589 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and 3590 // are only hit when mapping "inherit" or "initial" into front-end values. 3591 switch (property) { 3592// ident only properties 3593 case CSSPropertyBorderCollapse: 3594 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) 3595 if (!primitiveValue) 3596 return; 3597 switch (primitiveValue->getIdent()) { 3598 case CSSValueCollapse: 3599 m_style->setBorderCollapse(true); 3600 break; 3601 case CSSValueSeparate: 3602 m_style->setBorderCollapse(false); 3603 break; 3604 default: 3605 return; 3606 } 3607 return; 3608 case CSSPropertyOutlineStyle: 3609 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) 3610 if (primitiveValue) { 3611 if (primitiveValue->getIdent() == CSSValueAuto) 3612 m_style->setOutlineStyle(DOTTED, true); 3613 else 3614 m_style->setOutlineStyle(*primitiveValue); 3615 } 3616 return; 3617 case CSSPropertyCaptionSide: 3618 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide) 3619 return; 3620 case CSSPropertyClear: 3621 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear) 3622 return; 3623 case CSSPropertyDisplay: 3624 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display) 3625#if ENABLE(WCSS) 3626 if (primitiveValue) { 3627 if (primitiveValue->getIdent() == CSSValueWapMarquee) { 3628 // Initialize WAP Marquee style 3629 m_style->setOverflowX(OMARQUEE); 3630 m_style->setOverflowY(OMARQUEE); 3631 m_style->setWhiteSpace(NOWRAP); 3632 m_style->setMarqueeDirection(MLEFT); 3633 m_style->setMarqueeSpeed(85); // Normal speed 3634 m_style->setMarqueeLoopCount(1); 3635 m_style->setMarqueeBehavior(MSCROLL); 3636 3637 if (m_parentStyle) 3638 m_style->setDisplay(m_parentStyle->display()); 3639 else 3640 m_style->setDisplay(*primitiveValue); 3641 } else 3642 m_style->setDisplay(*primitiveValue); 3643 } 3644#endif 3645 return; 3646 case CSSPropertyEmptyCells: 3647 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells) 3648 return; 3649 case CSSPropertyFloat: 3650 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating) 3651 return; 3652 case CSSPropertyFontStyle: 3653 { 3654 FontDescription fontDescription = m_style->fontDescription(); 3655 if (isInherit) 3656 fontDescription.setItalic(m_parentStyle->fontDescription().italic()); 3657 else if (isInitial) 3658 fontDescription.setItalic(false); 3659 else { 3660 if (!primitiveValue) 3661 return; 3662 switch (primitiveValue->getIdent()) { 3663 case CSSValueOblique: 3664 // FIXME: oblique is the same as italic for the moment... 3665 case CSSValueItalic: 3666 fontDescription.setItalic(true); 3667 break; 3668 case CSSValueNormal: 3669 fontDescription.setItalic(false); 3670 break; 3671 default: 3672 return; 3673 } 3674 } 3675 if (m_style->setFontDescription(fontDescription)) 3676 m_fontDirty = true; 3677 return; 3678 } 3679 3680 case CSSPropertyFontVariant: 3681 { 3682 FontDescription fontDescription = m_style->fontDescription(); 3683 if (isInherit) 3684 fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps()); 3685 else if (isInitial) 3686 fontDescription.setSmallCaps(false); 3687 else { 3688 if (!primitiveValue) 3689 return; 3690 int id = primitiveValue->getIdent(); 3691 if (id == CSSValueNormal) 3692 fontDescription.setSmallCaps(false); 3693 else if (id == CSSValueSmallCaps) 3694 fontDescription.setSmallCaps(true); 3695 else 3696 return; 3697 } 3698 if (m_style->setFontDescription(fontDescription)) 3699 m_fontDirty = true; 3700 return; 3701 } 3702 3703 case CSSPropertyFontWeight: 3704 { 3705 FontDescription fontDescription = m_style->fontDescription(); 3706 if (isInherit) 3707 fontDescription.setWeight(m_parentStyle->fontDescription().weight()); 3708 else if (isInitial) 3709 fontDescription.setWeight(FontWeightNormal); 3710 else { 3711 if (!primitiveValue) 3712 return; 3713 if (primitiveValue->getIdent()) { 3714 switch (primitiveValue->getIdent()) { 3715 case CSSValueBolder: 3716 fontDescription.setWeight(fontDescription.bolderWeight()); 3717 break; 3718 case CSSValueLighter: 3719 fontDescription.setWeight(fontDescription.lighterWeight()); 3720 break; 3721 case CSSValueBold: 3722 case CSSValue700: 3723 fontDescription.setWeight(FontWeightBold); 3724 break; 3725 case CSSValueNormal: 3726 case CSSValue400: 3727 fontDescription.setWeight(FontWeightNormal); 3728 break; 3729 case CSSValue900: 3730 fontDescription.setWeight(FontWeight900); 3731 break; 3732 case CSSValue800: 3733 fontDescription.setWeight(FontWeight800); 3734 break; 3735 case CSSValue600: 3736 fontDescription.setWeight(FontWeight600); 3737 break; 3738 case CSSValue500: 3739 fontDescription.setWeight(FontWeight500); 3740 break; 3741 case CSSValue300: 3742 fontDescription.setWeight(FontWeight300); 3743 break; 3744 case CSSValue200: 3745 fontDescription.setWeight(FontWeight200); 3746 break; 3747 case CSSValue100: 3748 fontDescription.setWeight(FontWeight100); 3749 break; 3750 default: 3751 return; 3752 } 3753 } else 3754 ASSERT_NOT_REACHED(); 3755 } 3756 if (m_style->setFontDescription(fontDescription)) 3757 m_fontDirty = true; 3758 return; 3759 } 3760 3761 case CSSPropertyListStylePosition: 3762 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStylePosition, ListStylePosition) 3763 return; 3764 case CSSPropertyListStyleType: 3765 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType) 3766 return; 3767 case CSSPropertyPageBreakBefore: 3768 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) 3769 return; 3770 case CSSPropertyPageBreakAfter: 3771 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak) 3772 return; 3773 case CSSPropertyPageBreakInside: { 3774 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak) 3775 if (!primitiveValue) 3776 return; 3777 EPageBreak pageBreak = *primitiveValue; 3778 if (pageBreak != PBALWAYS) 3779 m_style->setPageBreakInside(pageBreak); 3780 return; 3781 } 3782 3783 case CSSPropertyPosition: 3784 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position) 3785 return; 3786 case CSSPropertyTableLayout: { 3787 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout) 3788 3789 ETableLayout l = *primitiveValue; 3790 if (l == TAUTO) 3791 l = RenderStyle::initialTableLayout(); 3792 3793 m_style->setTableLayout(l); 3794 return; 3795 } 3796 3797 case CSSPropertyUnicodeBidi: 3798 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi) 3799 return; 3800 case CSSPropertyTextTransform: 3801 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform) 3802 return; 3803 case CSSPropertyVisibility: 3804 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility) 3805 return; 3806 case CSSPropertyWhiteSpace: 3807 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace) 3808 return; 3809 case CSSPropertyBorderSpacing: { 3810 if (isInherit) { 3811 m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing()); 3812 m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing()); 3813 } 3814 else if (isInitial) { 3815 m_style->setHorizontalBorderSpacing(0); 3816 m_style->setVerticalBorderSpacing(0); 3817 } 3818 return; 3819 } 3820 case CSSPropertyWebkitBorderHorizontalSpacing: { 3821 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing) 3822 if (!primitiveValue) 3823 return; 3824 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); 3825 m_style->setHorizontalBorderSpacing(spacing); 3826 return; 3827 } 3828 case CSSPropertyWebkitBorderVerticalSpacing: { 3829 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing) 3830 if (!primitiveValue) 3831 return; 3832 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); 3833 m_style->setVerticalBorderSpacing(spacing); 3834 return; 3835 } 3836 case CSSPropertyCursor: 3837 if (isInherit) { 3838 m_style->setCursor(m_parentStyle->cursor()); 3839 m_style->setCursorList(m_parentStyle->cursors()); 3840 return; 3841 } 3842 m_style->clearCursorList(); 3843 if (isInitial) { 3844 m_style->setCursor(RenderStyle::initialCursor()); 3845 return; 3846 } 3847 if (value->isValueList()) { 3848 CSSValueList* list = static_cast<CSSValueList*>(value); 3849 int len = list->length(); 3850 m_style->setCursor(CURSOR_AUTO); 3851 for (int i = 0; i < len; i++) { 3852 CSSValue* item = list->itemWithoutBoundsCheck(i); 3853 if (!item->isPrimitiveValue()) 3854 continue; 3855 primitiveValue = static_cast<CSSPrimitiveValue*>(item); 3856 int type = primitiveValue->primitiveType(); 3857 if (type == CSSPrimitiveValue::CSS_URI) { 3858 if (primitiveValue->isCursorImageValue()) { 3859 CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue); 3860 if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style. 3861 m_style->setUnique(); 3862 m_style->addCursor(cachedOrPendingFromValue(CSSPropertyCursor, image), image->hotSpot()); 3863 } 3864 } else if (type == CSSPrimitiveValue::CSS_IDENT) 3865 m_style->setCursor(*primitiveValue); 3866 } 3867 } else if (primitiveValue) { 3868 int type = primitiveValue->primitiveType(); 3869 if (type == CSSPrimitiveValue::CSS_IDENT && m_style->cursor() != ECursor(*primitiveValue)) 3870 m_style->setCursor(*primitiveValue); 3871 } 3872 return; 3873 3874// uri || inherit 3875 case CSSPropertyListStyleImage: 3876 { 3877 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) 3878 m_style->setListStyleImage(styleImage(CSSPropertyListStyleImage, value)); 3879 return; 3880 } 3881 3882// length 3883 case CSSPropertyBorderTopWidth: 3884 case CSSPropertyBorderRightWidth: 3885 case CSSPropertyBorderBottomWidth: 3886 case CSSPropertyBorderLeftWidth: 3887 case CSSPropertyOutlineWidth: 3888 case CSSPropertyWebkitColumnRuleWidth: 3889 { 3890 if (isInherit) { 3891 HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth) 3892 HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth) 3893 HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth) 3894 HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth) 3895 HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth) 3896 HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth) 3897 return; 3898 } 3899 else if (isInitial) { 3900 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth) 3901 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth) 3902 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth) 3903 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth) 3904 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth) 3905 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth) 3906 return; 3907 } 3908 3909 if (!primitiveValue) 3910 return; 3911 short width = 3; 3912 switch (primitiveValue->getIdent()) { 3913 case CSSValueThin: 3914 width = 1; 3915 break; 3916 case CSSValueMedium: 3917 width = 3; 3918 break; 3919 case CSSValueThick: 3920 width = 5; 3921 break; 3922 case CSSValueInvalid: 3923 width = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor); 3924 break; 3925 default: 3926 return; 3927 } 3928 3929 if (width < 0) return; 3930 switch (id) { 3931 case CSSPropertyBorderTopWidth: 3932 m_style->setBorderTopWidth(width); 3933 break; 3934 case CSSPropertyBorderRightWidth: 3935 m_style->setBorderRightWidth(width); 3936 break; 3937 case CSSPropertyBorderBottomWidth: 3938 m_style->setBorderBottomWidth(width); 3939 break; 3940 case CSSPropertyBorderLeftWidth: 3941 m_style->setBorderLeftWidth(width); 3942 break; 3943 case CSSPropertyOutlineWidth: 3944 m_style->setOutlineWidth(width); 3945 break; 3946 case CSSPropertyWebkitColumnRuleWidth: 3947 m_style->setColumnRuleWidth(width); 3948 break; 3949 default: 3950 return; 3951 } 3952 return; 3953 } 3954 3955 case CSSPropertyWebkitFontSmoothing: { 3956 FontDescription fontDescription = m_style->fontDescription(); 3957 if (isInherit) 3958 fontDescription.setFontSmoothing(m_parentStyle->fontDescription().fontSmoothing()); 3959 else if (isInitial) 3960 fontDescription.setFontSmoothing(AutoSmoothing); 3961 else { 3962 if (!primitiveValue) 3963 return; 3964 int id = primitiveValue->getIdent(); 3965 FontSmoothingMode smoothing; 3966 switch (id) { 3967 case CSSValueAuto: 3968 smoothing = AutoSmoothing; 3969 break; 3970 case CSSValueNone: 3971 smoothing = NoSmoothing; 3972 break; 3973 case CSSValueAntialiased: 3974 smoothing = Antialiased; 3975 break; 3976 case CSSValueSubpixelAntialiased: 3977 smoothing = SubpixelAntialiased; 3978 break; 3979 default: 3980 ASSERT_NOT_REACHED(); 3981 smoothing = AutoSmoothing; 3982 } 3983 fontDescription.setFontSmoothing(smoothing); 3984 } 3985 if (m_style->setFontDescription(fontDescription)) 3986 m_fontDirty = true; 3987 return; 3988 } 3989 3990 case CSSPropertyLetterSpacing: 3991 case CSSPropertyWordSpacing: 3992 { 3993 if (isInherit) { 3994 HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing) 3995 HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing) 3996 return; 3997 } 3998 else if (isInitial) { 3999 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing) 4000 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing) 4001 return; 4002 } 4003 4004 int width = 0; 4005 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) { 4006 width = 0; 4007 } else { 4008 if (!primitiveValue) 4009 return; 4010 width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules(m_element) ? 1.0f : zoomFactor); 4011 } 4012 switch (id) { 4013 case CSSPropertyLetterSpacing: 4014 m_style->setLetterSpacing(width); 4015 break; 4016 case CSSPropertyWordSpacing: 4017 m_style->setWordSpacing(width); 4018 break; 4019 // ### needs the definitions in renderstyle 4020 default: break; 4021 } 4022 return; 4023 } 4024 4025 case CSSPropertyWordBreak: 4026 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak) 4027 return; 4028 case CSSPropertyWordWrap: 4029 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap) 4030 return; 4031 case CSSPropertyWebkitNbspMode: 4032 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode) 4033 return; 4034 case CSSPropertyWebkitLineBreak: 4035 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak) 4036 return; 4037 case CSSPropertyWebkitMatchNearestMailBlockquoteColor: 4038 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor) 4039 return; 4040 4041 case CSSPropertyResize: 4042 { 4043 HANDLE_INHERIT_AND_INITIAL(resize, Resize) 4044 4045 if (!primitiveValue->getIdent()) 4046 return; 4047 4048 EResize r = RESIZE_NONE; 4049 if (primitiveValue->getIdent() == CSSValueAuto) { 4050 if (Settings* settings = m_checker.m_document->settings()) 4051 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; 4052 } else 4053 r = *primitiveValue; 4054 4055 m_style->setResize(r); 4056 return; 4057 } 4058 4059 // length, percent 4060 case CSSPropertyMaxWidth: 4061 // +none +inherit 4062 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { 4063 l = Length(undefinedLength, Fixed); 4064 apply = true; 4065 } 4066 case CSSPropertyTop: 4067 case CSSPropertyLeft: 4068 case CSSPropertyRight: 4069 case CSSPropertyBottom: 4070 case CSSPropertyWidth: 4071 case CSSPropertyMinWidth: 4072 case CSSPropertyMarginTop: 4073 case CSSPropertyMarginRight: 4074 case CSSPropertyMarginBottom: 4075 case CSSPropertyMarginLeft: 4076 // +inherit +auto 4077 if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) { 4078 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) { 4079 l = Length(Intrinsic); 4080 apply = true; 4081 } 4082 else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) { 4083 l = Length(MinIntrinsic); 4084 apply = true; 4085 } 4086 } 4087 if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto) 4088 apply = true; 4089 case CSSPropertyPaddingTop: 4090 case CSSPropertyPaddingRight: 4091 case CSSPropertyPaddingBottom: 4092 case CSSPropertyPaddingLeft: 4093 case CSSPropertyTextIndent: 4094 // +inherit 4095 { 4096 if (isInherit) { 4097 HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth) 4098 HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom) 4099 HANDLE_INHERIT_COND(CSSPropertyTop, top, Top) 4100 HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left) 4101 HANDLE_INHERIT_COND(CSSPropertyRight, right, Right) 4102 HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width) 4103 HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth) 4104 HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop) 4105 HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight) 4106 HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom) 4107 HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft) 4108 HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop) 4109 HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight) 4110 HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom) 4111 HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft) 4112 HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent) 4113 return; 4114 } 4115 else if (isInitial) { 4116 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize) 4117 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset) 4118 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset) 4119 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset) 4120 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset) 4121 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size) 4122 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize) 4123 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding) 4124 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding) 4125 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding) 4126 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding) 4127 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin) 4128 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin) 4129 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin) 4130 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin) 4131 HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent) 4132 return; 4133 } 4134 4135 if (primitiveValue && !apply) { 4136 int type = primitiveValue->primitiveType(); 4137 if (CSSPrimitiveValue::isUnitTypeLength(type)) 4138 // Handle our quirky margin units if we have them. 4139 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed, 4140 primitiveValue->isQuirkValue()); 4141 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 4142 l = Length(primitiveValue->getDoubleValue(), Percent); 4143 else 4144 return; 4145 apply = true; 4146 } 4147 if (!apply) return; 4148 switch (id) { 4149 case CSSPropertyMaxWidth: 4150 m_style->setMaxWidth(l); 4151 break; 4152 case CSSPropertyBottom: 4153 m_style->setBottom(l); 4154 break; 4155 case CSSPropertyTop: 4156 m_style->setTop(l); 4157 break; 4158 case CSSPropertyLeft: 4159 m_style->setLeft(l); 4160 break; 4161 case CSSPropertyRight: 4162 m_style->setRight(l); 4163 break; 4164 case CSSPropertyWidth: 4165 m_style->setWidth(l); 4166 break; 4167 case CSSPropertyMinWidth: 4168 m_style->setMinWidth(l); 4169 break; 4170 case CSSPropertyPaddingTop: 4171 m_style->setPaddingTop(l); 4172 break; 4173 case CSSPropertyPaddingRight: 4174 m_style->setPaddingRight(l); 4175 break; 4176 case CSSPropertyPaddingBottom: 4177 m_style->setPaddingBottom(l); 4178 break; 4179 case CSSPropertyPaddingLeft: 4180 m_style->setPaddingLeft(l); 4181 break; 4182 case CSSPropertyMarginTop: 4183 m_style->setMarginTop(l); 4184 break; 4185 case CSSPropertyMarginRight: 4186 m_style->setMarginRight(l); 4187 break; 4188 case CSSPropertyMarginBottom: 4189 m_style->setMarginBottom(l); 4190 break; 4191 case CSSPropertyMarginLeft: 4192 m_style->setMarginLeft(l); 4193 break; 4194 case CSSPropertyTextIndent: 4195 m_style->setTextIndent(l); 4196 break; 4197 default: 4198 break; 4199 } 4200 return; 4201 } 4202 4203 case CSSPropertyMaxHeight: 4204 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { 4205 l = Length(undefinedLength, Fixed); 4206 apply = true; 4207 } 4208 case CSSPropertyHeight: 4209 case CSSPropertyMinHeight: 4210 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) { 4211 l = Length(Intrinsic); 4212 apply = true; 4213 } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) { 4214 l = Length(MinIntrinsic); 4215 apply = true; 4216 } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto) 4217 apply = true; 4218 if (isInherit) { 4219 HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight) 4220 HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height) 4221 HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight) 4222 return; 4223 } 4224 if (isInitial) { 4225 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize) 4226 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size) 4227 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize) 4228 return; 4229 } 4230 4231 if (primitiveValue && !apply) { 4232 unsigned short type = primitiveValue->primitiveType(); 4233 if (CSSPrimitiveValue::isUnitTypeLength(type)) 4234 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 4235 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 4236 l = Length(primitiveValue->getDoubleValue(), Percent); 4237 else 4238 return; 4239 apply = true; 4240 } 4241 if (apply) 4242 switch (id) { 4243 case CSSPropertyMaxHeight: 4244 m_style->setMaxHeight(l); 4245 break; 4246 case CSSPropertyHeight: 4247 m_style->setHeight(l); 4248 break; 4249 case CSSPropertyMinHeight: 4250 m_style->setMinHeight(l); 4251 break; 4252 } 4253 return; 4254 4255 case CSSPropertyVerticalAlign: 4256 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign) 4257 if (!primitiveValue) 4258 return; 4259 if (primitiveValue->getIdent()) { 4260 EVerticalAlign align; 4261 4262 switch (primitiveValue->getIdent()) { 4263 case CSSValueTop: 4264 align = TOP; break; 4265 case CSSValueBottom: 4266 align = BOTTOM; break; 4267 case CSSValueMiddle: 4268 align = MIDDLE; break; 4269 case CSSValueBaseline: 4270 align = BASELINE; break; 4271 case CSSValueTextBottom: 4272 align = TEXT_BOTTOM; break; 4273 case CSSValueTextTop: 4274 align = TEXT_TOP; break; 4275 case CSSValueSub: 4276 align = SUB; break; 4277 case CSSValueSuper: 4278 align = SUPER; break; 4279 case CSSValueWebkitBaselineMiddle: 4280 align = BASELINE_MIDDLE; break; 4281 default: 4282 return; 4283 } 4284 m_style->setVerticalAlign(align); 4285 return; 4286 } else { 4287 int type = primitiveValue->primitiveType(); 4288 Length l; 4289 if (CSSPrimitiveValue::isUnitTypeLength(type)) 4290 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 4291 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 4292 l = Length(primitiveValue->getDoubleValue(), Percent); 4293 4294 m_style->setVerticalAlign(LENGTH); 4295 m_style->setVerticalAlignLength(l); 4296 } 4297 return; 4298 4299 case CSSPropertyFontSize: 4300 { 4301 FontDescription fontDescription = m_style->fontDescription(); 4302 fontDescription.setKeywordSize(0); 4303 float oldSize = 0; 4304 float size = 0; 4305 4306 bool parentIsAbsoluteSize = false; 4307 if (m_parentNode) { 4308 oldSize = m_parentStyle->fontDescription().specifiedSize(); 4309 parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize(); 4310 } 4311 4312 if (isInherit) { 4313 size = oldSize; 4314 if (m_parentNode) 4315 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize()); 4316 } else if (isInitial) { 4317 size = fontSizeForKeyword(m_checker.m_document, CSSValueMedium, fontDescription.useFixedDefaultSize()); 4318 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); 4319 } else if (primitiveValue->getIdent()) { 4320 // Keywords are being used. 4321 switch (primitiveValue->getIdent()) { 4322 case CSSValueXxSmall: 4323 case CSSValueXSmall: 4324 case CSSValueSmall: 4325 case CSSValueMedium: 4326 case CSSValueLarge: 4327 case CSSValueXLarge: 4328 case CSSValueXxLarge: 4329 case CSSValueWebkitXxxLarge: 4330 size = fontSizeForKeyword(m_checker.m_document, primitiveValue->getIdent(), fontDescription.useFixedDefaultSize()); 4331 fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1); 4332 break; 4333 case CSSValueLarger: 4334 size = largerFontSize(oldSize, m_checker.m_document->inQuirksMode()); 4335 break; 4336 case CSSValueSmaller: 4337 size = smallerFontSize(oldSize, m_checker.m_document->inQuirksMode()); 4338 break; 4339 default: 4340 return; 4341 } 4342 4343 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && 4344 (primitiveValue->getIdent() == CSSValueLarger || 4345 primitiveValue->getIdent() == CSSValueSmaller)); 4346 } else { 4347 int type = primitiveValue->primitiveType(); 4348 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || 4349 (type != CSSPrimitiveValue::CSS_PERCENTAGE && 4350 type != CSSPrimitiveValue::CSS_EMS && 4351 type != CSSPrimitiveValue::CSS_EXS && 4352 type != CSSPrimitiveValue::CSS_REMS)); 4353 if (CSSPrimitiveValue::isUnitTypeLength(type)) 4354 size = primitiveValue->computeLengthFloat(m_parentStyle, m_rootElementStyle, true); 4355 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 4356 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f; 4357 else 4358 return; 4359 } 4360 4361 if (size < 0) 4362 return; 4363 4364 setFontSize(fontDescription, size); 4365 if (m_style->setFontDescription(fontDescription)) 4366 m_fontDirty = true; 4367 return; 4368 } 4369 4370 case CSSPropertyZIndex: { 4371 if (isInherit) { 4372 if (m_parentStyle->hasAutoZIndex()) 4373 m_style->setHasAutoZIndex(); 4374 else 4375 m_style->setZIndex(m_parentStyle->zIndex()); 4376 return; 4377 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { 4378 m_style->setHasAutoZIndex(); 4379 return; 4380 } 4381 4382 // FIXME: Should clamp all sorts of other integer properties too. 4383 m_style->setZIndex(clampToInteger(primitiveValue->getDoubleValue())); 4384 return; 4385 } 4386 case CSSPropertyWidows: 4387 { 4388 HANDLE_INHERIT_AND_INITIAL(widows, Widows) 4389 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 4390 return; 4391 m_style->setWidows(primitiveValue->getIntValue()); 4392 return; 4393 } 4394 4395 case CSSPropertyOrphans: 4396 { 4397 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans) 4398 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 4399 return; 4400 m_style->setOrphans(primitiveValue->getIntValue()); 4401 return; 4402 } 4403 4404// length, percent, number 4405 case CSSPropertyLineHeight: 4406 { 4407 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight) 4408 if (!primitiveValue) 4409 return; 4410 Length lineHeight; 4411 int type = primitiveValue->primitiveType(); 4412 if (primitiveValue->getIdent() == CSSValueNormal) 4413 lineHeight = Length(-100.0, Percent); 4414 else if (CSSPrimitiveValue::isUnitTypeLength(type)) { 4415 double multiplier = zoomFactor; 4416 if (m_style->textSizeAdjust()) { 4417 if (Frame* frame = m_checker.m_document->frame()) 4418 multiplier *= frame->textZoomFactor(); 4419 } 4420 lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, multiplier), Fixed); 4421 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 4422 lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed); 4423 else if (type == CSSPrimitiveValue::CSS_NUMBER) 4424 lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); 4425 else 4426 return; 4427 m_style->setLineHeight(lineHeight); 4428 return; 4429 } 4430 4431// string 4432 case CSSPropertyTextAlign: 4433 { 4434 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) 4435 if (!primitiveValue) 4436 return; 4437 if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) { 4438 if (m_parentStyle->textAlign() == TASTART) 4439 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT); 4440 else if (m_parentStyle->textAlign() == TAEND) 4441 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT); 4442 else 4443 m_style->setTextAlign(m_parentStyle->textAlign()); 4444 return; 4445 } 4446 m_style->setTextAlign(*primitiveValue); 4447 return; 4448 } 4449 4450// rect 4451 case CSSPropertyClip: 4452 { 4453 Length top; 4454 Length right; 4455 Length bottom; 4456 Length left; 4457 bool hasClip = true; 4458 if (isInherit) { 4459 if (m_parentStyle->hasClip()) { 4460 top = m_parentStyle->clipTop(); 4461 right = m_parentStyle->clipRight(); 4462 bottom = m_parentStyle->clipBottom(); 4463 left = m_parentStyle->clipLeft(); 4464 } else { 4465 hasClip = false; 4466 top = right = bottom = left = Length(); 4467 } 4468 } else if (isInitial) { 4469 hasClip = false; 4470 top = right = bottom = left = Length(); 4471 } else if (!primitiveValue) { 4472 return; 4473 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { 4474 Rect* rect = primitiveValue->getRectValue(); 4475 if (!rect) 4476 return; 4477 top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor); 4478 right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor); 4479 bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor); 4480 left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor); 4481 } else if (primitiveValue->getIdent() != CSSValueAuto) { 4482 return; 4483 } 4484 m_style->setClip(top, right, bottom, left); 4485 m_style->setHasClip(hasClip); 4486 4487 // rect, ident 4488 return; 4489 } 4490 4491// lists 4492 case CSSPropertyContent: 4493 // list of string, uri, counter, attr, i 4494 { 4495 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This 4496 // note is a reminder that eventually "inherit" needs to be supported. 4497 4498 if (isInitial) { 4499 m_style->clearContent(); 4500 return; 4501 } 4502 4503 if (!value->isValueList()) 4504 return; 4505 4506 CSSValueList* list = static_cast<CSSValueList*>(value); 4507 int len = list->length(); 4508 4509 bool didSet = false; 4510 for (int i = 0; i < len; i++) { 4511 CSSValue* item = list->itemWithoutBoundsCheck(i); 4512 if (item->isImageGeneratorValue()) { 4513 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet); 4514 didSet = true; 4515 } 4516 4517 if (!item->isPrimitiveValue()) 4518 continue; 4519 4520 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item); 4521 switch (contentValue->primitiveType()) { 4522 case CSSPrimitiveValue::CSS_STRING: 4523 m_style->setContent(contentValue->getStringValue().impl(), didSet); 4524 didSet = true; 4525 break; 4526 case CSSPrimitiveValue::CSS_ATTR: { 4527 // FIXME: Can a namespace be specified for an attr(foo)? 4528 if (m_style->styleType() == NOPSEUDO) 4529 m_style->setUnique(); 4530 else 4531 m_parentStyle->setUnique(); 4532 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom); 4533 m_style->setContent(m_element->getAttribute(attr).impl(), didSet); 4534 didSet = true; 4535 // register the fact that the attribute value affects the style 4536 m_selectorAttrs.add(attr.localName().impl()); 4537 break; 4538 } 4539 case CSSPrimitiveValue::CSS_URI: { 4540 if (!contentValue->isImageValue()) 4541 break; 4542 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet); 4543 didSet = true; 4544 break; 4545 } 4546 case CSSPrimitiveValue::CSS_COUNTER: { 4547 Counter* counterValue = contentValue->getCounterValue(); 4548 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), 4549 (EListStyleType)counterValue->listStyleNumber(), counterValue->separator())); 4550 m_style->setContent(counter.release(), didSet); 4551 didSet = true; 4552 break; 4553 } 4554 case CSSPrimitiveValue::CSS_IDENT: 4555 switch (contentValue->getIdent()) { 4556 case CSSValueOpenQuote: 4557 m_style->setContent(OPEN_QUOTE, didSet); 4558 didSet = true; 4559 break; 4560 case CSSValueCloseQuote: 4561 m_style->setContent(CLOSE_QUOTE, didSet); 4562 didSet = true; 4563 break; 4564 case CSSValueNoOpenQuote: 4565 m_style->setContent(NO_OPEN_QUOTE, didSet); 4566 didSet = true; 4567 break; 4568 case CSSValueNoCloseQuote: 4569 m_style->setContent(NO_CLOSE_QUOTE, didSet); 4570 didSet = true; 4571 break; 4572 default: 4573 // normal and none do not have any effect. 4574 {} 4575 } 4576 } 4577 } 4578 if (!didSet) 4579 m_style->clearContent(); 4580 return; 4581 } 4582 case CSSPropertyQuotes: 4583 if (isInherit) { 4584 if (m_parentStyle) 4585 m_style->setQuotes(m_parentStyle->quotes()); 4586 return; 4587 } 4588 if (isInitial) { 4589 m_style->setQuotes(0); 4590 return; 4591 } 4592 if (value->isValueList()) { 4593 CSSValueList* list = static_cast<CSSValueList*>(value); 4594 size_t length = list->length(); 4595 QuotesData* data = QuotesData::create(length); 4596 if (!data) 4597 return; // Out of memory 4598 String* quotes = data->data(); 4599 for (size_t i = 0; i < length; i++) { 4600 CSSValue* item = list->itemWithoutBoundsCheck(i); 4601 ASSERT(item->isPrimitiveValue()); 4602 primitiveValue = static_cast<CSSPrimitiveValue*>(item); 4603 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING); 4604 quotes[i] = primitiveValue->getStringValue(); 4605 } 4606 m_style->setQuotes(adoptRef(data)); 4607 } else if (primitiveValue) { 4608 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT); 4609 if (primitiveValue->getIdent() == CSSValueNone) 4610 m_style->setQuotes(adoptRef(QuotesData::create(0))); 4611 } 4612 return; 4613 4614 case CSSPropertyCounterIncrement: 4615 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false); 4616 return; 4617 case CSSPropertyCounterReset: 4618 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true); 4619 return; 4620 4621 case CSSPropertyFontFamily: { 4622 // list of strings and ids 4623 if (isInherit) { 4624 FontDescription parentFontDescription = m_parentStyle->fontDescription(); 4625 FontDescription fontDescription = m_style->fontDescription(); 4626 fontDescription.setGenericFamily(parentFontDescription.genericFamily()); 4627 fontDescription.setFamily(parentFontDescription.firstFamily()); 4628 fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont()); 4629 if (m_style->setFontDescription(fontDescription)) 4630 m_fontDirty = true; 4631 return; 4632 } else if (isInitial) { 4633 FontDescription initialDesc = FontDescription(); 4634 FontDescription fontDescription = m_style->fontDescription(); 4635 // We need to adjust the size to account for the generic family change from monospace 4636 // to non-monospace. 4637 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize()) 4638 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, false)); 4639 fontDescription.setGenericFamily(initialDesc.genericFamily()); 4640 if (!initialDesc.firstFamily().familyIsEmpty()) 4641 fontDescription.setFamily(initialDesc.firstFamily()); 4642 if (m_style->setFontDescription(fontDescription)) 4643 m_fontDirty = true; 4644 return; 4645 } 4646 4647 if (!value->isValueList()) 4648 return; 4649 FontDescription fontDescription = m_style->fontDescription(); 4650 CSSValueList* list = static_cast<CSSValueList*>(value); 4651 int len = list->length(); 4652 FontFamily& firstFamily = fontDescription.firstFamily(); 4653 FontFamily* currFamily = 0; 4654 4655 // Before mapping in a new font-family property, we should reset the generic family. 4656 bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize(); 4657 fontDescription.setGenericFamily(FontDescription::NoFamily); 4658 4659 for (int i = 0; i < len; i++) { 4660 CSSValue* item = list->itemWithoutBoundsCheck(i); 4661 if (!item->isPrimitiveValue()) 4662 continue; 4663 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item); 4664 AtomicString face; 4665 Settings* settings = m_checker.m_document->settings(); 4666 if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) { 4667 if (contentValue->isFontFamilyValue()) 4668 face = static_cast<FontFamilyValue*>(contentValue)->familyName(); 4669 } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) { 4670 switch (contentValue->getIdent()) { 4671 case CSSValueWebkitBody: 4672 face = settings->standardFontFamily(); 4673 break; 4674 case CSSValueSerif: 4675 face = "-webkit-serif"; 4676 fontDescription.setGenericFamily(FontDescription::SerifFamily); 4677 break; 4678 case CSSValueSansSerif: 4679 face = "-webkit-sans-serif"; 4680 fontDescription.setGenericFamily(FontDescription::SansSerifFamily); 4681 break; 4682 case CSSValueCursive: 4683 face = "-webkit-cursive"; 4684 fontDescription.setGenericFamily(FontDescription::CursiveFamily); 4685 break; 4686 case CSSValueFantasy: 4687 face = "-webkit-fantasy"; 4688 fontDescription.setGenericFamily(FontDescription::FantasyFamily); 4689 break; 4690 case CSSValueMonospace: 4691 face = "-webkit-monospace"; 4692 fontDescription.setGenericFamily(FontDescription::MonospaceFamily); 4693 break; 4694 } 4695 } 4696 4697 if (!face.isEmpty()) { 4698 if (!currFamily) { 4699 // Filling in the first family. 4700 firstFamily.setFamily(face); 4701 firstFamily.appendFamily(0); // Remove any inherited family-fallback list. 4702 currFamily = &firstFamily; 4703 fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily); 4704 } else { 4705 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); 4706 newFamily->setFamily(face); 4707 currFamily->appendFamily(newFamily); 4708 currFamily = newFamily.get(); 4709 } 4710 } 4711 } 4712 4713 // We can't call useFixedDefaultSize() until all new font families have been added 4714 // If currFamily is non-zero then we set at least one family on this description. 4715 if (currFamily) { 4716 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) 4717 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize)); 4718 4719 if (m_style->setFontDescription(fontDescription)) 4720 m_fontDirty = true; 4721 } 4722 return; 4723 } 4724 case CSSPropertyTextDecoration: { 4725 // list of ident 4726 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration) 4727 int t = RenderStyle::initialTextDecoration(); 4728 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { 4729 // do nothing 4730 } else { 4731 if (!value->isValueList()) 4732 return; 4733 CSSValueList *list = static_cast<CSSValueList*>(value); 4734 int len = list->length(); 4735 for (int i = 0; i < len; i++) 4736 { 4737 CSSValue *item = list->itemWithoutBoundsCheck(i); 4738 if (!item->isPrimitiveValue()) 4739 continue; 4740 primitiveValue = static_cast<CSSPrimitiveValue*>(item); 4741 switch (primitiveValue->getIdent()) { 4742 case CSSValueNone: 4743 t = TDNONE; break; 4744 case CSSValueUnderline: 4745 t |= UNDERLINE; break; 4746 case CSSValueOverline: 4747 t |= OVERLINE; break; 4748 case CSSValueLineThrough: 4749 t |= LINE_THROUGH; break; 4750 case CSSValueBlink: 4751 t |= BLINK; break; 4752 default: 4753 return; 4754 } 4755 } 4756 } 4757 4758 m_style->setTextDecoration(t); 4759 return; 4760 } 4761 4762 case CSSPropertyZoom: 4763 { 4764 // Reset the zoom in effect before we do anything. This allows the setZoom method to accurately compute a new 4765 // zoom in effect. 4766 m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom()); 4767 4768 // Now we can handle inherit and initial. 4769 HANDLE_INHERIT_AND_INITIAL(zoom, Zoom) 4770 4771 // Handle normal/reset, numbers and percentages. 4772 int type = primitiveValue->primitiveType(); 4773 if (primitiveValue->getIdent() == CSSValueNormal) 4774 m_style->setZoom(RenderStyle::initialZoom()); 4775 else if (primitiveValue->getIdent() == CSSValueReset) { 4776 m_style->setEffectiveZoom(RenderStyle::initialZoom()); 4777 m_style->setZoom(RenderStyle::initialZoom()); 4778 } else if (primitiveValue->getIdent() == CSSValueDocument) { 4779 float docZoom = m_checker.m_document->renderer()->style()->zoom(); 4780 m_style->setEffectiveZoom(docZoom); 4781 m_style->setZoom(docZoom); 4782 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) { 4783 if (primitiveValue->getFloatValue()) 4784 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f); 4785 } else if (type == CSSPrimitiveValue::CSS_NUMBER) { 4786 if (primitiveValue->getFloatValue()) 4787 m_style->setZoom(primitiveValue->getFloatValue()); 4788 } 4789 4790 m_fontDirty = true; 4791 return; 4792 } 4793// shorthand properties 4794 case CSSPropertyBackground: 4795 if (isInitial) { 4796 m_style->clearBackgroundLayers(); 4797 m_style->setBackgroundColor(Color()); 4798 } 4799 else if (isInherit) { 4800 m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers()); 4801 m_style->setBackgroundColor(m_parentStyle->backgroundColor()); 4802 } 4803 return; 4804 case CSSPropertyWebkitMask: 4805 if (isInitial) 4806 m_style->clearMaskLayers(); 4807 else if (isInherit) 4808 m_style->inheritMaskLayers(*m_parentStyle->maskLayers()); 4809 return; 4810 4811 case CSSPropertyBorder: 4812 case CSSPropertyBorderStyle: 4813 case CSSPropertyBorderWidth: 4814 case CSSPropertyBorderColor: 4815 if (id == CSSPropertyBorder || id == CSSPropertyBorderColor) 4816 { 4817 if (isInherit) { 4818 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color()); 4819 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color()); 4820 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color()); 4821 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color()); 4822 } 4823 else if (isInitial) { 4824 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead. 4825 m_style->setBorderBottomColor(Color()); 4826 m_style->setBorderLeftColor(Color()); 4827 m_style->setBorderRightColor(Color()); 4828 } 4829 } 4830 if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle) 4831 { 4832 if (isInherit) { 4833 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); 4834 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); 4835 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); 4836 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); 4837 } 4838 else if (isInitial) { 4839 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle()); 4840 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); 4841 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); 4842 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle()); 4843 } 4844 } 4845 if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth) 4846 { 4847 if (isInherit) { 4848 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); 4849 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); 4850 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); 4851 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); 4852 } 4853 else if (isInitial) { 4854 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth()); 4855 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); 4856 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); 4857 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth()); 4858 } 4859 } 4860 return; 4861 case CSSPropertyBorderTop: 4862 if (isInherit) { 4863 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color()); 4864 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); 4865 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); 4866 } 4867 else if (isInitial) 4868 m_style->resetBorderTop(); 4869 return; 4870 case CSSPropertyBorderRight: 4871 if (isInherit) { 4872 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color()); 4873 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); 4874 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); 4875 } 4876 else if (isInitial) 4877 m_style->resetBorderRight(); 4878 return; 4879 case CSSPropertyBorderBottom: 4880 if (isInherit) { 4881 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color()); 4882 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); 4883 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); 4884 } 4885 else if (isInitial) 4886 m_style->resetBorderBottom(); 4887 return; 4888 case CSSPropertyBorderLeft: 4889 if (isInherit) { 4890 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color()); 4891 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); 4892 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); 4893 } 4894 else if (isInitial) 4895 m_style->resetBorderLeft(); 4896 return; 4897 case CSSPropertyMargin: 4898 if (isInherit) { 4899 m_style->setMarginTop(m_parentStyle->marginTop()); 4900 m_style->setMarginBottom(m_parentStyle->marginBottom()); 4901 m_style->setMarginLeft(m_parentStyle->marginLeft()); 4902 m_style->setMarginRight(m_parentStyle->marginRight()); 4903 } 4904 else if (isInitial) 4905 m_style->resetMargin(); 4906 return; 4907 case CSSPropertyPadding: 4908 if (isInherit) { 4909 m_style->setPaddingTop(m_parentStyle->paddingTop()); 4910 m_style->setPaddingBottom(m_parentStyle->paddingBottom()); 4911 m_style->setPaddingLeft(m_parentStyle->paddingLeft()); 4912 m_style->setPaddingRight(m_parentStyle->paddingRight()); 4913 } 4914 else if (isInitial) 4915 m_style->resetPadding(); 4916 return; 4917 case CSSPropertyFont: 4918 if (isInherit) { 4919 FontDescription fontDescription = m_parentStyle->fontDescription(); 4920 m_style->setLineHeight(m_parentStyle->lineHeight()); 4921 m_lineHeightValue = 0; 4922 if (m_style->setFontDescription(fontDescription)) 4923 m_fontDirty = true; 4924 } else if (isInitial) { 4925 Settings* settings = m_checker.m_document->settings(); 4926 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings 4927 if (!settings) 4928 return; 4929 FontDescription fontDescription; 4930 fontDescription.setGenericFamily(FontDescription::StandardFamily); 4931 fontDescription.setRenderingMode(settings->fontRenderingMode()); 4932 fontDescription.setUsePrinterFont(m_checker.m_document->printing()); 4933 const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily(); 4934 if (!standardFontFamily.isEmpty()) { 4935 fontDescription.firstFamily().setFamily(standardFontFamily); 4936 fontDescription.firstFamily().appendFamily(0); 4937 } 4938 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); 4939 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueMedium, false)); 4940 m_style->setLineHeight(RenderStyle::initialLineHeight()); 4941 m_lineHeightValue = 0; 4942 if (m_style->setFontDescription(fontDescription)) 4943 m_fontDirty = true; 4944 } else if (primitiveValue) { 4945 m_style->setLineHeight(RenderStyle::initialLineHeight()); 4946 m_lineHeightValue = 0; 4947 4948 FontDescription fontDescription; 4949 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription); 4950 4951 // Double-check and see if the theme did anything. If not, don't bother updating the font. 4952 if (fontDescription.isAbsoluteSize()) { 4953 // Make sure the rendering mode and printer font settings are updated. 4954 Settings* settings = m_checker.m_document->settings(); 4955 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings 4956 if (!settings) 4957 return; 4958 fontDescription.setRenderingMode(settings->fontRenderingMode()); 4959 fontDescription.setUsePrinterFont(m_checker.m_document->printing()); 4960 4961 // Handle the zoom factor. 4962 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules(m_element))); 4963 if (m_style->setFontDescription(fontDescription)) 4964 m_fontDirty = true; 4965 } 4966 } else if (value->isFontValue()) { 4967 FontValue *font = static_cast<FontValue*>(value); 4968 if (!font->style || !font->variant || !font->weight || 4969 !font->size || !font->lineHeight || !font->family) 4970 return; 4971 applyProperty(CSSPropertyFontStyle, font->style.get()); 4972 applyProperty(CSSPropertyFontVariant, font->variant.get()); 4973 applyProperty(CSSPropertyFontWeight, font->weight.get()); 4974 // The previous properties can dirty our font but they don't try to read the font's 4975 // properties back, which is safe. However if font-size is using the 'ex' unit, it will 4976 // need query the dirtied font's x-height to get the computed size. To be safe in this 4977 // case, let's just update the font now. 4978 updateFont(); 4979 applyProperty(CSSPropertyFontSize, font->size.get()); 4980 4981 m_lineHeightValue = font->lineHeight.get(); 4982 4983 applyProperty(CSSPropertyFontFamily, font->family.get()); 4984 } 4985 return; 4986 4987 case CSSPropertyListStyle: 4988 if (isInherit) { 4989 m_style->setListStyleType(m_parentStyle->listStyleType()); 4990 m_style->setListStyleImage(m_parentStyle->listStyleImage()); 4991 m_style->setListStylePosition(m_parentStyle->listStylePosition()); 4992 } 4993 else if (isInitial) { 4994 m_style->setListStyleType(RenderStyle::initialListStyleType()); 4995 m_style->setListStyleImage(RenderStyle::initialListStyleImage()); 4996 m_style->setListStylePosition(RenderStyle::initialListStylePosition()); 4997 } 4998 return; 4999 case CSSPropertyOutline: 5000 if (isInherit) { 5001 m_style->setOutlineWidth(m_parentStyle->outlineWidth()); 5002 m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color()); 5003 m_style->setOutlineStyle(m_parentStyle->outlineStyle()); 5004 } 5005 else if (isInitial) 5006 m_style->resetOutline(); 5007 return; 5008 5009 // CSS3 Properties 5010 case CSSPropertyWebkitAppearance: { 5011 HANDLE_INHERIT_AND_INITIAL(appearance, Appearance) 5012 if (!primitiveValue) 5013 return; 5014 m_style->setAppearance(*primitiveValue); 5015 return; 5016 } 5017 5018 case CSSPropertyWebkitBorderImage: 5019 case CSSPropertyWebkitMaskBoxImage: { 5020 if (isInherit) { 5021 HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage) 5022 HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage) 5023 return; 5024 } else if (isInitial) { 5025 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage) 5026 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage) 5027 return; 5028 } 5029 5030 NinePieceImage image; 5031 mapNinePieceImage(property, value, image); 5032 5033 if (id == CSSPropertyWebkitBorderImage) 5034 m_style->setBorderImage(image); 5035 else 5036 m_style->setMaskBoxImage(image); 5037 return; 5038 } 5039 5040 case CSSPropertyBorderRadius: 5041 case CSSPropertyWebkitBorderRadius: 5042 if (isInherit) { 5043 m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius()); 5044 m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius()); 5045 m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius()); 5046 m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius()); 5047 return; 5048 } 5049 if (isInitial) { 5050 m_style->resetBorderRadius(); 5051 return; 5052 } 5053 // Fall through 5054 case CSSPropertyBorderTopLeftRadius: 5055 case CSSPropertyBorderTopRightRadius: 5056 case CSSPropertyBorderBottomLeftRadius: 5057 case CSSPropertyBorderBottomRightRadius: { 5058 if (isInherit) { 5059 HANDLE_INHERIT_COND(CSSPropertyBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius) 5060 HANDLE_INHERIT_COND(CSSPropertyBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius) 5061 HANDLE_INHERIT_COND(CSSPropertyBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius) 5062 HANDLE_INHERIT_COND(CSSPropertyBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius) 5063 return; 5064 } 5065 5066 if (isInitial) { 5067 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius) 5068 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopRightRadius, BorderTopRightRadius, BorderRadius) 5069 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius) 5070 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius) 5071 return; 5072 } 5073 5074 if (!primitiveValue) 5075 return; 5076 5077 Pair* pair = primitiveValue->getPairValue(); 5078 if (!pair || !pair->first() || !pair->second()) 5079 return; 5080 5081 Length radiusWidth; 5082 Length radiusHeight; 5083 if (pair->first()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 5084 radiusWidth = Length(pair->first()->getDoubleValue(), Percent); 5085 else 5086 radiusWidth = Length(max(intMinForLength, min(intMaxForLength, pair->first()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed); 5087 if (pair->second()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 5088 radiusHeight = Length(pair->second()->getDoubleValue(), Percent); 5089 else 5090 radiusHeight = Length(max(intMinForLength, min(intMaxForLength, pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed); 5091 int width = radiusWidth.value(); 5092 int height = radiusHeight.value(); 5093 if (width < 0 || height < 0) 5094 return; 5095 if (width == 0) 5096 radiusHeight = radiusWidth; // Null out the other value. 5097 else if (height == 0) 5098 radiusWidth = radiusHeight; // Null out the other value. 5099 5100 LengthSize size(radiusWidth, radiusHeight); 5101 switch (id) { 5102 case CSSPropertyBorderTopLeftRadius: 5103 m_style->setBorderTopLeftRadius(size); 5104 break; 5105 case CSSPropertyBorderTopRightRadius: 5106 m_style->setBorderTopRightRadius(size); 5107 break; 5108 case CSSPropertyBorderBottomLeftRadius: 5109 m_style->setBorderBottomLeftRadius(size); 5110 break; 5111 case CSSPropertyBorderBottomRightRadius: 5112 m_style->setBorderBottomRightRadius(size); 5113 break; 5114 default: 5115 m_style->setBorderRadius(size); 5116 break; 5117 } 5118 return; 5119 } 5120 5121 case CSSPropertyOutlineOffset: 5122 HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset) 5123 m_style->setOutlineOffset(primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor)); 5124 return; 5125 case CSSPropertyTextRendering: { 5126 FontDescription fontDescription = m_style->fontDescription(); 5127 if (isInherit) 5128 fontDescription.setTextRenderingMode(m_parentStyle->fontDescription().textRenderingMode()); 5129 else if (isInitial) 5130 fontDescription.setTextRenderingMode(AutoTextRendering); 5131 else { 5132 if (!primitiveValue) 5133 return; 5134 fontDescription.setTextRenderingMode(*primitiveValue); 5135 } 5136 if (m_style->setFontDescription(fontDescription)) 5137 m_fontDirty = true; 5138 return; 5139 } 5140 case CSSPropertyTextShadow: 5141 case CSSPropertyBoxShadow: 5142 case CSSPropertyWebkitBoxShadow: { 5143 if (isInherit) { 5144 if (id == CSSPropertyTextShadow) 5145 return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0); 5146 return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0); 5147 } 5148 if (isInitial || primitiveValue) // initial | none 5149 return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0); 5150 5151 if (!value->isValueList()) 5152 return; 5153 5154 CSSValueList *list = static_cast<CSSValueList*>(value); 5155 int len = list->length(); 5156 for (int i = 0; i < len; i++) { 5157 CSSValue* currValue = list->itemWithoutBoundsCheck(i); 5158 if (!currValue->isShadowValue()) 5159 continue; 5160 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i)); 5161 int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor); 5162 int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor); 5163 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; 5164 int spread = item->spread ? item->spread->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; 5165 ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal; 5166 Color color; 5167 if (item->color) 5168 color = getColorFromPrimitiveValue(item->color.get()); 5169 ShadowData* shadowData = new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent); 5170 if (id == CSSPropertyTextShadow) 5171 m_style->setTextShadow(shadowData, i != 0); 5172 else 5173 m_style->setBoxShadow(shadowData, i != 0); 5174 } 5175 return; 5176 } 5177 case CSSPropertyWebkitBoxReflect: { 5178 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect) 5179 if (primitiveValue) { 5180 m_style->setBoxReflect(RenderStyle::initialBoxReflect()); 5181 return; 5182 } 5183 5184 if (!value->isReflectValue()) 5185 return; 5186 5187 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value); 5188 RefPtr<StyleReflection> reflection = StyleReflection::create(); 5189 reflection->setDirection(reflectValue->direction()); 5190 if (reflectValue->offset()) { 5191 int type = reflectValue->offset()->primitiveType(); 5192 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5193 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent)); 5194 else 5195 reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed)); 5196 } 5197 NinePieceImage mask; 5198 mapNinePieceImage(property, reflectValue->mask(), mask); 5199 reflection->setMask(mask); 5200 5201 m_style->setBoxReflect(reflection.release()); 5202 return; 5203 } 5204 case CSSPropertyOpacity: 5205 HANDLE_INHERIT_AND_INITIAL(opacity, Opacity) 5206 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 5207 return; // Error case. 5208 // Clamp opacity to the range 0-1 5209 m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue()))); 5210 return; 5211 case CSSPropertyWebkitBoxAlign: 5212 { 5213 HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign) 5214 if (!primitiveValue) 5215 return; 5216 EBoxAlignment boxAlignment = *primitiveValue; 5217 if (boxAlignment != BJUSTIFY) 5218 m_style->setBoxAlign(boxAlignment); 5219 return; 5220 } 5221 case CSSPropertySrc: // Only used in @font-face rules. 5222 return; 5223 case CSSPropertyUnicodeRange: // Only used in @font-face rules. 5224 return; 5225 case CSSPropertyWebkitBackfaceVisibility: 5226 HANDLE_INHERIT_AND_INITIAL(backfaceVisibility, BackfaceVisibility) 5227 if (primitiveValue) 5228 m_style->setBackfaceVisibility((primitiveValue->getIdent() == CSSValueVisible) ? BackfaceVisibilityVisible : BackfaceVisibilityHidden); 5229 return; 5230 case CSSPropertyWebkitBoxDirection: 5231 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection) 5232 return; 5233 case CSSPropertyWebkitBoxLines: 5234 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines) 5235 return; 5236 case CSSPropertyWebkitBoxOrient: 5237 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient) 5238 return; 5239 case CSSPropertyWebkitBoxPack: 5240 { 5241 HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack) 5242 if (!primitiveValue) 5243 return; 5244 EBoxAlignment boxPack = *primitiveValue; 5245 if (boxPack != BSTRETCH && boxPack != BBASELINE) 5246 m_style->setBoxPack(boxPack); 5247 return; 5248 } 5249 case CSSPropertyWebkitBoxFlex: 5250 HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex) 5251 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 5252 return; // Error case. 5253 m_style->setBoxFlex(primitiveValue->getFloatValue()); 5254 return; 5255 case CSSPropertyWebkitBoxFlexGroup: 5256 HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup) 5257 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 5258 return; // Error case. 5259 m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue())); 5260 return; 5261 case CSSPropertyWebkitBoxOrdinalGroup: 5262 HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup) 5263 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 5264 return; // Error case. 5265 m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue())); 5266 return; 5267 case CSSPropertyBoxSizing: 5268 HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing) 5269 if (!primitiveValue) 5270 return; 5271 if (primitiveValue->getIdent() == CSSValueContentBox) 5272 m_style->setBoxSizing(CONTENT_BOX); 5273 else 5274 m_style->setBoxSizing(BORDER_BOX); 5275 return; 5276 case CSSPropertyWebkitColumnCount: { 5277 if (isInherit) { 5278 if (m_parentStyle->hasAutoColumnCount()) 5279 m_style->setHasAutoColumnCount(); 5280 else 5281 m_style->setColumnCount(m_parentStyle->columnCount()); 5282 return; 5283 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { 5284 m_style->setHasAutoColumnCount(); 5285 return; 5286 } 5287 m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue())); 5288 return; 5289 } 5290 case CSSPropertyWebkitColumnGap: { 5291 if (isInherit) { 5292 if (m_parentStyle->hasNormalColumnGap()) 5293 m_style->setHasNormalColumnGap(); 5294 else 5295 m_style->setColumnGap(m_parentStyle->columnGap()); 5296 return; 5297 } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) { 5298 m_style->setHasNormalColumnGap(); 5299 return; 5300 } 5301 m_style->setColumnGap(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor)); 5302 return; 5303 } 5304 case CSSPropertyWebkitColumnSpan: { 5305 HANDLE_INHERIT_AND_INITIAL(columnSpan, ColumnSpan) 5306 m_style->setColumnSpan(primitiveValue->getIdent() == CSSValueAll); 5307 return; 5308 } 5309 case CSSPropertyWebkitColumnWidth: { 5310 if (isInherit) { 5311 if (m_parentStyle->hasAutoColumnWidth()) 5312 m_style->setHasAutoColumnWidth(); 5313 else 5314 m_style->setColumnWidth(m_parentStyle->columnWidth()); 5315 return; 5316 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) { 5317 m_style->setHasAutoColumnWidth(); 5318 return; 5319 } 5320 m_style->setColumnWidth(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor)); 5321 return; 5322 } 5323 case CSSPropertyWebkitColumnRuleStyle: 5324 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle) 5325 return; 5326 case CSSPropertyWebkitColumnBreakBefore: 5327 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak) 5328 return; 5329 case CSSPropertyWebkitColumnBreakAfter: 5330 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak) 5331 return; 5332 case CSSPropertyWebkitColumnBreakInside: { 5333 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak) 5334 EPageBreak pb = *primitiveValue; 5335 if (pb != PBALWAYS) 5336 m_style->setColumnBreakInside(pb); 5337 return; 5338 } 5339 case CSSPropertyWebkitColumnRule: 5340 if (isInherit) { 5341 m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color()); 5342 m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle()); 5343 m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth()); 5344 } 5345 else if (isInitial) 5346 m_style->resetColumnRule(); 5347 return; 5348 case CSSPropertyWebkitColumns: 5349 if (isInherit) { 5350 if (m_parentStyle->hasAutoColumnWidth()) 5351 m_style->setHasAutoColumnWidth(); 5352 else 5353 m_style->setColumnWidth(m_parentStyle->columnWidth()); 5354 m_style->setColumnCount(m_parentStyle->columnCount()); 5355 } else if (isInitial) { 5356 m_style->setHasAutoColumnWidth(); 5357 m_style->setColumnCount(RenderStyle::initialColumnCount()); 5358 } 5359 return; 5360 case CSSPropertyWebkitMarquee: 5361 if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return; 5362 m_style->setMarqueeDirection(m_parentStyle->marqueeDirection()); 5363 m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement()); 5364 m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed()); 5365 m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount()); 5366 m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior()); 5367 return; 5368#if ENABLE(WCSS) 5369 case CSSPropertyWapMarqueeLoop: 5370#endif 5371 case CSSPropertyWebkitMarqueeRepetition: { 5372 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) 5373 if (!primitiveValue) 5374 return; 5375 if (primitiveValue->getIdent() == CSSValueInfinite) 5376 m_style->setMarqueeLoopCount(-1); // -1 means repeat forever. 5377 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) 5378 m_style->setMarqueeLoopCount(primitiveValue->getIntValue()); 5379 return; 5380 } 5381#if ENABLE(WCSS) 5382 case CSSPropertyWapMarqueeSpeed: 5383#endif 5384 case CSSPropertyWebkitMarqueeSpeed: { 5385 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) 5386 if (!primitiveValue) 5387 return; 5388 if (primitiveValue->getIdent()) { 5389 switch (primitiveValue->getIdent()) { 5390 case CSSValueSlow: 5391 m_style->setMarqueeSpeed(500); // 500 msec. 5392 break; 5393 case CSSValueNormal: 5394 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default. 5395 break; 5396 case CSSValueFast: 5397 m_style->setMarqueeSpeed(10); // 10msec. Super fast. 5398 break; 5399 } 5400 } 5401 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 5402 m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue()); 5403 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) 5404 m_style->setMarqueeSpeed(primitiveValue->getIntValue()); 5405 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. 5406 m_style->setMarqueeSpeed(primitiveValue->getIntValue()); 5407 return; 5408 } 5409 case CSSPropertyWebkitMarqueeIncrement: { 5410 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement) 5411 if (!primitiveValue) 5412 return; 5413 if (primitiveValue->getIdent()) { 5414 switch (primitiveValue->getIdent()) { 5415 case CSSValueSmall: 5416 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px. 5417 break; 5418 case CSSValueNormal: 5419 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. 5420 break; 5421 case CSSValueLarge: 5422 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px. 5423 break; 5424 } 5425 } 5426 else { 5427 bool ok = true; 5428 Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok); 5429 if (ok) 5430 m_style->setMarqueeIncrement(marqueeLength); 5431 } 5432 return; 5433 } 5434#if ENABLE(WCSS) 5435 case CSSPropertyWapMarqueeStyle: 5436#endif 5437 case CSSPropertyWebkitMarqueeStyle: 5438 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior) 5439 return; 5440#if ENABLE(WCSS) 5441 case CSSPropertyWapMarqueeDir: 5442 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) 5443 if (primitiveValue && primitiveValue->getIdent()) { 5444 switch (primitiveValue->getIdent()) { 5445 case CSSValueLtr: 5446 m_style->setMarqueeDirection(MRIGHT); 5447 break; 5448 case CSSValueRtl: 5449 m_style->setMarqueeDirection(MLEFT); 5450 break; 5451 default: 5452 m_style->setMarqueeDirection(*primitiveValue); 5453 break; 5454 } 5455 } 5456 return; 5457#endif 5458 case CSSPropertyWebkitMarqueeDirection: 5459 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection) 5460 return; 5461 case CSSPropertyWebkitUserDrag: 5462 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag) 5463 return; 5464 case CSSPropertyWebkitUserModify: 5465 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify) 5466 return; 5467 case CSSPropertyWebkitUserSelect: 5468 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect) 5469 return; 5470 5471 case CSSPropertyTextOverflow: { 5472 // This property is supported by WinIE, and so we leave off the "-webkit-" in order to 5473 // work with WinIE-specific pages that use the property. 5474 HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow) 5475 if (!primitiveValue || !primitiveValue->getIdent()) 5476 return; 5477 m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis); 5478 return; 5479 } 5480 case CSSPropertyWebkitMarginCollapse: { 5481 if (isInherit) { 5482 m_style->setMarginBeforeCollapse(m_parentStyle->marginBeforeCollapse()); 5483 m_style->setMarginAfterCollapse(m_parentStyle->marginAfterCollapse()); 5484 } 5485 else if (isInitial) { 5486 m_style->setMarginBeforeCollapse(MCOLLAPSE); 5487 m_style->setMarginAfterCollapse(MCOLLAPSE); 5488 } 5489 return; 5490 } 5491 5492 case CSSPropertyWebkitMarginBeforeCollapse: 5493 case CSSPropertyWebkitMarginTopCollapse: 5494 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginBeforeCollapse, MarginBeforeCollapse) 5495 return; 5496 case CSSPropertyWebkitMarginAfterCollapse: 5497 case CSSPropertyWebkitMarginBottomCollapse: 5498 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginAfterCollapse, MarginAfterCollapse) 5499 return; 5500 case CSSPropertyWebkitLineClamp: { 5501 HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp) 5502 if (!primitiveValue) 5503 return; 5504 int type = primitiveValue->primitiveType(); 5505 if (type == CSSPrimitiveValue::CSS_NUMBER) 5506 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount)); 5507 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5508 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage)); 5509 return; 5510 } 5511 case CSSPropertyWebkitHighlight: { 5512 HANDLE_INHERIT_AND_INITIAL(highlight, Highlight); 5513 if (primitiveValue->getIdent() == CSSValueNone) 5514 m_style->setHighlight(nullAtom); 5515 else 5516 m_style->setHighlight(primitiveValue->getStringValue()); 5517 return; 5518 } 5519 case CSSPropertyWebkitHyphens: { 5520 HANDLE_INHERIT_AND_INITIAL(hyphens, Hyphens); 5521 m_style->setHyphens(*primitiveValue); 5522 return; 5523 } 5524 case CSSPropertyWebkitHyphenateCharacter: { 5525 HANDLE_INHERIT_AND_INITIAL(hyphenationString, HyphenationString); 5526 if (primitiveValue->getIdent() == CSSValueAuto) 5527 m_style->setHyphenationString(nullAtom); 5528 else 5529 m_style->setHyphenationString(primitiveValue->getStringValue()); 5530 return; 5531 } 5532 case CSSPropertyWebkitHyphenateLimitAfter: { 5533 HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter); 5534 if (primitiveValue->getIdent() == CSSValueAuto) 5535 m_style->setHyphenationLimitAfter(-1); 5536 else 5537 m_style->setHyphenationLimitAfter(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max()))); 5538 return; 5539 } 5540 case CSSPropertyWebkitHyphenateLimitBefore: { 5541 HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore); 5542 if (primitiveValue->getIdent() == CSSValueAuto) 5543 m_style->setHyphenationLimitBefore(-1); 5544 else 5545 m_style->setHyphenationLimitBefore(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max()))); 5546 return; 5547 } 5548 case CSSPropertyWebkitLocale: { 5549 HANDLE_INHERIT_AND_INITIAL(locale, Locale); 5550 if (primitiveValue->getIdent() == CSSValueAuto) 5551 m_style->setLocale(nullAtom); 5552 else 5553 m_style->setLocale(primitiveValue->getStringValue()); 5554 return; 5555 } 5556 case CSSPropertyWebkitBorderFit: { 5557 HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit); 5558 if (primitiveValue->getIdent() == CSSValueBorder) 5559 m_style->setBorderFit(BorderFitBorder); 5560 else 5561 m_style->setBorderFit(BorderFitLines); 5562 return; 5563 } 5564 case CSSPropertyWebkitTextSizeAdjust: { 5565 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust) 5566 if (!primitiveValue || !primitiveValue->getIdent()) return; 5567 m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto); 5568 m_fontDirty = true; 5569 return; 5570 } 5571 case CSSPropertyWebkitTextSecurity: 5572 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity) 5573 return; 5574 5575#if ENABLE(DASHBOARD_SUPPORT) 5576 case CSSPropertyWebkitDashboardRegion: { 5577 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions) 5578 if (!primitiveValue) 5579 return; 5580 5581 if (primitiveValue->getIdent() == CSSValueNone) { 5582 m_style->setDashboardRegions(RenderStyle::noneDashboardRegions()); 5583 return; 5584 } 5585 5586 DashboardRegion *region = primitiveValue->getDashboardRegionValue(); 5587 if (!region) 5588 return; 5589 5590 DashboardRegion *first = region; 5591 while (region) { 5592 Length top = convertToIntLength(region->top(), style(), m_rootElementStyle); 5593 Length right = convertToIntLength(region->right(), style(), m_rootElementStyle); 5594 Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle); 5595 Length left = convertToIntLength(region->left(), style(), m_rootElementStyle); 5596 if (region->m_isCircle) 5597 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); 5598 else if (region->m_isRectangle) 5599 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true); 5600 region = region->m_next.get(); 5601 } 5602 5603 m_element->document()->setHasDashboardRegions(true); 5604 5605 return; 5606 } 5607#endif 5608 case CSSPropertyWebkitRtlOrdering: 5609 HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered) 5610 if (!primitiveValue || !primitiveValue->getIdent()) 5611 return; 5612 m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual); 5613 return; 5614 case CSSPropertyWebkitTextStrokeWidth: { 5615 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) 5616 float width = 0; 5617 switch (primitiveValue->getIdent()) { 5618 case CSSValueThin: 5619 case CSSValueMedium: 5620 case CSSValueThick: { 5621 double result = 1.0 / 48; 5622 if (primitiveValue->getIdent() == CSSValueMedium) 5623 result *= 3; 5624 else if (primitiveValue->getIdent() == CSSValueThick) 5625 result *= 5; 5626 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); 5627 break; 5628 } 5629 default: 5630 width = primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); 5631 break; 5632 } 5633 m_style->setTextStrokeWidth(width); 5634 return; 5635 } 5636 case CSSPropertyWebkitTransform: { 5637 HANDLE_INHERIT_AND_INITIAL(transform, Transform); 5638 TransformOperations operations; 5639 createTransformOperations(value, style(), m_rootElementStyle, operations); 5640 m_style->setTransform(operations); 5641 return; 5642 } 5643 case CSSPropertyWebkitTransformOrigin: 5644 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) 5645 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) 5646 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ) 5647 return; 5648 case CSSPropertyWebkitTransformOriginX: { 5649 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) 5650 if (!primitiveValue) 5651 return; 5652 Length l; 5653 int type = primitiveValue->primitiveType(); 5654 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5655 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 5656 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5657 l = Length(primitiveValue->getDoubleValue(), Percent); 5658 else 5659 return; 5660 m_style->setTransformOriginX(l); 5661 break; 5662 } 5663 case CSSPropertyWebkitTransformOriginY: { 5664 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) 5665 if (!primitiveValue) 5666 return; 5667 Length l; 5668 int type = primitiveValue->primitiveType(); 5669 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5670 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 5671 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5672 l = Length(primitiveValue->getDoubleValue(), Percent); 5673 else 5674 return; 5675 m_style->setTransformOriginY(l); 5676 break; 5677 } 5678 case CSSPropertyWebkitTransformOriginZ: { 5679 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ) 5680 if (!primitiveValue) 5681 return; 5682 float f; 5683 int type = primitiveValue->primitiveType(); 5684 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5685 f = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle)); 5686 else 5687 return; 5688 m_style->setTransformOriginZ(f); 5689 break; 5690 } 5691 case CSSPropertyWebkitTransformStyle: 5692 HANDLE_INHERIT_AND_INITIAL(transformStyle3D, TransformStyle3D) 5693 if (primitiveValue) 5694 m_style->setTransformStyle3D((primitiveValue->getIdent() == CSSValuePreserve3d) ? TransformStyle3DPreserve3D : TransformStyle3DFlat); 5695 return; 5696 case CSSPropertyWebkitPerspective: { 5697 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective) 5698 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { 5699 m_style->setPerspective(0); 5700 return; 5701 } 5702 5703 float perspectiveValue; 5704 int type = primitiveValue->primitiveType(); 5705 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5706 perspectiveValue = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor)); 5707 else if (type == CSSPrimitiveValue::CSS_NUMBER) { 5708 // For backward compatibility, treat valueless numbers as px. 5709 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor); 5710 } else 5711 return; 5712 5713 if (perspectiveValue >= 0.0f) 5714 m_style->setPerspective(perspectiveValue); 5715 return; 5716 } 5717 case CSSPropertyWebkitPerspectiveOrigin: 5718 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX) 5719 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY) 5720 return; 5721 case CSSPropertyWebkitPerspectiveOriginX: { 5722 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX) 5723 if (!primitiveValue) 5724 return; 5725 Length l; 5726 int type = primitiveValue->primitiveType(); 5727 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5728 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 5729 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5730 l = Length(primitiveValue->getDoubleValue(), Percent); 5731 else 5732 return; 5733 m_style->setPerspectiveOriginX(l); 5734 return; 5735 } 5736 case CSSPropertyWebkitPerspectiveOriginY: { 5737 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY) 5738 if (!primitiveValue) 5739 return; 5740 Length l; 5741 int type = primitiveValue->primitiveType(); 5742 if (CSSPrimitiveValue::isUnitTypeLength(type)) 5743 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 5744 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 5745 l = Length(primitiveValue->getDoubleValue(), Percent); 5746 else 5747 return; 5748 m_style->setPerspectiveOriginY(l); 5749 return; 5750 } 5751 case CSSPropertyWebkitAnimation: 5752 if (isInitial) 5753 m_style->clearAnimations(); 5754 else if (isInherit) 5755 m_style->inheritAnimations(m_parentStyle->animations()); 5756 return; 5757 case CSSPropertyWebkitAnimationDelay: 5758 HANDLE_ANIMATION_VALUE(delay, Delay, value) 5759 return; 5760 case CSSPropertyWebkitAnimationDirection: 5761 HANDLE_ANIMATION_VALUE(direction, Direction, value) 5762 return; 5763 case CSSPropertyWebkitAnimationDuration: 5764 HANDLE_ANIMATION_VALUE(duration, Duration, value) 5765 return; 5766 case CSSPropertyWebkitAnimationFillMode: 5767 HANDLE_ANIMATION_VALUE(fillMode, FillMode, value) 5768 return; 5769 case CSSPropertyWebkitAnimationIterationCount: 5770 HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value) 5771 return; 5772 case CSSPropertyWebkitAnimationName: 5773 HANDLE_ANIMATION_VALUE(name, Name, value) 5774 return; 5775 case CSSPropertyWebkitAnimationPlayState: 5776 HANDLE_ANIMATION_VALUE(playState, PlayState, value) 5777 return; 5778 case CSSPropertyWebkitAnimationTimingFunction: 5779 HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value) 5780 return; 5781 case CSSPropertyWebkitTransition: 5782 if (isInitial) 5783 m_style->clearTransitions(); 5784 else if (isInherit) 5785 m_style->inheritTransitions(m_parentStyle->transitions()); 5786 return; 5787 case CSSPropertyWebkitTransitionDelay: 5788 HANDLE_TRANSITION_VALUE(delay, Delay, value) 5789 return; 5790 case CSSPropertyWebkitTransitionDuration: 5791 HANDLE_TRANSITION_VALUE(duration, Duration, value) 5792 return; 5793 case CSSPropertyWebkitTransitionProperty: 5794 HANDLE_TRANSITION_VALUE(property, Property, value) 5795 return; 5796 case CSSPropertyWebkitTransitionTimingFunction: 5797 HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value) 5798 return; 5799 case CSSPropertyPointerEvents: 5800 { 5801#if ENABLE(DASHBOARD_SUPPORT) 5802 // <rdar://problem/6561077> Work around the Stocks widget's misuse of the 5803 // pointer-events property by not applying it in Dashboard. 5804 Settings* settings = m_checker.m_document->settings(); 5805 if (settings && settings->usesDashboardBackwardCompatibilityMode()) 5806 return; 5807#endif 5808 HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents) 5809 if (!primitiveValue) 5810 return; 5811 m_style->setPointerEvents(*primitiveValue); 5812 return; 5813 } 5814 case CSSPropertyWebkitColorCorrection: 5815 if (isInherit) 5816 m_style->setColorSpace(m_parentStyle->colorSpace()); 5817 else if (isInitial) 5818 m_style->setColorSpace(ColorSpaceDeviceRGB); 5819 else { 5820 if (!primitiveValue) 5821 return; 5822 m_style->setColorSpace(*primitiveValue); 5823 } 5824 return; 5825 case CSSPropertySize: 5826 applyPageSizeProperty(value); 5827 return; 5828 5829 case CSSPropertySpeak: 5830 HANDLE_INHERIT_AND_INITIAL(speak, Speak); 5831 if (!primitiveValue) 5832 return; 5833 m_style->setSpeak(*primitiveValue); 5834 return; 5835 5836 case CSSPropertyInvalid: 5837 return; 5838 5839 // Directional properties are resolved by resolveDirectionAwareProperty() before the switch. 5840 case CSSPropertyWebkitBorderEnd: 5841 case CSSPropertyWebkitBorderEndColor: 5842 case CSSPropertyWebkitBorderEndStyle: 5843 case CSSPropertyWebkitBorderEndWidth: 5844 case CSSPropertyWebkitBorderStart: 5845 case CSSPropertyWebkitBorderStartColor: 5846 case CSSPropertyWebkitBorderStartStyle: 5847 case CSSPropertyWebkitBorderStartWidth: 5848 case CSSPropertyWebkitBorderBefore: 5849 case CSSPropertyWebkitBorderBeforeColor: 5850 case CSSPropertyWebkitBorderBeforeStyle: 5851 case CSSPropertyWebkitBorderBeforeWidth: 5852 case CSSPropertyWebkitBorderAfter: 5853 case CSSPropertyWebkitBorderAfterColor: 5854 case CSSPropertyWebkitBorderAfterStyle: 5855 case CSSPropertyWebkitBorderAfterWidth: 5856 case CSSPropertyWebkitMarginEnd: 5857 case CSSPropertyWebkitMarginStart: 5858 case CSSPropertyWebkitMarginBefore: 5859 case CSSPropertyWebkitMarginAfter: 5860 case CSSPropertyWebkitPaddingEnd: 5861 case CSSPropertyWebkitPaddingStart: 5862 case CSSPropertyWebkitPaddingBefore: 5863 case CSSPropertyWebkitPaddingAfter: 5864 case CSSPropertyWebkitLogicalWidth: 5865 case CSSPropertyWebkitLogicalHeight: 5866 case CSSPropertyWebkitMinLogicalWidth: 5867 case CSSPropertyWebkitMinLogicalHeight: 5868 case CSSPropertyWebkitMaxLogicalWidth: 5869 case CSSPropertyWebkitMaxLogicalHeight: 5870 ASSERT_NOT_REACHED(); 5871 break; 5872 5873 case CSSPropertyFontStretch: 5874 case CSSPropertyPage: 5875 case CSSPropertyTextLineThrough: 5876 case CSSPropertyTextLineThroughColor: 5877 case CSSPropertyTextLineThroughMode: 5878 case CSSPropertyTextLineThroughStyle: 5879 case CSSPropertyTextLineThroughWidth: 5880 case CSSPropertyTextOverline: 5881 case CSSPropertyTextOverlineColor: 5882 case CSSPropertyTextOverlineMode: 5883 case CSSPropertyTextOverlineStyle: 5884 case CSSPropertyTextOverlineWidth: 5885 case CSSPropertyTextUnderline: 5886 case CSSPropertyTextUnderlineColor: 5887 case CSSPropertyTextUnderlineMode: 5888 case CSSPropertyTextUnderlineStyle: 5889 case CSSPropertyTextUnderlineWidth: 5890 case CSSPropertyWebkitFontSizeDelta: 5891 case CSSPropertyWebkitTextDecorationsInEffect: 5892 case CSSPropertyWebkitTextStroke: 5893 case CSSPropertyWebkitTextEmphasis: 5894 return; 5895#if ENABLE(WCSS) 5896 case CSSPropertyWapInputFormat: 5897 if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) { 5898 String mask = primitiveValue->getStringValue(); 5899 static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask); 5900 } 5901 return; 5902 5903 case CSSPropertyWapInputRequired: 5904 if (primitiveValue && m_element->isFormControlElement()) { 5905 HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element); 5906 bool required = primitiveValue->getStringValue() == "true"; 5907 element->setRequired(required); 5908 } 5909 return; 5910#endif 5911 5912 // CSS Text Layout Module Level 3: Vertical writing support 5913 case CSSPropertyWebkitWritingMode: { 5914 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode) 5915 if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement()) 5916 m_element->document()->setWritingModeSetOnDocumentElement(true); 5917 FontDescription fontDescription = m_style->fontDescription(); 5918 fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical); 5919 if (m_style->setFontDescription(fontDescription)) 5920 m_fontDirty = true; 5921 return; 5922 } 5923 5924 case CSSPropertyWebkitTextCombine: 5925 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine) 5926 return; 5927 5928 case CSSPropertyWebkitTextEmphasisPosition: 5929 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textEmphasisPosition, TextEmphasisPosition) 5930 return; 5931 5932 case CSSPropertyWebkitTextEmphasisStyle: 5933 HANDLE_INHERIT_AND_INITIAL(textEmphasisFill, TextEmphasisFill) 5934 HANDLE_INHERIT_AND_INITIAL(textEmphasisMark, TextEmphasisMark) 5935 HANDLE_INHERIT_AND_INITIAL(textEmphasisCustomMark, TextEmphasisCustomMark) 5936 if (isInherit || isInitial) 5937 return; 5938 5939 if (value->isValueList()) { 5940 CSSValueList* list = static_cast<CSSValueList*>(value); 5941 ASSERT(list->length() == 2); 5942 if (list->length() != 2) 5943 return; 5944 for (unsigned i = 0; i < 2; ++i) { 5945 CSSValue* item = list->itemWithoutBoundsCheck(i); 5946 if (!item->isPrimitiveValue()) 5947 continue; 5948 5949 CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(item); 5950 if (value->getIdent() == CSSValueFilled || value->getIdent() == CSSValueOpen) 5951 m_style->setTextEmphasisFill(*value); 5952 else 5953 m_style->setTextEmphasisMark(*value); 5954 } 5955 m_style->setTextEmphasisCustomMark(nullAtom); 5956 return; 5957 } 5958 5959 if (!primitiveValue) 5960 return; 5961 5962 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) { 5963 m_style->setTextEmphasisFill(TextEmphasisFillFilled); 5964 m_style->setTextEmphasisMark(TextEmphasisMarkCustom); 5965 m_style->setTextEmphasisCustomMark(primitiveValue->getStringValue()); 5966 return; 5967 } 5968 5969 m_style->setTextEmphasisCustomMark(nullAtom); 5970 5971 if (primitiveValue->getIdent() == CSSValueFilled || primitiveValue->getIdent() == CSSValueOpen) { 5972 m_style->setTextEmphasisFill(*primitiveValue); 5973 m_style->setTextEmphasisMark(TextEmphasisMarkAuto); 5974 } else { 5975 m_style->setTextEmphasisFill(TextEmphasisFillFilled); 5976 m_style->setTextEmphasisMark(*primitiveValue); 5977 } 5978 5979 return; 5980 5981 case CSSPropertyWebkitTextOrientation: { 5982 if (!isInherit && !isInitial && !primitiveValue) 5983 return; 5984 5985 TextOrientation result; 5986 if (isInherit) 5987 result = m_parentStyle->fontDescription().textOrientation(); 5988 else if (isInitial) 5989 result = RenderStyle::initialTextOrientation(); 5990 else 5991 result = *primitiveValue; 5992 5993 FontDescription fontDescription = m_style->fontDescription(); 5994 if (fontDescription.textOrientation() != result) { 5995 fontDescription.setTextOrientation(result); 5996 if (m_style->setFontDescription(fontDescription)) 5997 m_fontDirty = true; 5998 } 5999 return; 6000 } 6001 6002 case CSSPropertyWebkitLineBoxContain: { 6003 HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain) 6004 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { 6005 m_style->setLineBoxContain(LineBoxContainNone); 6006 return; 6007 } 6008 6009 if (!value->isCSSLineBoxContainValue()) 6010 return; 6011 6012 CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value); 6013 m_style->setLineBoxContain(lineBoxContainValue->value()); 6014 return; 6015 } 6016 6017 // These properties are implemented in the CSSStyleApplyProperty lookup table. 6018 case CSSPropertyColor: 6019 case CSSPropertyDirection: 6020 case CSSPropertyBackgroundAttachment: 6021 case CSSPropertyBackgroundClip: 6022 case CSSPropertyWebkitBackgroundClip: 6023 case CSSPropertyWebkitBackgroundComposite: 6024 case CSSPropertyBackgroundOrigin: 6025 case CSSPropertyWebkitBackgroundOrigin: 6026 case CSSPropertyBackgroundImage: 6027 case CSSPropertyBackgroundSize: 6028 case CSSPropertyWebkitBackgroundSize: 6029 case CSSPropertyWebkitMaskAttachment: 6030 case CSSPropertyWebkitMaskClip: 6031 case CSSPropertyWebkitMaskComposite: 6032 case CSSPropertyWebkitMaskOrigin: 6033 case CSSPropertyWebkitMaskImage: 6034 case CSSPropertyWebkitMaskSize: 6035 case CSSPropertyBackgroundColor: 6036 case CSSPropertyBorderBottomColor: 6037 case CSSPropertyBorderLeftColor: 6038 case CSSPropertyBorderRightColor: 6039 case CSSPropertyBorderTopColor: 6040 case CSSPropertyBorderTopStyle: 6041 case CSSPropertyBorderRightStyle: 6042 case CSSPropertyBorderBottomStyle: 6043 case CSSPropertyBorderLeftStyle: 6044 case CSSPropertyOutlineColor: 6045 case CSSPropertyWebkitColumnRuleColor: 6046 case CSSPropertyWebkitTextEmphasisColor: 6047 case CSSPropertyWebkitTextFillColor: 6048 case CSSPropertyWebkitTextStrokeColor: 6049 case CSSPropertyBackgroundPosition: 6050 case CSSPropertyBackgroundPositionX: 6051 case CSSPropertyBackgroundPositionY: 6052 case CSSPropertyWebkitMaskPosition: 6053 case CSSPropertyWebkitMaskPositionX: 6054 case CSSPropertyWebkitMaskPositionY: 6055 case CSSPropertyBackgroundRepeat: 6056 case CSSPropertyBackgroundRepeatX: 6057 case CSSPropertyBackgroundRepeatY: 6058 case CSSPropertyWebkitMaskRepeat: 6059 case CSSPropertyWebkitMaskRepeatX: 6060 case CSSPropertyWebkitMaskRepeatY: 6061 case CSSPropertyOverflow: 6062 case CSSPropertyOverflowX: 6063 case CSSPropertyOverflowY: 6064 ASSERT_NOT_REACHED(); 6065 return; 6066 6067#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR 6068 case CSSPropertyWebkitTapHighlightColor: { 6069 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); 6070 if (!primitiveValue) 6071 break; 6072 6073 Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite(); 6074 m_style->setTapHighlightColor(col); 6075 return; 6076 } 6077#endif 6078 6079#if ENABLE(SVG) 6080 default: 6081 // Try the SVG properties 6082 applySVGProperty(id, value); 6083 return; 6084#endif 6085 } 6086} 6087 6088void CSSStyleSelector::applyPageSizeProperty(CSSValue* value) 6089{ 6090 m_style->resetPageSizeType(); 6091 if (!value->isValueList()) 6092 return; 6093 CSSValueList* valueList = static_cast<CSSValueList*>(value); 6094 Length width; 6095 Length height; 6096 PageSizeType pageSizeType = PAGE_SIZE_AUTO; 6097 switch (valueList->length()) { 6098 case 2: { 6099 // <length>{2} | <page-size> <orientation> 6100 pageSizeType = PAGE_SIZE_RESOLVED; 6101 if (!valueList->item(0)->isPrimitiveValue() || !valueList->item(1)->isPrimitiveValue()) 6102 return; 6103 CSSPrimitiveValue* primitiveValue0 = static_cast<CSSPrimitiveValue*>(valueList->item(0)); 6104 CSSPrimitiveValue* primitiveValue1 = static_cast<CSSPrimitiveValue*>(valueList->item(1)); 6105 int type0 = primitiveValue0->primitiveType(); 6106 int type1 = primitiveValue1->primitiveType(); 6107 if (CSSPrimitiveValue::isUnitTypeLength(type0)) { 6108 // <length>{2} 6109 if (!CSSPrimitiveValue::isUnitTypeLength(type1)) 6110 return; 6111 width = Length(primitiveValue0->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); 6112 height = Length(primitiveValue1->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); 6113 } else { 6114 // <page-size> <orientation> 6115 // The value order is guaranteed. See CSSParser::parseSizeParameter. 6116 if (!pageSizeFromName(primitiveValue0, primitiveValue1, width, height)) 6117 return; 6118 } 6119 break; 6120 } 6121 case 1: { 6122 // <length> | auto | <page-size> | [ portrait | landscape] 6123 if (!valueList->item(0)->isPrimitiveValue()) 6124 return; 6125 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valueList->item(0)); 6126 int type = primitiveValue->primitiveType(); 6127 if (CSSPrimitiveValue::isUnitTypeLength(type)) { 6128 // <length> 6129 pageSizeType = PAGE_SIZE_RESOLVED; 6130 width = height = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); 6131 } else { 6132 if (type != CSSPrimitiveValue::CSS_IDENT) 6133 return; 6134 switch (primitiveValue->getIdent()) { 6135 case CSSValueAuto: 6136 pageSizeType = PAGE_SIZE_AUTO; 6137 break; 6138 case CSSValuePortrait: 6139 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT; 6140 break; 6141 case CSSValueLandscape: 6142 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE; 6143 break; 6144 default: 6145 // <page-size> 6146 pageSizeType = PAGE_SIZE_RESOLVED; 6147 if (!pageSizeFromName(primitiveValue, 0, width, height)) 6148 return; 6149 } 6150 } 6151 break; 6152 } 6153 default: 6154 return; 6155 } 6156 m_style->setPageSizeType(pageSizeType); 6157 m_style->setPageSize(LengthSize(width, height)); 6158 return; 6159} 6160 6161bool CSSStyleSelector::pageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height) 6162{ 6163 static const Length a5Width = mmLength(148), a5Height = mmLength(210); 6164 static const Length a4Width = mmLength(210), a4Height = mmLength(297); 6165 static const Length a3Width = mmLength(297), a3Height = mmLength(420); 6166 static const Length b5Width = mmLength(176), b5Height = mmLength(250); 6167 static const Length b4Width = mmLength(250), b4Height = mmLength(353); 6168 static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11); 6169 static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14); 6170 static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17); 6171 6172 if (!pageSizeName || pageSizeName->primitiveType() != CSSPrimitiveValue::CSS_IDENT) 6173 return false; 6174 6175 switch (pageSizeName->getIdent()) { 6176 case CSSValueA5: 6177 width = a5Width; 6178 height = a5Height; 6179 break; 6180 case CSSValueA4: 6181 width = a4Width; 6182 height = a4Height; 6183 break; 6184 case CSSValueA3: 6185 width = a3Width; 6186 height = a3Height; 6187 break; 6188 case CSSValueB5: 6189 width = b5Width; 6190 height = b5Height; 6191 break; 6192 case CSSValueB4: 6193 width = b4Width; 6194 height = b4Height; 6195 break; 6196 case CSSValueLetter: 6197 width = letterWidth; 6198 height = letterHeight; 6199 break; 6200 case CSSValueLegal: 6201 width = legalWidth; 6202 height = legalHeight; 6203 break; 6204 case CSSValueLedger: 6205 width = ledgerWidth; 6206 height = ledgerHeight; 6207 break; 6208 default: 6209 return false; 6210 } 6211 6212 if (pageOrientation) { 6213 if (pageOrientation->primitiveType() != CSSPrimitiveValue::CSS_IDENT) 6214 return false; 6215 switch (pageOrientation->getIdent()) { 6216 case CSSValueLandscape: 6217 std::swap(width, height); 6218 break; 6219 case CSSValuePortrait: 6220 // Nothing to do. 6221 break; 6222 default: 6223 return false; 6224 } 6225 } 6226 return true; 6227} 6228 6229Length CSSStyleSelector::mmLength(double mm) const 6230{ 6231 return Length(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); 6232} 6233 6234Length CSSStyleSelector::inchLength(double inch) const 6235{ 6236 return Length(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed); 6237} 6238 6239void CSSStyleSelector::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value) 6240{ 6241 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6242 layer->setAttachment(FillLayer::initialFillAttachment(layer->type())); 6243 return; 6244 } 6245 6246 if (!value->isPrimitiveValue()) 6247 return; 6248 6249 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6250 switch (primitiveValue->getIdent()) { 6251 case CSSValueFixed: 6252 layer->setAttachment(FixedBackgroundAttachment); 6253 break; 6254 case CSSValueScroll: 6255 layer->setAttachment(ScrollBackgroundAttachment); 6256 break; 6257 case CSSValueLocal: 6258 layer->setAttachment(LocalBackgroundAttachment); 6259 break; 6260 default: 6261 return; 6262 } 6263} 6264 6265void CSSStyleSelector::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value) 6266{ 6267 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6268 layer->setClip(FillLayer::initialFillClip(layer->type())); 6269 return; 6270 } 6271 6272 if (!value->isPrimitiveValue()) 6273 return; 6274 6275 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6276 layer->setClip(*primitiveValue); 6277} 6278 6279void CSSStyleSelector::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value) 6280{ 6281 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6282 layer->setComposite(FillLayer::initialFillComposite(layer->type())); 6283 return; 6284 } 6285 6286 if (!value->isPrimitiveValue()) 6287 return; 6288 6289 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6290 layer->setComposite(*primitiveValue); 6291} 6292 6293void CSSStyleSelector::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value) 6294{ 6295 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6296 layer->setOrigin(FillLayer::initialFillOrigin(layer->type())); 6297 return; 6298 } 6299 6300 if (!value->isPrimitiveValue()) 6301 return; 6302 6303 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6304 layer->setOrigin(*primitiveValue); 6305} 6306 6307StyleImage* CSSStyleSelector::styleImage(CSSPropertyID property, CSSValue* value) 6308{ 6309 if (value->isImageValue()) 6310 return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value)); 6311 6312 if (value->isImageGeneratorValue()) 6313 return static_cast<CSSImageGeneratorValue*>(value)->generatedImage(); 6314 6315 return 0; 6316} 6317 6318StyleImage* CSSStyleSelector::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value) 6319{ 6320 StyleImage* image = value->cachedOrPendingImage(); 6321 if (image && image->isPendingImage()) 6322 m_pendingImageProperties.add(property); 6323 return image; 6324} 6325 6326void CSSStyleSelector::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value) 6327{ 6328 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6329 layer->setImage(FillLayer::initialFillImage(layer->type())); 6330 return; 6331 } 6332 6333 layer->setImage(styleImage(property, value)); 6334} 6335 6336void CSSStyleSelector::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value) 6337{ 6338 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6339 layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type())); 6340 return; 6341 } 6342 6343 if (!value->isPrimitiveValue()) 6344 return; 6345 6346 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6347 layer->setRepeatX(*primitiveValue); 6348} 6349 6350void CSSStyleSelector::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value) 6351{ 6352 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6353 layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type())); 6354 return; 6355 } 6356 6357 if (!value->isPrimitiveValue()) 6358 return; 6359 6360 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6361 layer->setRepeatY(*primitiveValue); 6362} 6363 6364void CSSStyleSelector::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value) 6365{ 6366 if (!value->isPrimitiveValue()) { 6367 layer->setSizeType(SizeNone); 6368 return; 6369 } 6370 6371 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6372 if (primitiveValue->getIdent() == CSSValueContain) 6373 layer->setSizeType(Contain); 6374 else if (primitiveValue->getIdent() == CSSValueCover) 6375 layer->setSizeType(Cover); 6376 else 6377 layer->setSizeType(SizeLength); 6378 6379 LengthSize b = FillLayer::initialFillSizeLength(layer->type()); 6380 6381 if (value->cssValueType() == CSSValue::CSS_INITIAL || primitiveValue->getIdent() == CSSValueContain 6382 || primitiveValue->getIdent() == CSSValueCover) { 6383 layer->setSizeLength(b); 6384 return; 6385 } 6386 6387 Pair* pair = primitiveValue->getPairValue(); 6388 if (!pair || !pair->first() || !pair->second()) 6389 return; 6390 6391 CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first()); 6392 CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second()); 6393 6394 Length firstLength, secondLength; 6395 int firstType = first->primitiveType(); 6396 int secondType = second->primitiveType(); 6397 6398 float zoomFactor = m_style->effectiveZoom(); 6399 6400 if (firstType == CSSPrimitiveValue::CSS_UNKNOWN) 6401 firstLength = Length(Auto); 6402 else if (CSSPrimitiveValue::isUnitTypeLength(firstType)) 6403 firstLength = Length(first->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 6404 else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) 6405 firstLength = Length(first->getDoubleValue(), Percent); 6406 else 6407 return; 6408 6409 if (secondType == CSSPrimitiveValue::CSS_UNKNOWN) 6410 secondLength = Length(Auto); 6411 else if (CSSPrimitiveValue::isUnitTypeLength(secondType)) 6412 secondLength = Length(second->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 6413 else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) 6414 secondLength = Length(second->getDoubleValue(), Percent); 6415 else 6416 return; 6417 6418 b.setWidth(firstLength); 6419 b.setHeight(secondLength); 6420 layer->setSizeLength(b); 6421} 6422 6423void CSSStyleSelector::mapFillXPosition(CSSPropertyID, FillLayer* layer, CSSValue* value) 6424{ 6425 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6426 layer->setXPosition(FillLayer::initialFillXPosition(layer->type())); 6427 return; 6428 } 6429 6430 if (!value->isPrimitiveValue()) 6431 return; 6432 6433 float zoomFactor = m_style->effectiveZoom(); 6434 6435 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6436 Length l; 6437 int type = primitiveValue->primitiveType(); 6438 if (CSSPrimitiveValue::isUnitTypeLength(type)) 6439 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 6440 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 6441 l = Length(primitiveValue->getDoubleValue(), Percent); 6442 else 6443 return; 6444 layer->setXPosition(l); 6445} 6446 6447void CSSStyleSelector::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValue* value) 6448{ 6449 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6450 layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); 6451 return; 6452 } 6453 6454 if (!value->isPrimitiveValue()) 6455 return; 6456 6457 float zoomFactor = m_style->effectiveZoom(); 6458 6459 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6460 Length l; 6461 int type = primitiveValue->primitiveType(); 6462 if (CSSPrimitiveValue::isUnitTypeLength(type)) 6463 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed); 6464 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 6465 l = Length(primitiveValue->getDoubleValue(), Percent); 6466 else 6467 return; 6468 layer->setYPosition(l); 6469} 6470 6471void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value) 6472{ 6473 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6474 animation->setDelay(Animation::initialAnimationDelay()); 6475 return; 6476 } 6477 6478 if (!value->isPrimitiveValue()) 6479 return; 6480 6481 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6482 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 6483 animation->setDelay(primitiveValue->getFloatValue()); 6484 else 6485 animation->setDelay(primitiveValue->getFloatValue()/1000.0f); 6486} 6487 6488void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value) 6489{ 6490 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6491 layer->setDirection(Animation::initialAnimationDirection()); 6492 return; 6493 } 6494 6495 if (!value->isPrimitiveValue()) 6496 return; 6497 6498 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6499 layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal); 6500} 6501 6502void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value) 6503{ 6504 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6505 animation->setDuration(Animation::initialAnimationDuration()); 6506 return; 6507 } 6508 6509 if (!value->isPrimitiveValue()) 6510 return; 6511 6512 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6513 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 6514 animation->setDuration(primitiveValue->getFloatValue()); 6515 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) 6516 animation->setDuration(primitiveValue->getFloatValue()/1000.0f); 6517} 6518 6519void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value) 6520{ 6521 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6522 layer->setFillMode(Animation::initialAnimationFillMode()); 6523 return; 6524 } 6525 6526 if (!value->isPrimitiveValue()) 6527 return; 6528 6529 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6530 switch (primitiveValue->getIdent()) { 6531 case CSSValueNone: 6532 layer->setFillMode(AnimationFillModeNone); 6533 break; 6534 case CSSValueForwards: 6535 layer->setFillMode(AnimationFillModeForwards); 6536 break; 6537 case CSSValueBackwards: 6538 layer->setFillMode(AnimationFillModeBackwards); 6539 break; 6540 case CSSValueBoth: 6541 layer->setFillMode(AnimationFillModeBoth); 6542 break; 6543 } 6544} 6545 6546void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value) 6547{ 6548 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6549 animation->setIterationCount(Animation::initialAnimationIterationCount()); 6550 return; 6551 } 6552 6553 if (!value->isPrimitiveValue()) 6554 return; 6555 6556 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6557 if (primitiveValue->getIdent() == CSSValueInfinite) 6558 animation->setIterationCount(-1); 6559 else 6560 animation->setIterationCount(int(primitiveValue->getFloatValue())); 6561} 6562 6563void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value) 6564{ 6565 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6566 layer->setName(Animation::initialAnimationName()); 6567 return; 6568 } 6569 6570 if (!value->isPrimitiveValue()) 6571 return; 6572 6573 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6574 if (primitiveValue->getIdent() == CSSValueNone) 6575 layer->setIsNoneAnimation(true); 6576 else 6577 layer->setName(primitiveValue->getStringValue()); 6578} 6579 6580void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value) 6581{ 6582 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6583 layer->setPlayState(Animation::initialAnimationPlayState()); 6584 return; 6585 } 6586 6587 if (!value->isPrimitiveValue()) 6588 return; 6589 6590 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6591 EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying; 6592 layer->setPlayState(playState); 6593} 6594 6595void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value) 6596{ 6597 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6598 animation->setProperty(Animation::initialAnimationProperty()); 6599 return; 6600 } 6601 6602 if (!value->isPrimitiveValue()) 6603 return; 6604 6605 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6606 if (primitiveValue->getIdent() == CSSValueAll) 6607 animation->setProperty(cAnimateAll); 6608 else if (primitiveValue->getIdent() == CSSValueNone) 6609 animation->setProperty(cAnimateNone); 6610 else 6611 animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent())); 6612} 6613 6614void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value) 6615{ 6616 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 6617 animation->setTimingFunction(Animation::initialAnimationTimingFunction()); 6618 return; 6619 } 6620 6621 if (value->isPrimitiveValue()) { 6622 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 6623 switch (primitiveValue->getIdent()) { 6624 case CSSValueLinear: 6625 animation->setTimingFunction(LinearTimingFunction::create()); 6626 break; 6627 case CSSValueEase: 6628 animation->setTimingFunction(CubicBezierTimingFunction::create()); 6629 break; 6630 case CSSValueEaseIn: 6631 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 1.0, 1.0)); 6632 break; 6633 case CSSValueEaseOut: 6634 animation->setTimingFunction(CubicBezierTimingFunction::create(0.0, 0.0, 0.58, 1.0)); 6635 break; 6636 case CSSValueEaseInOut: 6637 animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 0.58, 1.0)); 6638 break; 6639 case CSSValueStepStart: 6640 animation->setTimingFunction(StepsTimingFunction::create(1, true)); 6641 break; 6642 case CSSValueStepEnd: 6643 animation->setTimingFunction(StepsTimingFunction::create(1, false)); 6644 break; 6645 } 6646 return; 6647 } 6648 6649 if (value->isTimingFunctionValue()) { 6650 CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value); 6651 if (timingFunction->isCubicBezierTimingFunctionValue()) { 6652 CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value); 6653 animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2())); 6654 } else if (timingFunction->isStepsTimingFunctionValue()) { 6655 CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value); 6656 animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart())); 6657 } else 6658 animation->setTimingFunction(LinearTimingFunction::create()); 6659 } 6660} 6661 6662void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image) 6663{ 6664 // If we're a primitive value, then we are "none" and don't need to alter the empty image at all. 6665 if (!value || value->isPrimitiveValue() || !value->isBorderImageValue()) 6666 return; 6667 6668 // Retrieve the border image value. 6669 CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); 6670 6671 // Set the image (this kicks off the load). 6672 image.setImage(styleImage(property, borderImage->imageValue())); 6673 6674 // Set up a length box to represent our image slices. 6675 LengthBox l; 6676 Rect* r = borderImage->m_imageSliceRect.get(); 6677 if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 6678 l.m_top = Length(r->top()->getDoubleValue(), Percent); 6679 else 6680 l.m_top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 6681 if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 6682 l.m_bottom = Length(r->bottom()->getDoubleValue(), Percent); 6683 else 6684 l.m_bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 6685 if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 6686 l.m_left = Length(r->left()->getDoubleValue(), Percent); 6687 else 6688 l.m_left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 6689 if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 6690 l.m_right = Length(r->right()->getDoubleValue(), Percent); 6691 else 6692 l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 6693 image.setSlices(l); 6694 6695 // Set the appropriate rules for stretch/round/repeat of the slices 6696 ENinePieceImageRule horizontalRule; 6697 switch (borderImage->m_horizontalSizeRule) { 6698 case CSSValueStretch: 6699 horizontalRule = StretchImageRule; 6700 break; 6701 case CSSValueRound: 6702 horizontalRule = RoundImageRule; 6703 break; 6704 default: // CSSValueRepeat 6705 horizontalRule = RepeatImageRule; 6706 break; 6707 } 6708 image.setHorizontalRule(horizontalRule); 6709 6710 ENinePieceImageRule verticalRule; 6711 switch (borderImage->m_verticalSizeRule) { 6712 case CSSValueStretch: 6713 verticalRule = StretchImageRule; 6714 break; 6715 case CSSValueRound: 6716 verticalRule = RoundImageRule; 6717 break; 6718 default: // CSSValueRepeat 6719 verticalRule = RepeatImageRule; 6720 break; 6721 } 6722 image.setVerticalRule(verticalRule); 6723} 6724 6725void CSSStyleSelector::checkForTextSizeAdjust() 6726{ 6727 if (m_style->textSizeAdjust()) 6728 return; 6729 6730 /* TODO: Remove this when a fix for webkit bug 56543 is submitted and can 6731 * be cherry picked. 6732 * This is a quick fix for Android to prevent sites from using 6733 * -webkit-text-size-adjust: none; which breaks font size accessibility 6734 * options on all platforms. The purpose of the property is to prevent 6735 * the automatic font size changes done by platforms like iOS when the 6736 * rotation changes. Since Android doesn't do this, we can safely ignore 6737 * the 'none' option. 6738 */ 6739#if PLATFORM(ANDROID) 6740 return; 6741#endif 6742 6743 FontDescription newFontDescription(m_style->fontDescription()); 6744 newFontDescription.setComputedSize(newFontDescription.specifiedSize()); 6745 m_style->setFontDescription(newFontDescription); 6746} 6747 6748void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle) 6749{ 6750 if (style->effectiveZoom() == parentStyle->effectiveZoom()) 6751 return; 6752 6753 const FontDescription& childFont = style->fontDescription(); 6754 FontDescription newFontDescription(childFont); 6755 setFontSize(newFontDescription, childFont.specifiedSize()); 6756 style->setFontDescription(newFontDescription); 6757} 6758 6759void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle) 6760{ 6761 const FontDescription& childFont = style->fontDescription(); 6762 6763 if (childFont.isAbsoluteSize() || !parentStyle) 6764 return; 6765 6766 const FontDescription& parentFont = parentStyle->fontDescription(); 6767 if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize()) 6768 return; 6769 6770 // For now, lump all families but monospace together. 6771 if (childFont.genericFamily() != FontDescription::MonospaceFamily && 6772 parentFont.genericFamily() != FontDescription::MonospaceFamily) 6773 return; 6774 6775 // We know the parent is monospace or the child is monospace, and that font 6776 // size was unspecified. We want to scale our font size as appropriate. 6777 // If the font uses a keyword size, then we refetch from the table rather than 6778 // multiplying by our scale factor. 6779 float size; 6780 if (childFont.keywordSize()) 6781 size = fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize()); 6782 else { 6783 Settings* settings = m_checker.m_document->settings(); 6784 float fixedScaleFactor = settings 6785 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize() 6786 : 1; 6787 size = parentFont.useFixedDefaultSize() ? 6788 childFont.specifiedSize() / fixedScaleFactor : 6789 childFont.specifiedSize() * fixedScaleFactor; 6790 } 6791 6792 FontDescription newFontDescription(childFont); 6793 setFontSize(newFontDescription, size); 6794 style->setFontDescription(newFontDescription); 6795} 6796 6797void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) 6798{ 6799 fontDescription.setSpecifiedSize(size); 6800 6801 bool useSVGZoomRules = m_element && m_element->isSVGElement(); 6802 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); 6803} 6804 6805float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules) 6806{ 6807 // Text with a 0px font size should not be visible and therefore needs to be 6808 // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect 6809 // rendering. This is also compatible with other browsers that have minimum 6810 // font size settings (e.g. Firefox). 6811 if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon()) 6812 return 0.0f; 6813 6814 float zoomFactor = 1.0f; 6815 if (!useSVGZoomRules) { 6816 zoomFactor = style->effectiveZoom(); 6817 if (Frame* frame = document->frame()) 6818 zoomFactor *= frame->textZoomFactor(); 6819 } 6820 6821 // We support two types of minimum font size. The first is a hard override that applies to 6822 // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum" 6823 // that is applied only when the Web page can't know what size it really asked for, e.g., 6824 // when it uses logical sizes like "small" or expresses the font-size as a percentage of 6825 // the user's default font setting. 6826 6827 // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable. 6828 // However we always allow the page to set an explicit pixel size that is smaller, 6829 // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum). 6830 6831 Settings* settings = document->settings(); 6832 if (!settings) 6833 return 1.0f; 6834 6835 int minSize = settings->minimumFontSize(); 6836 int minLogicalSize = settings->minimumLogicalFontSize(); 6837 float zoomedSize = specifiedSize * zoomFactor; 6838 6839 // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small. 6840 if (zoomedSize < minSize) 6841 zoomedSize = minSize; 6842 6843 // Now apply the "smart minimum." This minimum is also only applied if we're still too small 6844 // after zooming. The font size must either be relative to the user default or the original size 6845 // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive 6846 // doing so won't disrupt the layout. 6847 if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize)) 6848 zoomedSize = minLogicalSize; 6849 6850 // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various 6851 // platforms (I'm looking at you, Windows.) 6852 return min(1000000.0f, zoomedSize); 6853} 6854 6855const int fontSizeTableMax = 16; 6856const int fontSizeTableMin = 9; 6857const int totalKeywords = 8; 6858 6859// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML. 6860static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = 6861{ 6862 { 9, 9, 9, 9, 11, 14, 18, 28 }, 6863 { 9, 9, 9, 10, 12, 15, 20, 31 }, 6864 { 9, 9, 9, 11, 13, 17, 22, 34 }, 6865 { 9, 9, 10, 12, 14, 18, 24, 37 }, 6866 { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13) 6867 { 9, 9, 11, 14, 17, 21, 28, 42 }, 6868 { 9, 10, 12, 15, 17, 23, 30, 45 }, 6869 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) 6870}; 6871// HTML 1 2 3 4 5 6 7 6872// CSS xxs xs s m l xl xxl 6873// | 6874// user pref 6875 6876// Strict mode table matches MacIE and Mozilla's settings exactly. 6877static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = 6878{ 6879 { 9, 9, 9, 9, 11, 14, 18, 27 }, 6880 { 9, 9, 9, 10, 12, 15, 20, 30 }, 6881 { 9, 9, 10, 11, 13, 17, 22, 33 }, 6882 { 9, 9, 10, 12, 14, 18, 24, 36 }, 6883 { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13) 6884 { 9, 10, 12, 14, 17, 21, 28, 42 }, 6885 { 9, 10, 13, 15, 18, 23, 30, 45 }, 6886 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) 6887}; 6888// HTML 1 2 3 4 5 6 7 6889// CSS xxs xs s m l xl xxl 6890// | 6891// user pref 6892 6893// For values outside the range of the table, we use Todd Fahrner's suggested scale 6894// factors for each keyword value. 6895static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f }; 6896 6897float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool shouldUseFixedDefaultSize) 6898{ 6899 Settings* settings = document->settings(); 6900 if (!settings) 6901 return 1.0f; 6902 6903 bool quirksMode = document->inQuirksMode(); 6904 int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize(); 6905 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { 6906 // Look up the entry in the table. 6907 int row = mediumSize - fontSizeTableMin; 6908 int col = (keyword - CSSValueXxSmall); 6909 return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col]; 6910 } 6911 6912 // Value is outside the range of the table. Apply the scale factor instead. 6913 float minLogicalSize = max(settings->minimumLogicalFontSize(), 1); 6914 return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize); 6915} 6916 6917template<typename T> 6918static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier) 6919{ 6920 // Ignore table[0] because xx-small does not correspond to any legacy font size. 6921 for (int i = 1; i < totalKeywords - 1; i++) { 6922 if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier) 6923 return i; 6924 } 6925 return totalKeywords - 1; 6926} 6927 6928int CSSStyleSelector::legacyFontSize(Document* document, int pixelFontSize, bool shouldUseFixedDefaultSize) 6929{ 6930 Settings* settings = document->settings(); 6931 if (!settings) 6932 return 1; 6933 6934 bool quirksMode = document->inQuirksMode(); 6935 int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize(); 6936 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { 6937 int row = mediumSize - fontSizeTableMin; 6938 return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1); 6939 } 6940 6941 return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize); 6942} 6943 6944float CSSStyleSelector::largerFontSize(float size, bool) const 6945{ 6946 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to 6947 // the next size level. 6948 return size * 1.2f; 6949} 6950 6951float CSSStyleSelector::smallerFontSize(float size, bool) const 6952{ 6953 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to 6954 // the next size level. 6955 return size / 1.2f; 6956} 6957 6958static Color colorForCSSValue(int cssValueId) 6959{ 6960 struct ColorValue { 6961 int cssValueId; 6962 RGBA32 color; 6963 }; 6964 6965 static const ColorValue colorValues[] = { 6966 { CSSValueAqua, 0xFF00FFFF }, 6967 { CSSValueBlack, 0xFF000000 }, 6968 { CSSValueBlue, 0xFF0000FF }, 6969 { CSSValueFuchsia, 0xFFFF00FF }, 6970 { CSSValueGray, 0xFF808080 }, 6971 { CSSValueGreen, 0xFF008000 }, 6972 { CSSValueGrey, 0xFF808080 }, 6973 { CSSValueLime, 0xFF00FF00 }, 6974 { CSSValueMaroon, 0xFF800000 }, 6975 { CSSValueNavy, 0xFF000080 }, 6976 { CSSValueOlive, 0xFF808000 }, 6977 { CSSValueOrange, 0xFFFFA500 }, 6978 { CSSValuePurple, 0xFF800080 }, 6979 { CSSValueRed, 0xFFFF0000 }, 6980 { CSSValueSilver, 0xFFC0C0C0 }, 6981 { CSSValueTeal, 0xFF008080 }, 6982 { CSSValueTransparent, 0x00000000 }, 6983 { CSSValueWhite, 0xFFFFFFFF }, 6984 { CSSValueYellow, 0xFFFFFF00 }, 6985 { 0, 0 } 6986 }; 6987 6988 for (const ColorValue* col = colorValues; col->cssValueId; ++col) { 6989 if (col->cssValueId == cssValueId) 6990 return col->color; 6991 } 6992 return RenderTheme::defaultTheme()->systemColor(cssValueId); 6993} 6994 6995Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) const 6996{ 6997 Color col; 6998 int ident = primitiveValue->getIdent(); 6999 if (ident) { 7000 if (ident == CSSValueWebkitText) 7001 col = m_element->document()->textColor(); 7002 else if (ident == CSSValueWebkitLink) 7003 col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor(); 7004 else if (ident == CSSValueWebkitActivelink) 7005 col = m_element->document()->activeLinkColor(); 7006 else if (ident == CSSValueWebkitFocusRingColor) 7007 col = RenderTheme::focusRingColor(); 7008 else if (ident == CSSValueCurrentcolor) 7009 col = m_style->color(); 7010 else 7011 col = colorForCSSValue(ident); 7012 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) 7013 col.setRGB(primitiveValue->getRGBA32Value()); 7014 return col; 7015} 7016 7017bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) const 7018{ 7019 return m_selectorAttrs.contains(attrname.impl()); 7020} 7021 7022void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result) 7023{ 7024 m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result)); 7025} 7026 7027bool CSSStyleSelector::affectedByViewportChange() const 7028{ 7029 unsigned s = m_viewportDependentMediaQueryResults.size(); 7030 for (unsigned i = 0; i < s; i++) { 7031 if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result) 7032 return true; 7033 } 7034 return false; 7035} 7036 7037void CSSStyleSelector::SelectorChecker::allVisitedStateChanged() 7038{ 7039 if (m_linksCheckedForVisitedState.isEmpty()) 7040 return; 7041 for (Node* node = m_document; node; node = node->traverseNextNode()) { 7042 if (node->isLink()) 7043 node->setNeedsStyleRecalc(); 7044 } 7045} 7046 7047void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash) 7048{ 7049 if (!m_linksCheckedForVisitedState.contains(visitedHash)) 7050 return; 7051 for (Node* node = m_document; node; node = node->traverseNextNode()) { 7052 const AtomicString* attr = linkAttribute(node); 7053 if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash) 7054 node->setNeedsStyleRecalc(); 7055 } 7056} 7057 7058static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type) 7059{ 7060 switch (type) { 7061 case WebKitCSSTransformValue::ScaleTransformOperation: return TransformOperation::SCALE; 7062 case WebKitCSSTransformValue::ScaleXTransformOperation: return TransformOperation::SCALE_X; 7063 case WebKitCSSTransformValue::ScaleYTransformOperation: return TransformOperation::SCALE_Y; 7064 case WebKitCSSTransformValue::ScaleZTransformOperation: return TransformOperation::SCALE_Z; 7065 case WebKitCSSTransformValue::Scale3DTransformOperation: return TransformOperation::SCALE_3D; 7066 case WebKitCSSTransformValue::TranslateTransformOperation: return TransformOperation::TRANSLATE; 7067 case WebKitCSSTransformValue::TranslateXTransformOperation: return TransformOperation::TRANSLATE_X; 7068 case WebKitCSSTransformValue::TranslateYTransformOperation: return TransformOperation::TRANSLATE_Y; 7069 case WebKitCSSTransformValue::TranslateZTransformOperation: return TransformOperation::TRANSLATE_Z; 7070 case WebKitCSSTransformValue::Translate3DTransformOperation: return TransformOperation::TRANSLATE_3D; 7071 case WebKitCSSTransformValue::RotateTransformOperation: return TransformOperation::ROTATE; 7072 case WebKitCSSTransformValue::RotateXTransformOperation: return TransformOperation::ROTATE_X; 7073 case WebKitCSSTransformValue::RotateYTransformOperation: return TransformOperation::ROTATE_Y; 7074 case WebKitCSSTransformValue::RotateZTransformOperation: return TransformOperation::ROTATE_Z; 7075 case WebKitCSSTransformValue::Rotate3DTransformOperation: return TransformOperation::ROTATE_3D; 7076 case WebKitCSSTransformValue::SkewTransformOperation: return TransformOperation::SKEW; 7077 case WebKitCSSTransformValue::SkewXTransformOperation: return TransformOperation::SKEW_X; 7078 case WebKitCSSTransformValue::SkewYTransformOperation: return TransformOperation::SKEW_Y; 7079 case WebKitCSSTransformValue::MatrixTransformOperation: return TransformOperation::MATRIX; 7080 case WebKitCSSTransformValue::Matrix3DTransformOperation: return TransformOperation::MATRIX_3D; 7081 case WebKitCSSTransformValue::PerspectiveTransformOperation: return TransformOperation::PERSPECTIVE; 7082 case WebKitCSSTransformValue::UnknownTransformOperation: return TransformOperation::NONE; 7083 } 7084 return TransformOperation::NONE; 7085} 7086 7087bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations) 7088{ 7089 if (!inValue || !inValue->isValueList()) { 7090 outOperations.clear(); 7091 return false; 7092 } 7093 7094 float zoomFactor = style ? style->effectiveZoom() : 1; 7095 TransformOperations operations; 7096 CSSValueList* list = static_cast<CSSValueList*>(inValue); 7097 unsigned size = list->length(); 7098 for (unsigned i = 0; i < size; i++) { 7099 CSSValue* currValue = list->itemWithoutBoundsCheck(i); 7100 if (!currValue->isWebKitCSSTransformValue()) 7101 continue; 7102 7103 WebKitCSSTransformValue* transformValue = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i)); 7104 if (!transformValue->length()) 7105 continue; 7106 7107 bool haveNonPrimitiveValue = false; 7108 for (unsigned j = 0; j < transformValue->length(); ++j) { 7109 if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { 7110 haveNonPrimitiveValue = true; 7111 break; 7112 } 7113 } 7114 if (haveNonPrimitiveValue) 7115 continue; 7116 7117 CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0)); 7118 7119 switch (transformValue->operationType()) { 7120 case WebKitCSSTransformValue::ScaleTransformOperation: 7121 case WebKitCSSTransformValue::ScaleXTransformOperation: 7122 case WebKitCSSTransformValue::ScaleYTransformOperation: { 7123 double sx = 1.0; 7124 double sy = 1.0; 7125 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation) 7126 sy = firstValue->getDoubleValue(); 7127 else { 7128 sx = firstValue->getDoubleValue(); 7129 if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) { 7130 if (transformValue->length() > 1) { 7131 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7132 sy = secondValue->getDoubleValue(); 7133 } else 7134 sy = sx; 7135 } 7136 } 7137 operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType()))); 7138 break; 7139 } 7140 case WebKitCSSTransformValue::ScaleZTransformOperation: 7141 case WebKitCSSTransformValue::Scale3DTransformOperation: { 7142 double sx = 1.0; 7143 double sy = 1.0; 7144 double sz = 1.0; 7145 if (transformValue->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation) 7146 sz = firstValue->getDoubleValue(); 7147 else if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation) 7148 sy = firstValue->getDoubleValue(); 7149 else { 7150 sx = firstValue->getDoubleValue(); 7151 if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) { 7152 if (transformValue->length() > 2) { 7153 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2)); 7154 sz = thirdValue->getDoubleValue(); 7155 } 7156 if (transformValue->length() > 1) { 7157 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7158 sy = secondValue->getDoubleValue(); 7159 } else 7160 sy = sx; 7161 } 7162 } 7163 operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType()))); 7164 break; 7165 } 7166 case WebKitCSSTransformValue::TranslateTransformOperation: 7167 case WebKitCSSTransformValue::TranslateXTransformOperation: 7168 case WebKitCSSTransformValue::TranslateYTransformOperation: { 7169 bool ok = true; 7170 Length tx = Length(0, Fixed); 7171 Length ty = Length(0, Fixed); 7172 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) 7173 ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7174 else { 7175 tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7176 if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { 7177 if (transformValue->length() > 1) { 7178 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7179 ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok); 7180 } 7181 } 7182 } 7183 7184 if (!ok) 7185 return false; 7186 7187 operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType()))); 7188 break; 7189 } 7190 case WebKitCSSTransformValue::TranslateZTransformOperation: 7191 case WebKitCSSTransformValue::Translate3DTransformOperation: { 7192 bool ok = true; 7193 Length tx = Length(0, Fixed); 7194 Length ty = Length(0, Fixed); 7195 Length tz = Length(0, Fixed); 7196 if (transformValue->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation) 7197 tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7198 else if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) 7199 ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7200 else { 7201 tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7202 if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { 7203 if (transformValue->length() > 2) { 7204 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2)); 7205 tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor, &ok); 7206 } 7207 if (transformValue->length() > 1) { 7208 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7209 ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok); 7210 } 7211 } 7212 } 7213 7214 if (!ok) 7215 return false; 7216 7217 operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); 7218 break; 7219 } 7220 case WebKitCSSTransformValue::RotateTransformOperation: { 7221 double angle = firstValue->getDoubleValue(); 7222 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) 7223 angle = rad2deg(angle); 7224 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) 7225 angle = grad2deg(angle); 7226 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) 7227 angle = turn2deg(angle); 7228 7229 operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); 7230 break; 7231 } 7232 case WebKitCSSTransformValue::RotateXTransformOperation: 7233 case WebKitCSSTransformValue::RotateYTransformOperation: 7234 case WebKitCSSTransformValue::RotateZTransformOperation: { 7235 double x = 0; 7236 double y = 0; 7237 double z = 0; 7238 double angle = firstValue->getDoubleValue(); 7239 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) 7240 angle = rad2deg(angle); 7241 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) 7242 angle = grad2deg(angle); 7243 7244 if (transformValue->operationType() == WebKitCSSTransformValue::RotateXTransformOperation) 7245 x = 1; 7246 else if (transformValue->operationType() == WebKitCSSTransformValue::RotateYTransformOperation) 7247 y = 1; 7248 else 7249 z = 1; 7250 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); 7251 break; 7252 } 7253 case WebKitCSSTransformValue::Rotate3DTransformOperation: { 7254 if (transformValue->length() < 4) 7255 break; 7256 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7257 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2)); 7258 CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3)); 7259 double x = firstValue->getDoubleValue(); 7260 double y = secondValue->getDoubleValue(); 7261 double z = thirdValue->getDoubleValue(); 7262 double angle = fourthValue->getDoubleValue(); 7263 if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) 7264 angle = rad2deg(angle); 7265 else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) 7266 angle = grad2deg(angle); 7267 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); 7268 break; 7269 } 7270 case WebKitCSSTransformValue::SkewTransformOperation: 7271 case WebKitCSSTransformValue::SkewXTransformOperation: 7272 case WebKitCSSTransformValue::SkewYTransformOperation: { 7273 double angleX = 0; 7274 double angleY = 0; 7275 double angle = firstValue->getDoubleValue(); 7276 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) 7277 angle = rad2deg(angle); 7278 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) 7279 angle = grad2deg(angle); 7280 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) 7281 angle = turn2deg(angle); 7282 if (transformValue->operationType() == WebKitCSSTransformValue::SkewYTransformOperation) 7283 angleY = angle; 7284 else { 7285 angleX = angle; 7286 if (transformValue->operationType() == WebKitCSSTransformValue::SkewTransformOperation) { 7287 if (transformValue->length() > 1) { 7288 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); 7289 angleY = secondValue->getDoubleValue(); 7290 if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) 7291 angleY = rad2deg(angleY); 7292 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) 7293 angleY = grad2deg(angleY); 7294 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) 7295 angleY = turn2deg(angleY); 7296 } 7297 } 7298 } 7299 operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType()))); 7300 break; 7301 } 7302 case WebKitCSSTransformValue::MatrixTransformOperation: { 7303 if (transformValue->length() < 6) 7304 break; 7305 double a = firstValue->getDoubleValue(); 7306 double b = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(); 7307 double c = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(); 7308 double d = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(); 7309 double e = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(); 7310 double f = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(); 7311 operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); 7312 break; 7313 } 7314 case WebKitCSSTransformValue::Matrix3DTransformOperation: { 7315 if (transformValue->length() < 16) 7316 break; 7317 TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(), 7318 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(), 7319 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(), 7320 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(), 7321 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(), 7322 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(), 7323 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(), 7324 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(), 7325 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(), 7326 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(), 7327 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(), 7328 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(), 7329 zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(), 7330 zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(), 7331 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(), 7332 static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue()); 7333 operations.operations().append(Matrix3DTransformOperation::create(matrix)); 7334 break; 7335 } 7336 case WebKitCSSTransformValue::PerspectiveTransformOperation: { 7337 bool ok = true; 7338 Length p = Length(0, Fixed); 7339 if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType())) 7340 p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); 7341 else { 7342 // This is a quirk that should go away when 3d transforms are finalized. 7343 double val = firstValue->getDoubleValue(); 7344 ok = val >= 0; 7345 val = clampToPositiveInteger(val); 7346 p = Length(static_cast<int>(val), Fixed); 7347 } 7348 7349 if (!ok) 7350 return false; 7351 7352 operations.operations().append(PerspectiveTransformOperation::create(p)); 7353 break; 7354 } 7355 case WebKitCSSTransformValue::UnknownTransformOperation: 7356 ASSERT_NOT_REACHED(); 7357 break; 7358 } 7359 } 7360 7361 outOperations = operations; 7362 return true; 7363} 7364 7365void CSSStyleSelector::loadPendingImages() 7366{ 7367 if (m_pendingImageProperties.isEmpty()) 7368 return; 7369 7370 HashSet<int>::const_iterator end = m_pendingImageProperties.end(); 7371 for (HashSet<int>::const_iterator it = m_pendingImageProperties.begin(); it != end; ++it) { 7372 CSSPropertyID currentProperty = static_cast<CSSPropertyID>(*it); 7373 7374 CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader(); 7375 7376 switch (currentProperty) { 7377 case CSSPropertyBackgroundImage: { 7378 for (FillLayer* backgroundLayer = m_style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) { 7379 if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage()) { 7380 CSSImageValue* imageValue = static_cast<StylePendingImage*>(backgroundLayer->image())->cssImageValue(); 7381 backgroundLayer->setImage(imageValue->cachedImage(cachedResourceLoader)); 7382 } 7383 } 7384 break; 7385 } 7386 7387 case CSSPropertyContent: { 7388 for (ContentData* contentData = const_cast<ContentData*>(m_style->contentData()); contentData; contentData = contentData->next()) { 7389 if (contentData->isImage() && contentData->image()->isPendingImage()) { 7390 CSSImageValue* imageValue = static_cast<StylePendingImage*>(contentData->image())->cssImageValue(); 7391 if (StyleCachedImage* cachedImage = imageValue->cachedImage(cachedResourceLoader)) 7392 contentData->setImage(cachedImage); 7393 } 7394 } 7395 break; 7396 } 7397 7398 case CSSPropertyCursor: { 7399 if (CursorList* cursorList = m_style->cursors()) { 7400 for (size_t i = 0; i < cursorList->size(); ++i) { 7401 CursorData& currentCursor = cursorList->at(i); 7402 if (StyleImage* image = currentCursor.image()) { 7403 if (image->isPendingImage()) { 7404 CSSImageValue* imageValue = static_cast<StylePendingImage*>(image)->cssImageValue(); 7405 currentCursor.setImage(imageValue->cachedImage(cachedResourceLoader)); 7406 } 7407 } 7408 } 7409 } 7410 break; 7411 } 7412 7413 case CSSPropertyListStyleImage: { 7414 if (m_style->listStyleImage() && m_style->listStyleImage()->isPendingImage()) { 7415 CSSImageValue* imageValue = static_cast<StylePendingImage*>(m_style->listStyleImage())->cssImageValue(); 7416 m_style->setListStyleImage(imageValue->cachedImage(cachedResourceLoader)); 7417 } 7418 break; 7419 } 7420 7421 case CSSPropertyWebkitBorderImage: { 7422 const NinePieceImage& borderImage = m_style->borderImage(); 7423 if (borderImage.image() && borderImage.image()->isPendingImage()) { 7424 CSSImageValue* imageValue = static_cast<StylePendingImage*>(borderImage.image())->cssImageValue(); 7425 m_style->setBorderImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), borderImage.slices(), borderImage.horizontalRule(), borderImage.verticalRule())); 7426 } 7427 break; 7428 } 7429 7430 case CSSPropertyWebkitBoxReflect: { 7431 if (StyleReflection* reflection = m_style->boxReflect()) { 7432 const NinePieceImage& maskImage = reflection->mask(); 7433 if (maskImage.image() && maskImage.image()->isPendingImage()) { 7434 CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskImage.image())->cssImageValue(); 7435 reflection->setMask(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskImage.slices(), maskImage.horizontalRule(), maskImage.verticalRule())); 7436 } 7437 } 7438 break; 7439 } 7440 7441 case CSSPropertyWebkitMaskBoxImage: { 7442 const NinePieceImage& maskBoxImage = m_style->maskBoxImage(); 7443 if (maskBoxImage.image() && maskBoxImage.image()->isPendingImage()) { 7444 CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskBoxImage.image())->cssImageValue(); 7445 m_style->setMaskBoxImage(NinePieceImage(imageValue->cachedImage(cachedResourceLoader), maskBoxImage.slices(), maskBoxImage.horizontalRule(), maskBoxImage.verticalRule())); 7446 } 7447 break; 7448 } 7449 7450 case CSSPropertyWebkitMaskImage: { 7451 for (FillLayer* maskLayer = m_style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) { 7452 if (maskLayer->image() && maskLayer->image()->isPendingImage()) { 7453 CSSImageValue* imageValue = static_cast<StylePendingImage*>(maskLayer->image())->cssImageValue(); 7454 maskLayer->setImage(imageValue->cachedImage(cachedResourceLoader)); 7455 } 7456 } 7457 break; 7458 } 7459 default: 7460 ASSERT_NOT_REACHED(); 7461 } 7462 } 7463 7464 m_pendingImageProperties.clear(); 7465} 7466 7467} // namespace WebCore 7468