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