2 * This file is part of the CSS implementation for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
6 * (C) 2006 Nicholas Shanks (webkit@nickshanks.com)
7 * Copyright (C) 2005, 2006 Apple Computer, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 #include "cssstyleselector.h"
28 #include "CSSBorderImageValue.h"
29 #include "CSSImageValue.h"
30 #include "CSSImportRule.h"
31 #include "CSSMediaRule.h"
32 #include "CSSProperty.h"
33 #include "CSSPropertyNames.h"
34 #include "CSSRuleList.h"
35 #include "CSSSelector.h"
36 #include "CSSStyleRule.h"
37 #include "CSSStyleSheet.h"
38 #include "CSSValueKeywords.h"
39 #include "CSSValueList.h"
40 #include "CachedImage.h"
41 #include "DashboardRegion.h"
42 #include "FontFamilyValue.h"
43 #include "FontValue.h"
45 #include "HTMLDocument.h"
46 #include "HTMLElement.h"
47 #include "HTMLInputElement.h"
48 #include "HTMLNames.h"
50 #include "KWQKHTMLSettings.h"
51 #include "MediaList.h"
52 #include "MediaQueryEvaluator.h"
55 #include "RenderTheme.h"
56 #include "StyleSheetList.h"
57 #include "UserAgentStyleSheets.h"
59 #include "ShadowValue.h"
65 using namespace HTMLNames;
67 // #define STYLE_SHARING_STATS 1
69 #define HANDLE_INHERIT(prop, Prop) \
71 style->set##Prop(parentStyle->prop()); \
75 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
76 HANDLE_INHERIT(prop, Prop) \
78 style->set##Prop(RenderStyle::initial##Prop()); \
82 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
83 HANDLE_INHERIT(prop, Prop) \
85 style->set##Prop(RenderStyle::initial##Value());\
89 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
91 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
92 BackgroundLayer* prevChild = 0; \
93 const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
94 while (currParent && currParent->is##Prop##Set()) { \
96 /* Need to make a new layer.*/ \
97 currChild = new BackgroundLayer(); \
98 prevChild->setNext(currChild); \
100 currChild->set##Prop(currParent->prop()); \
101 prevChild = currChild; \
102 currChild = prevChild->next(); \
103 currParent = currParent->next(); \
106 while (currChild) { \
107 /* Reset any remaining layers to not have the property set. */ \
108 currChild->clear##Prop(); \
109 currChild = currChild->next(); \
114 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
115 currChild->set##Prop(RenderStyle::initial##Prop()); \
116 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
117 currChild->clear##Prop(); \
121 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
122 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
123 if (!value->isPrimitiveValue() && !value->isValueList()) \
125 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
126 BackgroundLayer* prevChild = 0; \
127 if (value->isPrimitiveValue()) { \
128 map##Prop(currChild, value); \
129 currChild = currChild->next(); \
132 /* Walk each value and put it into a layer, creating new layers as needed. */ \
133 CSSValueList* valueList = static_cast<CSSValueList*>(value); \
134 for (unsigned int i = 0; i < valueList->length(); i++) { \
136 /* Need to make a new layer to hold this value */ \
137 currChild = new BackgroundLayer(); \
138 prevChild->setNext(currChild); \
140 map##Prop(currChild, valueList->item(i)); \
141 prevChild = currChild; \
142 currChild = currChild->next(); \
145 while (currChild) { \
146 /* Reset all remaining layers to not have the property set. */ \
147 currChild->clear##Prop(); \
148 currChild = currChild->next(); \
151 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
152 if (id == propID) { \
153 style->set##Prop(parentStyle->prop()); \
157 #define HANDLE_INITIAL_COND(propID, Prop) \
158 if (id == propID) { \
159 style->set##Prop(RenderStyle::initial##Prop()); \
163 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
164 if (id == propID) { \
165 style->set##Prop(RenderStyle::initial##Value()); \
175 typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
177 void addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium);
179 void addRule(CSSStyleRule* rule, CSSSelector* sel);
180 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
181 CSSStyleRule* rule, CSSSelector* sel);
183 CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
184 CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
185 CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
186 CSSRuleDataList* getUniversalRules() { return m_universalRules; }
189 AtomRuleMap m_idRules;
190 AtomRuleMap m_classRules;
191 AtomRuleMap m_tagRules;
192 CSSRuleDataList* m_universalRules;
194 unsigned m_ruleCount;
197 CSSRuleSet* CSSStyleSelector::defaultStyle = 0;
198 CSSRuleSet* CSSStyleSelector::defaultQuirksStyle = 0;
199 CSSRuleSet* CSSStyleSelector::defaultPrintStyle = 0;
200 CSSRuleSet* CSSStyleSelector::defaultViewSourceStyle = 0;
202 CSSStyleSheet* CSSStyleSelector::defaultSheet = 0;
203 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0;
204 CSSStyleSheet* CSSStyleSelector::quirksSheet = 0;
205 CSSStyleSheet* CSSStyleSelector::viewSourceSheet = 0;
208 CSSStyleSheet *CSSStyleSelector::svgSheet = 0;
211 static CSSStyleSelector::Encodedurl *currentEncodedURL = 0;
212 static PseudoState pseudoState;
214 CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList *styleSheets, bool _strictParsing)
219 strictParsing = _strictParsing;
220 settings = view ? view->frame()->settings() : 0;
227 // construct document root element default style. this is needed
228 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
229 // This is here instead of constructor, because when constructor is run,
230 // document doesn't have documentElement
231 // NOTE: this assumes that element that gets passed to styleForElement -call
232 // is always from the document that owns the style selector
234 m_medium = new MediaQueryEvaluator(view->mediaType());
236 m_medium = new MediaQueryEvaluator("all");
238 Element* root = doc->documentElement();
241 m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap
243 if (m_rootDefaultStyle && view) {
245 m_medium = new MediaQueryEvaluator(view->mediaType(), view, m_rootDefaultStyle);
249 // FIXME: This sucks! The user sheet is reparsed every time!
250 if (!userStyleSheet.isEmpty()) {
251 m_userSheet = new CSSStyleSheet(doc);
252 m_userSheet->parseString(userStyleSheet, strictParsing);
254 m_userStyle = new CSSRuleSet();
255 m_userStyle->addRulesFromSheet(m_userSheet, m_medium);
258 // add stylesheets from document
259 m_authorStyle = new CSSRuleSet();
261 DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets);
262 for (; it.current(); ++it)
263 if (it.current()->isCSSStyleSheet() && !it.current()->disabled())
264 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), m_medium);
268 CSSStyleSelector::CSSStyleSelector(CSSStyleSheet *sheet)
274 FrameView *view = sheet->doc()->view();
277 m_medium = new MediaQueryEvaluator(view->mediaType());
279 m_medium = new MediaQueryEvaluator("all");
281 Element* root = sheet->doc()->documentElement();
283 m_rootDefaultStyle = styleForElement(root, 0, false, true);
285 if (m_rootDefaultStyle && view) {
287 m_medium = new MediaQueryEvaluator(view->mediaType(), view, m_rootDefaultStyle);
290 m_authorStyle = new CSSRuleSet();
291 m_authorStyle->addRulesFromSheet(sheet, m_medium);
294 void CSSStyleSelector::init()
298 m_matchedRules.clear();
299 m_matchedDecls.clear();
301 m_collectRulesOnly = false;
302 m_rootDefaultStyle = 0;
306 void CSSStyleSelector::setEncodedURL(const KURL& url)
310 u.setQuery(DeprecatedString::null);
311 u.setRef(DeprecatedString::null);
312 encodedurl.file = u.url();
313 int pos = encodedurl.file.findRev('/');
314 encodedurl.path = encodedurl.file;
316 encodedurl.path.truncate(pos);
317 encodedurl.path += '/';
319 u.setPath(DeprecatedString::null);
320 encodedurl.host = u.url();
323 CSSStyleSelector::~CSSStyleSelector()
326 ::delete m_rootDefaultStyle;
328 delete m_authorStyle;
333 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
335 CSSStyleSheet* const parent = 0;
336 CSSStyleSheet* sheet = new CSSStyleSheet(parent);
337 sheet->ref(); // leak the sheet on purpose since it will be stored in a global variable
338 sheet->parseString(String(characters, size));
342 template<typename T> CSSStyleSheet* parseUASheet(const T& array)
344 return parseUASheet(array, sizeof(array));
347 void CSSStyleSelector::loadDefaultStyle()
352 defaultStyle = new CSSRuleSet;
353 defaultPrintStyle = new CSSRuleSet;
354 defaultQuirksStyle = new CSSRuleSet;
355 defaultViewSourceStyle = new CSSRuleSet;
357 MediaQueryEvaluator screenEval("screen");
358 MediaQueryEvaluator printEval("print");
360 // Strict-mode rules.
361 defaultSheet = parseUASheet(html4UserAgentStyleSheet);
362 defaultStyle->addRulesFromSheet(defaultSheet, &screenEval);
363 defaultPrintStyle->addRulesFromSheet(defaultSheet, &printEval);
367 svgSheet = parseUASheet(svgUserAgentStyleSheet);
368 defaultStyle->addRulesFromSheet(svgSheet, &screenEval);
369 defaultPrintStyle->addRulesFromSheet(svgSheet, &printEval);
372 // Quirks-mode rules.
373 quirksSheet = parseUASheet(quirksUserAgentStyleSheet);
374 defaultQuirksStyle->addRulesFromSheet(quirksSheet, &screenEval);
376 // View source rules.
377 viewSourceSheet = parseUASheet(sourceUserAgentStyleSheet);
378 defaultViewSourceStyle->addRulesFromSheet(viewSourceSheet, &screenEval);
381 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
383 m_matchedRules.clear();
385 if (!rules || !element)
388 // We need to collect the rules for id, class, tag, and everything else into a buffer and
389 // then sort the buffer.
390 if (element->hasID())
391 matchRulesForList(rules->getIDRules(element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);
392 if (element->hasClass()) {
393 for (const AtomicStringList* singleClass = element->getClassList(); singleClass; singleClass = singleClass->next())
394 matchRulesForList(rules->getClassRules(singleClass->string().impl()), firstRuleIndex, lastRuleIndex);
396 matchRulesForList(rules->getTagRules(element->localName().impl()), firstRuleIndex, lastRuleIndex);
397 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
399 // If we didn't match any rules, we're done.
400 if (m_matchedRules.isEmpty())
403 // Sort the set of matched rules.
404 sortMatchedRules(0, m_matchedRules.size());
406 // Now transfer the set of matched rules over to our list of decls.
407 if (!m_collectRulesOnly) {
408 for (unsigned i = 0; i < m_matchedRules.size(); i++)
409 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
411 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
413 m_ruleList = new CSSRuleList();
414 m_ruleList->append(m_matchedRules[i]->rule());
419 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
424 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
425 CSSStyleRule* rule = d->rule();
426 const AtomicString& localName = element->localName();
427 const AtomicString& selectorLocalName = d->selector()->tag.localName();
428 if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector(), element)) {
429 // If the rule has no properties to apply, then ignore it.
430 CSSMutableStyleDeclaration* decl = rule->declaration();
431 if (!decl || !decl->length())
434 // If we're matching normal rules, set a pseudo bit if
435 // we really just matched a pseudo-element.
436 if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO) {
437 if (m_collectRulesOnly)
439 style->setHasPseudoStyle(dynamicPseudo);
441 // Update our first/last rule indices in the matched rules array.
442 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
443 if (firstRuleIndex == -1)
444 firstRuleIndex = lastRuleIndex;
446 // Add this rule to our list of matched rules.
453 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
455 int spec1 = r1.selector()->specificity();
456 int spec2 = r2.selector()->specificity();
457 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
459 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
464 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
466 if (start >= end || (end - start == 1))
467 return; // Sanity check.
469 if (end - start <= 6) {
470 // Apply a bubble sort for smaller lists.
471 for (unsigned i = end - 1; i > start; i--) {
473 for (unsigned j = start; j < i; j++) {
474 CSSRuleData* elt = m_matchedRules[j];
475 CSSRuleData* elt2 = m_matchedRules[j + 1];
478 m_matchedRules[j] = elt2;
479 m_matchedRules[j + 1] = elt;
488 // Peform a merge sort for larger lists.
489 unsigned mid = (start + end) / 2;
490 sortMatchedRules(start, mid);
491 sortMatchedRules(mid, end);
493 CSSRuleData* elt = m_matchedRules[mid - 1];
494 CSSRuleData* elt2 = m_matchedRules[mid];
496 // Handle the fast common case (of equal specificity). The list may already
497 // be completely sorted.
501 // We have to merge sort. Ensure our merge buffer is big enough to hold
503 Vector<CSSRuleData*> rulesMergeBuffer;
504 rulesMergeBuffer.reserveCapacity(end - start);
509 elt = m_matchedRules[i1];
510 elt2 = m_matchedRules[i2];
512 while (i1 < mid || i2 < end) {
513 if (i1 < mid && (i2 == end || *elt <= *elt2)) {
514 rulesMergeBuffer.append(elt);
516 elt = m_matchedRules[i1];
518 rulesMergeBuffer.append(elt2);
520 elt2 = m_matchedRules[i2];
524 for (unsigned i = start; i < end; i++)
525 m_matchedRules[i] = rulesMergeBuffer[i - start];
528 void CSSStyleSelector::initElementAndPseudoState(Element* e)
531 if (element && element->isStyledElement())
532 styledElement = static_cast<StyledElement*>(element);
535 currentEncodedURL = &encodedurl;
536 pseudoState = PseudoUnknown;
539 void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent)
541 // set some variables we will need
542 pseudoStyle = RenderStyle::NOPSEUDO;
544 parentNode = e->parentNode();
546 parentStyle = defaultParent;
548 parentStyle = parentNode ? parentNode->renderStyle() : 0;
549 view = element->document()->view();
550 isXMLDoc = !element->document()->isHTMLDocument();
551 frame = element->document()->frame();
552 settings = frame ? frame->settings() : 0;
556 m_matchedRules.clear();
557 m_matchedDecls.clear();
564 // modified version of the one in kurl.cpp
565 static void cleanpath(DeprecatedString &path)
568 while ((pos = path.find("/../")) != -1) {
571 prev = path.findRev("/", pos -1);
572 // don't remove the host, i.e. http://foo.org/../foo.html
573 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
576 // matching directory found ?
577 path.remove(prev, pos- prev + 3);
581 // Don't remove "//" from an anchor identifier. -rjw
582 // Set refPos to -2 to mean "I haven't looked for the anchor yet".
583 // We don't want to waste a function call on the search for the the anchor
584 // in the vast majority of cases where there is no "//" in the path.
586 while ((pos = path.find("//", pos)) != -1) {
588 refPos = path.find("#");
589 if (refPos > 0 && pos >= refPos)
592 if (pos == 0 || path[pos-1] != ':')
597 while ((pos = path.find("/./")) != -1)
601 static void checkPseudoState(Element *e, bool checkVisited = true)
604 pseudoState = PseudoNone;
608 const AtomicString& attr = e->getAttribute(hrefAttr);
610 pseudoState = PseudoNone;
615 pseudoState = PseudoAnyLink;
619 QConstString cu(reinterpret_cast<const QChar*>(attr.characters()), attr.length());
620 DeprecatedString u = cu.string();
621 if (!u.contains("://")) {
623 u.prepend(currentEncodedURL->host);
624 else if (u[0] == '#')
625 u.prepend(currentEncodedURL->file);
627 u.prepend(currentEncodedURL->path);
630 pseudoState = historyContains(u) ? PseudoVisited : PseudoLink;
633 #ifdef STYLE_SHARING_STATS
634 static int fraction = 0;
635 static int total = 0;
638 const int siblingThreshold = 10;
640 Node* CSSStyleSelector::locateCousinList(Element* parent)
642 if (parent && parent->isStyledElement()) {
643 StyledElement* p = static_cast<StyledElement*>(parent);
644 if (!p->inlineStyleDecl() && !p->hasID()) {
645 Node* r = p->previousSibling();
647 RenderStyle* st = p->renderStyle();
649 if (r->renderStyle() == st)
650 return r->lastChild();
651 if (subcount++ == siblingThreshold)
653 r = r->previousSibling();
656 r = locateCousinList(static_cast<Element*>(parent->parentNode()));
658 if (r->renderStyle() == st)
659 return r->lastChild();
660 if (subcount++ == siblingThreshold)
662 r = r->previousSibling();
669 bool CSSStyleSelector::canShareStyleWithElement(Node* n)
671 if (n->isStyledElement()) {
672 StyledElement* s = static_cast<StyledElement*>(n);
673 RenderStyle* style = s->renderStyle();
674 if (style && !style->unique() &&
675 (s->tagQName() == element->tagQName()) && !s->hasID() &&
676 (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
677 (s->hasMappedAttributes() == styledElement->hasMappedAttributes()) &&
678 (s->isLink() == element->isLink()) &&
679 !style->affectedByAttributeSelectors() &&
680 (s->hovered() == element->hovered()) &&
681 (s->active() == element->active()) &&
682 (s->focused() == element->focused()) &&
683 (s->isEnabled() == element->isEnabled()) &&
684 (s->isIndeterminate() == element->isIndeterminate()) &&
685 (s->isChecked() == element->isChecked()) &&
686 (s != s->document()->getCSSTarget() && element != element->document()->getCSSTarget()) &&
687 (s->getAttribute(typeAttr) == element->getAttribute(typeAttr))) {
688 bool classesMatch = true;
690 const AtomicString& class1 = element->getAttribute(classAttr);
691 const AtomicString& class2 = s->getAttribute(classAttr);
692 classesMatch = (class1 == class2);
696 bool mappedAttrsMatch = true;
697 if (s->hasMappedAttributes())
698 mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(styledElement->mappedAttributes());
699 if (mappedAttrsMatch) {
700 bool linksMatch = true;
702 // We need to check to see if the visited state matches.
703 Color linkColor = element->document()->linkColor();
704 Color visitedColor = element->document()->visitedLinkColor();
705 if (pseudoState == PseudoUnknown)
706 checkPseudoState(element, style->pseudoState() != PseudoAnyLink ||
707 linkColor != visitedColor);
708 linksMatch = (pseudoState == style->pseudoState());
720 RenderStyle* CSSStyleSelector::locateSharedStyle()
722 if (styledElement && !styledElement->inlineStyleDecl() && !styledElement->hasID() &&
723 !styledElement->document()->usesSiblingRules()) {
724 // Check previous siblings.
727 for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
729 if (canShareStyleWithElement(n))
730 return n->renderStyle();
731 if (count++ == siblingThreshold)
733 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
736 n = locateCousinList(static_cast<Element*>(element->parentNode()));
738 if (canShareStyleWithElement(n))
739 return n->renderStyle();
740 if (count++ == siblingThreshold)
742 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
748 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
750 // 1. First we match rules from the user agent sheet.
751 matchRules(defaultStyle, firstUARule, lastUARule);
753 // 2. In quirks mode, we match rules from the quirks user agent sheet.
755 matchRules(defaultQuirksStyle, firstUARule, lastUARule);
757 // 3. If our medium is print, then we match rules from the print sheet.
758 if (m_medium->mediaTypeMatch("print"))
759 matchRules(defaultPrintStyle, firstUARule, lastUARule);
761 // 4. If we're in view source mode, then we match rules from the view source style sheet.
762 if (view && view->frame() && view->frame()->inViewSourceMode())
763 matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
766 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
767 // relative units are interpreted according to document root element style, styled only with UA stylesheet
769 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
771 if (allowSharing && !e->document()->haveStylesheetsLoaded()) {
772 if (!styleNotYetAvailable) {
773 styleNotYetAvailable = ::new RenderStyle();
774 styleNotYetAvailable->setDisplay(NONE);
775 styleNotYetAvailable->ref();
777 styleNotYetAvailable->ref();
778 return styleNotYetAvailable;
781 initElementAndPseudoState(e);
783 style = locateSharedStyle();
784 #ifdef STYLE_SHARING_STATS
785 fraction += style != 0;
787 printf("Sharing %d out of %d\n", fraction, total);
794 initForStyleResolve(e, defaultParent);
796 if (resolveForRootDefault) {
797 style = ::new RenderStyle();
798 // don't ref, because we want to delete this, but we cannot unref it
800 style = new (e->document()->renderArena()) RenderStyle();
804 style->inheritFrom(parentStyle);
808 int firstUARule = -1, lastUARule = -1;
809 int firstUserRule = -1, lastUserRule = -1;
810 int firstAuthorRule = -1, lastAuthorRule = -1;
811 matchUARules(firstUARule, lastUARule);
813 if (!resolveForRootDefault) {
814 // 4. Now we check user sheet rules.
815 matchRules(m_userStyle, firstUserRule, lastUserRule);
817 // 5. Now check author rules, beginning first with presentational attributes
820 // Ask if the HTML element has mapped attributes.
821 if (styledElement->hasMappedAttributes()) {
822 // Walk our attribute list and add in each decl.
823 const NamedMappedAttrMap* map = styledElement->mappedAttributes();
824 for (unsigned i = 0; i < map->length(); i++) {
825 MappedAttribute* attr = map->attributeItem(i);
827 lastAuthorRule = m_matchedDecls.size();
828 if (firstAuthorRule == -1)
829 firstAuthorRule = lastAuthorRule;
830 addMatchedDeclaration(attr->decl());
835 // Now we check additional mapped declarations.
836 // Tables and table cells share an additional mapped rule that must be applied
837 // after all attributes, since their mapped style depends on the values of multiple attributes.
838 CSSMutableStyleDeclaration* attributeDecl = styledElement->additionalAttributeStyleDecl();
840 lastAuthorRule = m_matchedDecls.size();
841 if (firstAuthorRule == -1)
842 firstAuthorRule = lastAuthorRule;
843 addMatchedDeclaration(attributeDecl);
847 // 6. Check the rules in author sheets next.
848 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
850 // 7. Now check our inline style attribute.
852 CSSMutableStyleDeclaration* inlineDecl = styledElement->inlineStyleDecl();
854 lastAuthorRule = m_matchedDecls.size();
855 if (firstAuthorRule == -1)
856 firstAuthorRule = lastAuthorRule;
857 addMatchedDeclaration(inlineDecl);
862 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
863 // high-priority properties first, i.e., those properties that other properties depend on.
864 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
865 // and (4) normal important.
866 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
867 if (!resolveForRootDefault) {
868 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
869 applyDeclarations(true, true, firstUserRule, lastUserRule);
871 applyDeclarations(true, true, firstUARule, lastUARule);
873 // If our font got dirtied, go ahead and update it now.
877 // Now do the normal priority UA properties.
878 applyDeclarations(false, false, firstUARule, lastUARule);
880 // Cache our border and background so that we can examine them later.
881 cacheBorderAndBackground();
883 // Now do the author and user normal priority properties and all the !important properties.
884 if (!resolveForRootDefault) {
885 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
886 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
887 applyDeclarations(false, true, firstUserRule, lastUserRule);
889 applyDeclarations(false, true, firstUARule, lastUARule);
891 // If our font got dirtied by one of the non-essential font props,
892 // go ahead and update it a second time.
896 // Clean up our style object's display and text decorations (among other fixups).
897 adjustRenderStyle(style, e);
899 // If we are a link, cache the determined pseudo-state.
901 style->setPseudoState(pseudoState);
903 // Now return the style.
907 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle)
912 initElementAndPseudoState(e);
913 initForStyleResolve(e, parentStyle);
914 pseudoStyle = pseudo;
916 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
919 // Check UA, user and author rules.
920 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
921 matchRules(defaultStyle, firstUARule, lastUARule);
922 matchRules(m_userStyle, firstUserRule, lastUserRule);
923 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
925 if (m_matchedDecls.isEmpty())
928 style = new (e->document()->renderArena()) RenderStyle();
931 style->inheritFrom(parentStyle);
934 style->noninherited_flags._styleType = pseudoStyle;
936 // High-priority properties.
937 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
938 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
939 applyDeclarations(true, true, firstUserRule, lastUserRule);
940 applyDeclarations(true, true, firstUARule, lastUARule);
942 // If our font got dirtied, go ahead and update it now.
946 // Now do the normal priority properties.
947 applyDeclarations(false, false, firstUARule, lastUARule);
949 // Cache our border and background so that we can examine them later.
950 cacheBorderAndBackground();
952 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
953 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
954 applyDeclarations(false, true, firstUserRule, lastUserRule);
955 applyDeclarations(false, true, firstUARule, lastUARule);
957 // If our font got dirtied by one of the non-essential font props,
958 // go ahead and update it a second time.
961 // Clean up our style object's display and text decorations (among other fixups).
962 adjustRenderStyle(style, 0);
964 // Now return the style.
968 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
970 // Cache our original display.
971 style->setOriginalDisplay(style->display());
973 if (style->display() != NONE) {
974 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
976 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
977 // these tags to retain their display types.
978 if (!strictParsing && e) {
979 if (e->hasTagName(tdTag)) {
980 style->setDisplay(TABLE_CELL);
981 style->setFloating(FNONE);
983 else if (e->hasTagName(tableTag))
984 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
987 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
988 // fix a crash where a site tries to position these objects. They also never honor display.
989 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
990 style->setPosition(StaticPosition);
991 style->setDisplay(BLOCK);
994 // Table headers with a text-align of auto will change the text-align to center.
995 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
996 style->setTextAlign(CENTER);
998 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
999 // position or float an inline, compact, or run-in. Cache the original display, since it
1000 // may be needed for positioned elements that have to compute their static normal flow
1001 // positions. We also force inline-level roots to be block-level.
1002 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1003 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1004 (e && e->document()->documentElement() == e))) {
1005 if (style->display() == INLINE_TABLE)
1006 style->setDisplay(TABLE);
1007 else if (style->display() == INLINE_BOX)
1008 style->setDisplay(BOX);
1009 else if (style->display() == LIST_ITEM) {
1010 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1011 // but only in quirks mode.
1012 if (!strictParsing && style->floating() != FNONE)
1013 style->setDisplay(BLOCK);
1016 style->setDisplay(BLOCK);
1019 // After performing the display mutation, check table rows. We do not honor position:relative on
1020 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1022 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1023 style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1024 style->position() == RelativePosition)
1025 style->setPosition(StaticPosition);
1028 // Make sure our z-index value is only applied if the object is positioned,
1029 // relatively positioned, or transparent.
1030 if (style->position() == StaticPosition && style->opacity() == 1.0f)
1031 style->setHasAutoZIndex();
1033 // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1034 // cases where objects that should be blended as a single unit end up with a non-transparent
1035 // object wedged in between them.
1036 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f))
1037 style->setZIndex(0);
1039 // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
1040 // This will be important when we use block flows for all form controls.
1041 if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
1042 e->hasTagName(selectTag) || e->hasTagName(textareaTag))) {
1043 if (style->width().isAuto())
1044 style->setWidth(Length(Intrinsic));
1047 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1048 // tables, inline blocks, inline tables, or run-ins.
1049 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1050 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1051 style->setTextDecorationsInEffect(style->textDecoration());
1053 style->addToTextDecorationsInEffect(style->textDecoration());
1055 // If either overflow value is not visible, change to auto.
1056 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1057 style->setOverflowY(OMARQUEE);
1058 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1059 style->setOverflowX(OMARQUEE);
1060 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1061 style->setOverflowX(OAUTO);
1062 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1063 style->setOverflowY(OAUTO);
1065 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1066 // FIXME: Eventually table sections will support auto and scroll.
1067 if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1068 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1069 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1070 style->setOverflowX(OVISIBLE);
1071 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1072 style->setOverflowY(OVISIBLE);
1075 // Links should be user selectable when content editable
1076 if (e && e->isLink() && (style->userModify() == READ_WRITE || style->userModify() == READ_WRITE_PLAINTEXT_ONLY))
1077 style->setUserSelect(SELECT_AUTO);
1079 // Cull out any useless layers and also repeat patterns into additional layers.
1080 style->adjustBackgroundLayers();
1082 // Let the theme also have a crack at adjusting the style.
1083 if (style->hasAppearance()) {
1084 if (m_hasUAAppearance && theme()->isControlStyled(style, m_borderData, m_backgroundData, m_backgroundColor))
1085 style->setAppearance(NoAppearance);
1087 theme()->adjustStyle(this, style, e);
1090 // Only use slow repaints if we actually have a background image.
1091 // FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to
1092 // prevent the entire view from blitting on a scroll.
1093 if (style->hasFixedBackgroundImage() && view)
1094 view->useSlowRepaints();
1097 void CSSStyleSelector::updateFont()
1099 checkForTextSizeAdjust();
1100 checkForGenericFamilyChange(style, parentStyle);
1101 style->font().update();
1105 void CSSStyleSelector::cacheBorderAndBackground()
1107 m_hasUAAppearance = style->hasAppearance();
1108 if (m_hasUAAppearance) {
1109 m_borderData = style->border();
1110 m_backgroundData = *style->backgroundLayers();
1111 m_backgroundColor = style->backgroundColor();
1115 RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
1117 if (!e->document()->haveStylesheetsLoaded())
1120 m_collectRulesOnly = true;
1122 initElementAndPseudoState(e);
1123 initForStyleResolve(e, 0);
1126 int firstUARule = -1, lastUARule = -1;
1127 // First we match rules from the user agent sheet.
1128 matchUARules(firstUARule, lastUARule);
1130 // Now we check user sheet rules.
1131 int firstUserRule = -1, lastUserRule = -1;
1132 matchRules(m_userStyle, firstUserRule, lastUserRule);
1135 // Check the rules in author sheets.
1136 int firstAuthorRule = -1, lastAuthorRule = -1;
1137 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1139 m_collectRulesOnly = false;
1144 RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, StringImpl* pseudoStyle, bool authorOnly)
1146 // FIXME: Implement this.
1150 static bool subject;
1152 bool CSSStyleSelector::checkSelector(CSSSelector* sel, Element *e)
1154 dynamicPseudo = RenderStyle::NOPSEUDO;
1158 // we have the subject part of the selector
1161 // We track whether or not the rule contains only :hover and :active in a simple selector. If
1162 // so, we can't allow that to apply to every element on the page. We assume the author intended
1163 // to apply the rules only to links.
1164 bool onlyHoverActive = (!sel->hasTag() &&
1165 (sel->match == CSSSelector::PseudoClass &&
1166 (sel->pseudoType() == CSSSelector::PseudoHover ||
1167 sel->pseudoType() == CSSSelector::PseudoActive)));
1168 bool affectedByHover = style ? style->affectedByHoverRules() : false;
1169 bool affectedByActive = style ? style->affectedByActiveRules() : false;
1170 bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
1172 // first selector has to match
1173 if (!checkOneSelector(sel, e))
1176 // check the subselectors
1177 CSSSelector::Relation relation = sel->relation();
1178 while((sel = sel->tagHistory)) {
1179 if (!n->isElementNode())
1181 if (relation != CSSSelector::SubSelector) {
1183 if (havePseudo && dynamicPseudo != pseudoStyle)
1189 case CSSSelector::Descendant:
1190 // FIXME: This match needs to know how to backtrack and be non-deterministic.
1192 n = n->parentNode();
1193 if (!n || !n->isElementNode())
1195 } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1197 case CSSSelector::Child:
1199 n = n->parentNode();
1201 while (n && n->implicitNode())
1202 n = n->parentNode();
1203 if (!n || !n->isElementNode())
1205 if (!checkOneSelector(sel, static_cast<Element*>(n)))
1209 case CSSSelector::DirectAdjacent:
1211 n = n->previousSibling();
1212 while (n && !n->isElementNode())
1213 n = n->previousSibling();
1216 if (!checkOneSelector(sel, static_cast<Element*>(n)))
1220 case CSSSelector::IndirectAdjacent:
1221 // FIXME: This match needs to know how to backtrack and be non-deterministic.
1223 n = n->previousSibling();
1224 while (n && !n->isElementNode())
1225 n = n->previousSibling();
1228 } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1230 case CSSSelector::SubSelector:
1232 if (onlyHoverActive)
1233 onlyHoverActive = (sel->match == CSSSelector::PseudoClass &&
1234 (sel->pseudoType() == CSSSelector::PseudoHover ||
1235 sel->pseudoType() == CSSSelector::PseudoActive));
1237 Element *elem = static_cast<Element*>(n);
1238 // a selector is invalid if something follows :first-xxx
1239 if (elem == element && dynamicPseudo != RenderStyle::NOPSEUDO)
1241 if (!checkOneSelector(sel, elem, true))
1246 relation = sel->relation();
1249 if (subject && havePseudo && dynamicPseudo != pseudoStyle)
1252 // disallow *:hover, *:active, and *:hover:active except for links
1253 if (onlyHoverActive && subject) {
1254 if (pseudoState == PseudoUnknown)
1255 checkPseudoState(e);
1257 if (pseudoState == PseudoNone) {
1258 if (!affectedByHover && style->affectedByHoverRules())
1259 style->setAffectedByHoverRules(false);
1260 if (!affectedByActive && style->affectedByActiveRules())
1261 style->setAffectedByActiveRules(false);
1269 bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSubSelector)
1274 if (sel->hasTag()) {
1275 const AtomicString& localName = e->localName();
1276 const AtomicString& ns = e->namespaceURI();
1277 const AtomicString& selLocalName = sel->tag.localName();
1278 const AtomicString& selNS = sel->tag.namespaceURI();
1280 if ((selLocalName != starAtom && localName != selLocalName) ||
1281 (selNS != starAtom && ns != selNS))
1285 if (sel->hasAttribute()) {
1286 if (sel->match == CSSSelector::Class) {
1289 for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1290 if (c->string() == sel->value)
1294 else if (sel->match == CSSSelector::Id)
1295 return e->hasID() && e->getIDAttribute() == sel->value;
1296 else if (style && (e != element || !styledElement || (!styledElement->isMappedAttribute(sel->attr) && sel->attr != typeAttr))) {
1297 style->setAffectedByAttributeSelectors(); // Special-case the "type" attribute so input form controls can share style.
1298 m_selectorAttrs.add(sel->attr.localName().impl());
1301 const AtomicString& value = e->getAttribute(sel->attr);
1303 return false; // attribute is not set
1305 switch(sel->match) {
1306 case CSSSelector::Exact:
1307 if ((isXMLDoc && sel->value != value) || (!isXMLDoc && !equalIgnoringCase(sel->value, value)))
1310 case CSSSelector::List:
1312 // The selector's value can't contain a space, or it's totally bogus.
1313 if (sel->value.contains(' '))
1316 int startSearchAt = 0;
1318 int foundPos = value.find(sel->value, startSearchAt, isXMLDoc);
1321 if (foundPos == 0 || value[foundPos-1] == ' ') {
1322 unsigned endStr = foundPos + sel->value.length();
1323 if (endStr == value.length() || value[endStr] == ' ')
1324 break; // We found a match.
1327 // No match. Keep looking.
1328 startSearchAt = foundPos + 1;
1332 case CSSSelector::Contain:
1333 if (!value.contains(sel->value, isXMLDoc))
1336 case CSSSelector::Begin:
1337 if (!value.startsWith(sel->value, isXMLDoc))
1340 case CSSSelector::End:
1341 if (!value.endsWith(sel->value, isXMLDoc))
1344 case CSSSelector::Hyphen:
1345 if (value.length() < sel->value.length())
1347 if (!value.startsWith(sel->value, isXMLDoc))
1349 // It they start the same, check for exact match or following '-':
1350 if (value.length() != sel->value.length() && value[sel->value.length()] != '-')
1353 case CSSSelector::PseudoClass:
1354 case CSSSelector::PseudoElement:
1359 if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
1361 // Pseudo elements. We need to check first child here. No dynamic pseudo
1362 // elements for the moment
1363 switch (sel->pseudoType()) {
1365 case CSSSelector::PseudoEmpty:
1366 if (!e->firstChild())
1369 case CSSSelector::PseudoFirstChild: {
1370 // first-child matches the first child that is an element!
1371 if (e->parentNode() && e->parentNode()->isElementNode()) {
1372 Node *n = e->previousSibling();
1373 while (n && !n->isElementNode())
1374 n = n->previousSibling();
1380 case CSSSelector::PseudoFirstOfType: {
1381 // first-of-type matches the first element of its type!
1382 if (e->parentNode() && e->parentNode()->isElementNode()) {
1383 const QualifiedName& type = e->tagQName();
1384 Node *n = e->previousSibling();
1386 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1388 n = n->previousSibling();
1395 case CSSSelector::PseudoLastChild: {
1396 // last-child matches the last child that is an element!
1397 if (e->parentNode() && e->parentNode()->isElementNode()) {
1398 Node *n = e->nextSibling();
1399 while (n && !n->isElementNode())
1400 n = n->nextSibling();
1406 case CSSSelector::PseudoLastOfType: {
1407 // last-of-type matches the last element of its type!
1408 if (e->parentNode() && e->parentNode()->isElementNode()) {
1409 const QualifiedName& type = e->tagQName();
1410 Node *n = e->nextSibling();
1412 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1414 n = n->nextSibling();
1421 case CSSSelector::PseudoOnlyChild: {
1422 // If both first-child and last-child apply, then only-child applies.
1423 if (e->parentNode() && e->parentNode()->isElementNode()) {
1424 Node *n = e->previousSibling();
1425 while (n && !n->isElementNode())
1426 n = n->previousSibling();
1428 n = e->nextSibling();
1429 while (n && !n->isElementNode())
1430 n = n->nextSibling();
1437 case CSSSelector::PseudoOnlyOfType: {
1438 // If both first-of-type and last-of-type apply, then only-of-type applies.
1439 if (e->parentNode() && e->parentNode()->isElementNode()) {
1440 const QualifiedName& type = e->tagQName();
1441 Node *n = e->previousSibling();
1442 while (n && !static_cast<Element*>(n)->hasTagName(type))
1443 n = n->previousSibling();
1445 n = e->nextSibling();
1446 while (n && !static_cast<Element*>(n)->hasTagName(type))
1447 n = n->nextSibling();
1454 case CSSSelector::PseudoTarget:
1455 if (e == e->document()->getCSSTarget())
1458 case CSSSelector::PseudoAnyLink:
1459 if (pseudoState == PseudoUnknown)
1460 checkPseudoState(e, false);
1461 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1464 case CSSSelector::PseudoAutofill:
1465 if (e && e->hasTagName(inputTag))
1466 return static_cast<HTMLInputElement*>(e)->autofilled();
1468 case CSSSelector::PseudoLink:
1469 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1470 checkPseudoState(e);
1471 if (pseudoState == PseudoLink)
1474 case CSSSelector::PseudoVisited:
1475 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1476 checkPseudoState(e);
1477 if (pseudoState == PseudoVisited)
1480 case CSSSelector::PseudoHover: {
1481 // If we're in quirks mode, then hover should never match anchors with no
1482 // href and *:hover should not match anything. This is important for sites like wsj.com.
1483 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1484 if (element == e && style)
1485 style->setAffectedByHoverRules(true);
1486 if (element != e && e->renderStyle())
1487 e->renderStyle()->setAffectedByHoverRules(true);
1493 case CSSSelector::PseudoDrag: {
1494 if (element == e && style)
1495 style->setAffectedByDragRules(true);
1496 if (element != e && e->renderStyle())
1497 e->renderStyle()->setAffectedByDragRules(true);
1498 if (e->renderer() && e->renderer()->isDragging())
1502 case CSSSelector::PseudoFocus:
1503 if (e && e->focused() && e->document()->frame()->isActive())
1506 case CSSSelector::PseudoActive:
1507 // If we're in quirks mode, then :active should never match anchors with no
1508 // href and *:active should not match anything.
1509 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1510 if (element == e && style)
1511 style->setAffectedByActiveRules(true);
1512 else if (e->renderStyle())
1513 e->renderStyle()->setAffectedByActiveRules(true);
1518 case CSSSelector::PseudoEnabled:
1519 if (e && e->isControl())
1520 // The UI spec states that you can't match :enabled unless you are an object that can
1521 // "receive focus and be activated." We will limit matching of this pseudo-class to elements
1522 // that are controls.
1523 return e->isEnabled();
1525 case CSSSelector::PseudoDisabled:
1526 if (e && e->isControl())
1527 // The UI spec states that you can't match :enabled unless you are an object that can
1528 // "receive focus and be activated." We will limit matching of this pseudo-class to elements
1529 // that are controls.
1530 return !e->isEnabled();
1532 case CSSSelector::PseudoChecked:
1533 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
1534 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
1535 // obey the CSS spec here in the test for matching the pseudo.
1536 if (e && e->isChecked() && !e->isIndeterminate())
1539 case CSSSelector::PseudoIndeterminate:
1540 if (e && e->isIndeterminate())
1543 case CSSSelector::PseudoRoot:
1544 if (e == e->document()->documentElement())
1547 case CSSSelector::PseudoLang: {
1548 const AtomicString& value = e->getAttribute(langAttr);
1549 if (value.isEmpty() || !value.startsWith(sel->argument, false))
1551 if (value.length() != sel->argument.length() && value[sel->argument.length()] != '-')
1555 case CSSSelector::PseudoNot: {
1556 // check the simple selector
1557 for (CSSSelector* subSel = sel->simpleSelector; subSel; subSel = subSel->tagHistory) {
1558 // :not cannot nest. I don't really know why this is a
1559 // restriction in CSS3, but it is, so let's honour it.
1560 if (subSel->simpleSelector)
1562 if (!checkOneSelector(subSel, e))
1567 case CSSSelector::PseudoOther:
1571 case CSSSelector::PseudoFirstLine:
1573 dynamicPseudo=RenderStyle::FIRST_LINE;
1577 case CSSSelector::PseudoFirstLetter:
1579 dynamicPseudo=RenderStyle::FIRST_LETTER;
1583 case CSSSelector::PseudoSelection:
1584 dynamicPseudo = RenderStyle::SELECTION;
1586 case CSSSelector::PseudoBefore:
1587 dynamicPseudo = RenderStyle::BEFORE;
1589 case CSSSelector::PseudoAfter:
1590 dynamicPseudo = RenderStyle::AFTER;
1593 case CSSSelector::PseudoNotParsed:
1599 // ### add the rest of the checks...
1603 // -----------------------------------------------------------------
1605 CSSRuleSet::CSSRuleSet()
1607 m_universalRules = 0;
1611 CSSRuleSet::~CSSRuleSet()
1613 deleteAllValues(m_idRules);
1614 deleteAllValues(m_classRules);
1615 deleteAllValues(m_tagRules);
1617 delete m_universalRules;
1621 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1622 CSSStyleRule* rule, CSSSelector* sel)
1625 CSSRuleDataList* rules = map.get(key);
1627 rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1628 map.set(key, rules);
1630 rules->append(m_ruleCount++, rule, sel);
1633 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1635 if (sel->match == CSSSelector::Id) {
1636 addToRuleSet(sel->value.impl(), m_idRules, rule, sel);
1639 if (sel->match == CSSSelector::Class) {
1640 addToRuleSet(sel->value.impl(), m_classRules, rule, sel);
1644 const AtomicString& localName = sel->tag.localName();
1645 if (localName != starAtom) {
1646 addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1650 // Just put it in the universal rule set.
1651 if (!m_universalRules)
1652 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1654 m_universalRules->append(m_ruleCount++, rule, sel);
1657 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium)
1659 if (!sheet || !sheet->isCSSStyleSheet())
1662 // No media implies "all", but if a media list exists it must
1663 // contain our current medium
1664 if (sheet->media() && !medium->eval(sheet->media()))
1665 return; // the style sheet doesn't apply
1667 int len = sheet->length();
1669 for (int i = 0; i < len; i++) {
1670 StyleBase* item = sheet->item(i);
1671 if (item->isStyleRule()) {
1672 CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
1673 for (CSSSelector* s = rule->selector(); s; s = s->next())
1676 else if(item->isImportRule()) {
1677 CSSImportRule* import = static_cast<CSSImportRule*>(item);
1678 if (!import->media() || medium->eval(import->media()))
1679 addRulesFromSheet(import->styleSheet(), medium);
1681 else if(item->isMediaRule()) {
1682 CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
1683 CSSRuleList* rules = r->cssRules();
1685 if ((!r->media() || medium->eval(r->media())) && rules) {
1686 // Traverse child elements of the @media rule.
1687 for (unsigned j = 0; j < rules->length(); j++) {
1688 CSSRule *childItem = rules->item(j);
1689 if (childItem->isStyleRule()) {
1690 // It is a StyleRule, so append it to our list
1691 CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
1692 for (CSSSelector* s = rule->selector(); s; s = s->next())
1702 // -------------------------------------------------------------------------------------
1703 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1705 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
1708 if (!primitiveValue) {
1712 int type = primitiveValue->primitiveType();
1713 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1714 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
1715 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1716 l = Length(int(primitiveValue->getFloatValue()), Percent);
1717 else if(type == CSSPrimitiveValue::CSS_NUMBER)
1718 l = Length(int(primitiveValue->getFloatValue() * 100), Percent);
1725 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1726 int startIndex, int endIndex)
1728 if (startIndex == -1) return;
1729 for (int i = startIndex; i <= endIndex; i++) {
1730 CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
1731 DeprecatedValueListConstIterator<CSSProperty> end;
1732 for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
1733 const CSSProperty& current = *it;
1734 // give special priority to font-xxx, color properties
1735 if (isImportant == current.isImportant()) {
1737 switch(current.id()) {
1738 case CSS_PROP_COLOR:
1739 case CSS_PROP_DIRECTION:
1740 case CSS_PROP_DISPLAY:
1742 case CSS_PROP_FONT_SIZE:
1743 case CSS_PROP_FONT_STYLE:
1744 case CSS_PROP_FONT_FAMILY:
1745 case CSS_PROP_FONT_WEIGHT:
1746 case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1747 case CSS_PROP_FONT_VARIANT:
1748 // these have to be applied first, because other properties use the computed
1749 // values of these porperties.
1757 if (first == applyFirst)
1758 applyProperty(current.id(), current.value());
1764 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
1766 CSSPrimitiveValue *primitiveValue = 0;
1767 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1772 unsigned short valueType = value->cssValueType();
1774 bool isInherit = parentNode && valueType == CSSValue::CSS_INHERIT;
1775 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!parentNode && valueType == CSSValue::CSS_INHERIT);
1777 // These properties are used to set the correct margins/padding on RTL lists.
1778 if (id == CSS_PROP__WEBKIT_MARGIN_START)
1779 id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
1780 else if (id == CSS_PROP__WEBKIT_PADDING_START)
1781 id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
1783 // What follows is a list that maps the CSS properties into their corresponding front-end
1784 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
1785 // are only hit when mapping "inherit" or "initial" into front-end values.
1788 // ident only properties
1789 case CSS_PROP_BACKGROUND_ATTACHMENT:
1790 HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
1792 case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1793 HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
1795 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1796 HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value)
1798 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1799 HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
1801 case CSS_PROP_BACKGROUND_REPEAT:
1802 HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
1804 case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1805 HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
1807 case CSS_PROP_BORDER_COLLAPSE:
1808 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1809 if(!primitiveValue) break;
1810 switch(primitiveValue->getIdent())
1812 case CSS_VAL_COLLAPSE:
1813 style->setBorderCollapse(true);
1815 case CSS_VAL_SEPARATE:
1816 style->setBorderCollapse(false);
1823 case CSS_PROP_BORDER_TOP_STYLE:
1824 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1825 if (!primitiveValue) return;
1826 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1828 case CSS_PROP_BORDER_RIGHT_STYLE:
1829 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1830 if (!primitiveValue) return;
1831 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1833 case CSS_PROP_BORDER_BOTTOM_STYLE:
1834 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1835 if (!primitiveValue) return;
1836 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1838 case CSS_PROP_BORDER_LEFT_STYLE:
1839 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1840 if (!primitiveValue) return;
1841 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1843 case CSS_PROP_OUTLINE_STYLE:
1844 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1845 if (!primitiveValue) return;
1846 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1847 style->setOutlineStyle(DOTTED, true);
1849 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1851 case CSS_PROP_CAPTION_SIDE:
1853 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1854 if(!primitiveValue) break;
1855 ECaptionSide c = RenderStyle::initialCaptionSide();
1856 switch(primitiveValue->getIdent())
1861 c = CAPRIGHT; break;
1864 case CSS_VAL_BOTTOM:
1865 c = CAPBOTTOM; break;
1869 style->setCaptionSide(c);
1872 case CSS_PROP_CLEAR:
1874 HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1875 if(!primitiveValue) break;
1877 switch(primitiveValue->getIdent())
1893 case CSS_PROP_DIRECTION:
1895 HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1896 if(!primitiveValue) break;
1897 style->setDirection(primitiveValue->getIdent() == CSS_VAL_LTR ? LTR : RTL);
1900 case CSS_PROP_DISPLAY:
1902 HANDLE_INHERIT_AND_INITIAL(display, Display)
1903 if(!primitiveValue) break;
1904 int id = primitiveValue->getIdent();
1906 if (id == CSS_VAL_NONE)
1909 d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1911 style->setDisplay(d);
1915 case CSS_PROP_EMPTY_CELLS:
1917 HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1918 if (!primitiveValue) break;
1919 int id = primitiveValue->getIdent();
1920 if (id == CSS_VAL_SHOW)
1921 style->setEmptyCells(SHOW);
1922 else if (id == CSS_VAL_HIDE)
1923 style->setEmptyCells(HIDE);
1926 case CSS_PROP_FLOAT:
1928 HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1929 if(!primitiveValue) return;
1931 switch(primitiveValue->getIdent())
1938 case CSS_VAL_CENTER: //Non standart CSS-Value
1944 style->setFloating(f);
1949 case CSS_PROP_FONT_STRETCH:
1950 break; /* Not supported. */
1952 case CSS_PROP_FONT_STYLE:
1954 FontDescription fontDescription = style->fontDescription();
1956 fontDescription.setItalic(parentStyle->fontDescription().italic());
1958 fontDescription.setItalic(false);
1960 if (!primitiveValue) return;
1961 switch (primitiveValue->getIdent()) {
1962 case CSS_VAL_OBLIQUE:
1963 // FIXME: oblique is the same as italic for the moment...
1964 case CSS_VAL_ITALIC:
1965 fontDescription.setItalic(true);
1967 case CSS_VAL_NORMAL:
1968 fontDescription.setItalic(false);
1974 if (style->setFontDescription(fontDescription))
1979 case CSS_PROP_FONT_VARIANT:
1981 FontDescription fontDescription = style->fontDescription();
1983 fontDescription.setSmallCaps(parentStyle->fontDescription().smallCaps());
1985 fontDescription.setSmallCaps(false);
1987 if (!primitiveValue) return;
1988 int id = primitiveValue->getIdent();
1989 if (id == CSS_VAL_NORMAL)
1990 fontDescription.setSmallCaps(false);
1991 else if (id == CSS_VAL_SMALL_CAPS)
1992 fontDescription.setSmallCaps(true);
1996 if (style->setFontDescription(fontDescription))
2001 case CSS_PROP_FONT_WEIGHT:
2003 FontDescription fontDescription = style->fontDescription();
2005 fontDescription.setWeight(parentStyle->fontDescription().weight());
2007 fontDescription.setWeight(cNormalWeight);
2009 if (!primitiveValue) return;
2010 if (primitiveValue->getIdent()) {
2011 switch (primitiveValue->getIdent()) {
2012 // FIXME: We aren't genuinely supporting specific weight values.
2014 case CSS_VAL_BOLDER:
2019 fontDescription.setWeight(cBoldWeight);
2021 case CSS_VAL_NORMAL:
2022 case CSS_VAL_LIGHTER:
2028 fontDescription.setWeight(cNormalWeight);
2036 // ### fix parsing of 100-900 values in parser, apply them here
2039 if (style->setFontDescription(fontDescription))
2044 case CSS_PROP_LIST_STYLE_POSITION:
2046 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2047 if (!primitiveValue) return;
2048 if (primitiveValue->getIdent())
2049 style->setListStylePosition((EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE));
2053 case CSS_PROP_LIST_STYLE_TYPE:
2055 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2056 if (!primitiveValue) return;
2057 if (primitiveValue->getIdent())
2060 int id = primitiveValue->getIdent();
2061 if (id == CSS_VAL_NONE) { // important!!
2064 t = EListStyleType(id - CSS_VAL_DISC);
2066 style->setListStyleType(t);
2071 case CSS_PROP_OVERFLOW:
2074 style->setOverflowX(parentStyle->overflowX());
2075 style->setOverflowY(parentStyle->overflowY());
2080 style->setOverflowX(RenderStyle::initialOverflowX());
2081 style->setOverflowY(RenderStyle::initialOverflowY());
2086 switch(primitiveValue->getIdent()) {
2087 case CSS_VAL_VISIBLE:
2088 o = OVISIBLE; break;
2089 case CSS_VAL_HIDDEN:
2091 case CSS_VAL_SCROLL:
2095 case CSS_VAL__WEBKIT_MARQUEE:
2096 o = OMARQUEE; break;
2097 case CSS_VAL_OVERLAY:
2098 o = OOVERLAY; break;
2102 style->setOverflowX(o);
2103 style->setOverflowY(o);
2107 case CSS_PROP_OVERFLOW_X:
2109 HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
2111 switch(primitiveValue->getIdent())
2113 case CSS_VAL_VISIBLE:
2114 o = OVISIBLE; break;
2115 case CSS_VAL_HIDDEN:
2117 case CSS_VAL_SCROLL:
2121 case CSS_VAL_OVERLAY:
2122 o = OOVERLAY; break;
2126 style->setOverflowX(o);
2130 case CSS_PROP_OVERFLOW_Y:
2132 HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
2134 switch(primitiveValue->getIdent())
2136 case CSS_VAL_VISIBLE:
2137 o = OVISIBLE; break;
2138 case CSS_VAL_HIDDEN:
2140 case CSS_VAL_SCROLL:
2144 case CSS_VAL_OVERLAY:
2145 o = OOVERLAY; break;
2149 style->setOverflowY(o);
2153 case CSS_PROP_PAGE_BREAK_BEFORE:
2155 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2156 if (!primitiveValue) return;
2157 switch (primitiveValue->getIdent()) {
2159 style->setPageBreakBefore(PBAUTO);
2163 case CSS_VAL_ALWAYS:
2164 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2167 style->setPageBreakBefore(PBAVOID);
2173 case CSS_PROP_PAGE_BREAK_AFTER:
2175 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2176 if (!primitiveValue) return;
2177 switch (primitiveValue->getIdent()) {
2179 style->setPageBreakAfter(PBAUTO);
2183 case CSS_VAL_ALWAYS:
2184 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2187 style->setPageBreakAfter(PBAVOID);
2193 case CSS_PROP_PAGE_BREAK_INSIDE: {
2194 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2195 if (!primitiveValue) return;
2196 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2197 style->setPageBreakInside(PBAUTO);
2198 else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2199 style->setPageBreakInside(PBAVOID);
2204 break; /* FIXME: Not even sure what this is... -dwh */
2206 case CSS_PROP_POSITION:
2208 HANDLE_INHERIT_AND_INITIAL(position, Position)
2209 if(!primitiveValue) return;
2211 switch(primitiveValue->getIdent())
2213 case CSS_VAL_STATIC:
2214 p = StaticPosition; break;
2215 case CSS_VAL_RELATIVE:
2216 p = RelativePosition; break;
2217 case CSS_VAL_ABSOLUTE:
2218 p = AbsolutePosition; break;
2222 view->useSlowRepaints();
2229 style->setPosition(p);
2233 case CSS_PROP_TABLE_LAYOUT: {
2234 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2236 if (!primitiveValue->getIdent())
2239 ETableLayout l = RenderStyle::initialTableLayout();
2240 switch(primitiveValue->getIdent()) {
2245 style->setTableLayout(l);
2252 case CSS_PROP_UNICODE_BIDI: {
2253 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2254 switch (primitiveValue->getIdent()) {
2255 case CSS_VAL_NORMAL:
2256 style->setUnicodeBidi(UBNormal);
2259 style->setUnicodeBidi(Embed);
2261 case CSS_VAL_BIDI_OVERRIDE:
2262 style->setUnicodeBidi(Override);
2269 case CSS_PROP_TEXT_TRANSFORM: {
2270 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2272 if(!primitiveValue->getIdent()) return;
2275 switch(primitiveValue->getIdent()) {
2276 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break;
2277 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break;
2278 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break;
2280 default: tt = TTNONE; break;
2282 style->setTextTransform(tt);
2286 case CSS_PROP_VISIBILITY:
2288 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2290 switch(primitiveValue->getIdent()) {
2291 case CSS_VAL_HIDDEN:
2292 style->setVisibility(HIDDEN);
2294 case CSS_VAL_VISIBLE:
2295 style->setVisibility(VISIBLE);
2297 case CSS_VAL_COLLAPSE:
2298 style->setVisibility(COLLAPSE);
2304 case CSS_PROP_WHITE_SPACE:
2305 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2307 if(!primitiveValue->getIdent()) return;
2310 switch(primitiveValue->getIdent()) {
2311 case CSS_VAL__WEBKIT_NOWRAP:
2314 case CSS_VAL_NOWRAP:
2320 case CSS_VAL_PRE_WRAP:
2323 case CSS_VAL_PRE_LINE:
2326 case CSS_VAL_NORMAL:
2331 style->setWhiteSpace(s);
2334 case CSS_PROP_BACKGROUND_POSITION:
2335 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2336 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2338 case CSS_PROP_BACKGROUND_POSITION_X: {
2339 HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2342 case CSS_PROP_BACKGROUND_POSITION_Y: {
2343 HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2346 case CSS_PROP_BORDER_SPACING: {
2348 style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2349 style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2351 else if (isInitial) {
2352 style->setHorizontalBorderSpacing(0);
2353 style->setVerticalBorderSpacing(0);
2357 case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: {
2358 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2359 if (!primitiveValue) break;
2360 short spacing = primitiveValue->computeLengthShort(style);
2361 style->setHorizontalBorderSpacing(spacing);
2364 case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: {
2365 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2366 if (!primitiveValue) break;
2367 short spacing = primitiveValue->computeLengthShort(style);
2368 style->setVerticalBorderSpacing(spacing);
2371 case CSS_PROP_CURSOR:
2373 style->setCursor(parentStyle->cursor());
2374 style->setCursorImage(parentStyle->cursorImage());
2378 style->setCursor(RenderStyle::initialCursor());
2379 style->setCursorImage(0);
2382 if (primitiveValue) {
2383 int type = primitiveValue->primitiveType();
2384 if (type == CSSPrimitiveValue::CSS_IDENT) {
2385 style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
2386 style->setCursorImage(0);
2387 } else if (type == CSSPrimitiveValue::CSS_URI) {
2388 CSSImageValue* image = static_cast<CSSImageValue*>(primitiveValue);
2389 style->setCursor(CURSOR_AUTO);
2390 style->setCursorImage(image->image(element->document()->docLoader()));
2394 // colors || inherit
2395 case CSS_PROP_BACKGROUND_COLOR:
2396 case CSS_PROP_BORDER_TOP_COLOR:
2397 case CSS_PROP_BORDER_RIGHT_COLOR:
2398 case CSS_PROP_BORDER_BOTTOM_COLOR:
2399 case CSS_PROP_BORDER_LEFT_COLOR:
2400 case CSS_PROP_COLOR:
2401 case CSS_PROP_OUTLINE_COLOR:
2402 // this property is an extension used to get HTML4 <font> right.
2406 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2407 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2408 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2409 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2410 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2411 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2412 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2416 // The border/outline colors will just map to the invalid color |col| above. This will have the
2417 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2418 // not painting the background since the color won't be valid).
2419 if (id == CSS_PROP_COLOR)
2420 col = RenderStyle::initialColor();
2422 if (!primitiveValue)
2424 col = getColorFromPrimitiveValue(primitiveValue);
2428 case CSS_PROP_BACKGROUND_COLOR:
2429 style->setBackgroundColor(col); break;
2430 case CSS_PROP_BORDER_TOP_COLOR:
2431 style->setBorderTopColor(col); break;
2432 case CSS_PROP_BORDER_RIGHT_COLOR:
2433 style->setBorderRightColor(col); break;
2434 case CSS_PROP_BORDER_BOTTOM_COLOR:
2435 style->setBorderBottomColor(col); break;
2436 case CSS_PROP_BORDER_LEFT_COLOR:
2437 style->setBorderLeftColor(col); break;
2438 case CSS_PROP_COLOR:
2439 style->setColor(col); break;
2440 case CSS_PROP_OUTLINE_COLOR:
2441 style->setOutlineColor(col); break;
2448 case CSS_PROP_BACKGROUND_IMAGE:
2449 HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2451 case CSS_PROP_LIST_STYLE_IMAGE:
2453 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2454 if (!primitiveValue)
2456 style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader()));
2461 case CSS_PROP_BORDER_TOP_WIDTH:
2462 case CSS_PROP_BORDER_RIGHT_WIDTH:
2463 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2464 case CSS_PROP_BORDER_LEFT_WIDTH:
2465 case CSS_PROP_OUTLINE_WIDTH:
2468 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2469 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2470 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2471 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2472 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2475 else if (isInitial) {
2476 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2477 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2478 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2479 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2480 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2484 if(!primitiveValue) break;
2486 switch(primitiveValue->getIdent())
2491 case CSS_VAL_MEDIUM:
2497 case CSS_VAL_INVALID:
2498 width = primitiveValue->computeLengthShort(style);
2504 if(width < 0) return;
2507 case CSS_PROP_BORDER_TOP_WIDTH:
2508 style->setBorderTopWidth(width);
2510 case CSS_PROP_BORDER_RIGHT_WIDTH:
2511 style->setBorderRightWidth(width);
2513 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2514 style->setBorderBottomWidth(width);
2516 case CSS_PROP_BORDER_LEFT_WIDTH:
2517 style->setBorderLeftWidth(width);
2519 case CSS_PROP_OUTLINE_WIDTH:
2520 style->setOutlineWidth(width);
2528 case CSS_PROP_LETTER_SPACING:
2529 case CSS_PROP_WORD_SPACING:
2533 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2534 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2537 else if (isInitial) {
2538 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2539 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2544 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2547 if(!primitiveValue) return;
2548 width = primitiveValue->computeLengthInt(style);
2552 case CSS_PROP_LETTER_SPACING:
2553 style->setLetterSpacing(width);
2555 case CSS_PROP_WORD_SPACING:
2556 style->setWordSpacing(width);
2558 // ### needs the definitions in renderstyle
2564 case CSS_PROP_WORD_WRAP:
2566 HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2568 if(!primitiveValue->getIdent()) return;
2571 switch(primitiveValue->getIdent()) {
2572 case CSS_VAL_BREAK_WORD:
2575 case CSS_VAL_NORMAL:
2580 style->setWordWrap(s);
2584 case CSS_PROP__WEBKIT_NBSP_MODE:
2586 HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2588 if (!primitiveValue->getIdent()) return;
2591 switch(primitiveValue->getIdent()) {
2595 case CSS_VAL_NORMAL:
2600 style->setNBSPMode(m);
2604 case CSS_PROP__WEBKIT_LINE_BREAK:
2606 HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2608 if (!primitiveValue->getIdent()) return;
2611 switch(primitiveValue->getIdent()) {
2612 case CSS_VAL_AFTER_WHITE_SPACE:
2613 b = AFTER_WHITE_SPACE;
2615 case CSS_VAL_NORMAL:
2620 style->setKHTMLLineBreak(b);
2624 case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:
2626 HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2628 if (!primitiveValue->getIdent()) return;
2630 EMatchNearestMailBlockquoteColor c;
2631 switch(primitiveValue->getIdent()) {
2632 case CSS_VAL_NORMAL:
2640 style->setMatchNearestMailBlockquoteColor(c);
2644 case CSS_PROP_RESIZE:
2646 HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2648 if (!primitiveValue->getIdent()) return;
2651 switch(primitiveValue->getIdent()) {
2655 case CSS_VAL_HORIZONTAL:
2656 r = RESIZE_HORIZONTAL;
2658 case CSS_VAL_VERTICAL:
2659 r = RESIZE_VERTICAL;
2666 style->setResize(r);
2671 case CSS_PROP_MAX_WIDTH:
2673 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2677 case CSS_PROP_RIGHT:
2678 case CSS_PROP_BOTTOM:
2679 case CSS_PROP_WIDTH:
2680 case CSS_PROP_MIN_WIDTH:
2681 case CSS_PROP_MARGIN_TOP:
2682 case CSS_PROP_MARGIN_RIGHT:
2683 case CSS_PROP_MARGIN_BOTTOM:
2684 case CSS_PROP_MARGIN_LEFT:
2686 if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2687 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2688 l = Length(Intrinsic);
2691 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2692 l = Length(MinIntrinsic);
2696 if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2698 case CSS_PROP_PADDING_TOP:
2699 case CSS_PROP_PADDING_RIGHT:
2700 case CSS_PROP_PADDING_BOTTOM:
2701 case CSS_PROP_PADDING_LEFT:
2702 case CSS_PROP_TEXT_INDENT:
2706 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2707 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2708 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2709 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2710 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2711 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2712 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2713 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2714 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2715 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2716 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2717 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2718 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2719 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2720 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2721 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2724 else if (isInitial) {
2725 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2726 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2727 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2728 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2729 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2730 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2731 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2732 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2733 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2734 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2735 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2736 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2737 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2738 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2739 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2740 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2744 if (primitiveValue && !apply) {
2745 int type = primitiveValue->primitiveType();
2746 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2747 // Handle our quirky margin units if we have them.
2748 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed,
2749 primitiveValue->isQuirkValue());
2750 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2751 l = Length((int)primitiveValue->getFloatValue(), Percent);
2754 if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2755 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2756 // Padding can't be negative
2757 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
2764 case CSS_PROP_MAX_WIDTH:
2765 style->setMaxWidth(l); break;
2766 case CSS_PROP_BOTTOM:
2767 style->setBottom(l); break;
2769 style->setTop(l); break;
2771 style->setLeft(l); break;
2772 case CSS_PROP_RIGHT:
2773 style->setRight(l); break;
2774 case CSS_PROP_WIDTH:
2775 style->setWidth(l); break;
2776 case CSS_PROP_MIN_WIDTH:
2777 style->setMinWidth(l); break;
2778 case CSS_PROP_PADDING_TOP:
2779 style->setPaddingTop(l); break;
2780 case CSS_PROP_PADDING_RIGHT:
2781 style->setPaddingRight(l); break;
2782 case CSS_PROP_PADDING_BOTTOM:
2783 style->setPaddingBottom(l); break;
2784 case CSS_PROP_PADDING_LEFT:
2785 style->setPaddingLeft(l); break;
2786 case CSS_PROP_MARGIN_TOP:
2787 style->setMarginTop(l); break;
2788 case CSS_PROP_MARGIN_RIGHT:
2789 style->setMarginRight(l); break;
2790 case CSS_PROP_MARGIN_BOTTOM:
2791 style->setMarginBottom(l); break;
2792 case CSS_PROP_MARGIN_LEFT:
2793 style->setMarginLeft(l); break;
2794 case CSS_PROP_TEXT_INDENT:
2795 style->setTextIndent(l); break;
2801 case CSS_PROP_MAX_HEIGHT:
2802 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
2803 l = Length(undefinedLength, Fixed);
2806 case CSS_PROP_HEIGHT:
2807 case CSS_PROP_MIN_HEIGHT:
2808 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2809 l = Length(Intrinsic);
2811 } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2812 l = Length(MinIntrinsic);
2814 } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2817 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2818 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2819 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2823 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2824 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2825 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2829 if (primitiveValue && !apply) {
2830 unsigned short type = primitiveValue->primitiveType();
2831 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2832 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2833 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2834 l = Length((int)primitiveValue->getFloatValue(), Percent);
2841 case CSS_PROP_MAX_HEIGHT:
2842 style->setMaxHeight(l);
2844 case CSS_PROP_HEIGHT:
2845 style->setHeight(l);
2847 case CSS_PROP_MIN_HEIGHT:
2848 style->setMinHeight(l);
2853 case CSS_PROP_VERTICAL_ALIGN:
2854 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2855 if (!primitiveValue) return;
2856 if (primitiveValue->getIdent()) {
2857 EVerticalAlign align;
2859 switch(primitiveValue->getIdent())
2863 case CSS_VAL_BOTTOM:
2864 align = BOTTOM; break;
2865 case CSS_VAL_MIDDLE:
2866 align = MIDDLE; break;
2867 case CSS_VAL_BASELINE:
2868 align = BASELINE; break;
2869 case CSS_VAL_TEXT_BOTTOM:
2870 align = TEXT_BOTTOM; break;
2871 case CSS_VAL_TEXT_TOP:
2872 align = TEXT_TOP; break;
2876 align = SUPER; break;
2877 case CSS_VAL__WEBKIT_BASELINE_MIDDLE:
2878 align = BASELINE_MIDDLE; break;
2882 style->setVerticalAlign(align);
2885 int type = primitiveValue->primitiveType();
2887 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2888 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2889 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2890 l = Length(int(primitiveValue->getFloatValue()), Percent);
2892 style->setVerticalAlign(LENGTH);
2893 style->setVerticalAlignLength(l);
2897 case CSS_PROP_FONT_SIZE:
2899 FontDescription fontDescription = style->fontDescription();
2903 bool parentIsAbsoluteSize = false;
2905 oldSize = parentStyle->fontDescription().specifiedSize();
2906 parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
2912 size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks());
2913 else if (primitiveValue->getIdent()) {
2914 // Keywords are being used.
2915 switch (primitiveValue->getIdent()) {
2916 case CSS_VAL_XX_SMALL:
2917 case CSS_VAL_X_SMALL:
2919 case CSS_VAL_MEDIUM:
2921 case CSS_VAL_X_LARGE:
2922 case CSS_VAL_XX_LARGE:
2923 case CSS_VAL__WEBKIT_XXX_LARGE:
2924 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks());
2926 case CSS_VAL_LARGER:
2927 size = largerFontSize(oldSize, style->htmlHacks());
2929 case CSS_VAL_SMALLER:
2930 size = smallerFontSize(oldSize, style->htmlHacks());
2936 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
2937 (primitiveValue->getIdent() == CSS_VAL_LARGER ||
2938 primitiveValue->getIdent() == CSS_VAL_SMALLER));
2940 int type = primitiveValue->primitiveType();
2941 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
2942 (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
2943 type != CSSPrimitiveValue::CSS_EMS &&
2944 type != CSSPrimitiveValue::CSS_EXS));
2945 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2946 size = primitiveValue->computeLengthFloat(parentStyle, false);
2947 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2948 size = (primitiveValue->getFloatValue() * oldSize) / 100;
2956 setFontSize(fontDescription, size);
2957 if (style->setFontDescription(fontDescription))
2962 case CSS_PROP_Z_INDEX:
2964 HANDLE_INHERIT(zIndex, ZIndex)
2965 else if (isInitial) {
2966 style->setHasAutoZIndex();
2970 if (!primitiveValue)
2973 if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
2974 style->setHasAutoZIndex();
2978 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2979 return; // Error case.
2981 style->setZIndex((int)primitiveValue->getFloatValue());
2986 case CSS_PROP_WIDOWS:
2988 HANDLE_INHERIT_AND_INITIAL(widows, Widows)
2989 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2991 style->setWidows((int)primitiveValue->getFloatValue());
2995 case CSS_PROP_ORPHANS:
2997 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
2998 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3000 style->setOrphans((int)primitiveValue->getFloatValue());
3004 // length, percent, number
3005 case CSS_PROP_LINE_HEIGHT:
3007 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
3008 if(!primitiveValue) return;
3010 int type = primitiveValue->primitiveType();
3011 if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
3012 lineHeight = Length(-100, Percent);
3013 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3014 double multiplier = 1.0;
3015 // Scale for the font zoom factor only for types other than "em" and "ex", since those are
3016 // already based on the font size.
3017 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->frame()) {
3018 multiplier = view->frame()->zoomFactor() / 100.0;
3020 lineHeight = Length(primitiveValue->computeLengthIntForLength(style, multiplier), Fixed);
3021 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3022 lineHeight = Length((style->fontSize() * int(primitiveValue->getFloatValue())) / 100, Fixed);
3023 else if (type == CSSPrimitiveValue::CSS_NUMBER)
3024 lineHeight = Length(int(primitiveValue->getFloatValue() * 100), Percent);
3027 style->setLineHeight(lineHeight);
3032 case CSS_PROP_TEXT_ALIGN:
3034 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
3035 if (!primitiveValue) return;
3036 if (primitiveValue->getIdent())
3037 style->setTextAlign((ETextAlign) (primitiveValue->getIdent() - CSS_VAL__WEBKIT_AUTO));
3048 bool hasClip = true;
3050 if (parentStyle->hasClip()) {
3051 top = parentStyle->clipTop();
3052 right = parentStyle->clipRight();
3053 bottom = parentStyle->clipBottom();
3054 left = parentStyle->clipLeft();
3058 top = right = bottom = left = Length();
3060 } else if (isInitial) {
3062 top = right = bottom = left = Length();
3063 } else if (!primitiveValue) {
3065 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3066 RectImpl* rect = primitiveValue->getRectValue();
3069 top = convertToLength(rect->top(), style);
3070 right = convertToLength(rect->right(), style);
3071 bottom = convertToLength(rect->bottom(), style);
3072 left = convertToLength(rect->left(), style);
3074 } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) {
3077 style->setClip(top, right, bottom, left);
3078 style->setHasClip(hasClip);
3085 case CSS_PROP_CONTENT:
3086 // list of string, uri, counter, attr, i
3088 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
3089 // note is a reminder that eventually "inherit" needs to be supported.
3090 if (!(style->styleType()==RenderStyle::BEFORE ||
3091 style->styleType()==RenderStyle::AFTER))
3095 if (style->contentData())
3096 style->contentData()->clearContent();
3100 if (!value->isValueList()) return;
3101 CSSValueList *list = static_cast<CSSValueList*>(value);
3102 int len = list->length();
3104 for (int i = 0; i < len; i++) {
3105 CSSValue *item = list->item(i);
3106 if (!item->isPrimitiveValue()) continue;
3107 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3108 if (val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
3109 style->setContent(val->getStringValue().impl(), i != 0);
3110 else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) {
3111 // FIXME: Can a namespace be specified for an attr(foo)?
3112 if (style->styleType() == RenderStyle::NOPSEUDO)
3115 parentStyle->setUnique();
3116 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
3117 style->setContent(element->getAttribute(attr).impl(), i != 0);
3118 // register the fact that the attribute value affects the style
3119 m_selectorAttrs.add(attr.localName().impl());
3121 else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) {
3122 CSSImageValue *image = static_cast<CSSImageValue*>(val);
3123 style->setContent(image->image(element->document()->docLoader()), i != 0);
3129 case CSS_PROP_COUNTER_INCREMENT:
3130 // list of CSS2CounterIncrement
3131 case CSS_PROP_COUNTER_RESET:
3132 // list of CSS2CounterReset
3134 case CSS_PROP_FONT_FAMILY: {
3135 // list of strings and ids
3137 FontDescription parentFontDescription = parentStyle->fontDescription();
3138 FontDescription fontDescription = style->fontDescription();
3139 fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3140 fontDescription.setFamily(parentFontDescription.firstFamily());
3141 if (style->setFontDescription(fontDescription))
3145 else if (isInitial) {
3146 FontDescription initialDesc = FontDescription();
3147 FontDescription fontDescription = style->fontDescription();
3148 fontDescription.setGenericFamily(initialDesc.genericFamily());
3149 fontDescription.setFamily(initialDesc.firstFamily());
3150 if (style->setFontDescription(fontDescription))
3155 if (!value->isValueList()) return;
3156 FontDescription fontDescription = style->fontDescription();
3157 CSSValueList *list = static_cast<CSSValueList*>(value);
3158 int len = list->length();
3159 FontFamily& firstFamily = fontDescription.firstFamily();
3160 FontFamily *currFamily = 0;
3162 for(int i = 0; i < len; i++) {
3163 CSSValue *item = list->item(i);
3164 if(!item->isPrimitiveValue()) continue;
3165 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3167 if(val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
3168 face = static_cast<FontFamilyValue*>(val)->fontName();
3169 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3170 switch (val->getIdent()) {
3171 case CSS_VAL__WEBKIT_BODY:
3172 face = settings->stdFontName();
3175 face = settings->serifFontName();
3176 fontDescription.setGenericFamily(FontDescription::SerifFamily);
3178 case CSS_VAL_SANS_SERIF:
3179 face = settings->sansSerifFontName();
3180 fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3182 case CSS_VAL_CURSIVE:
3183 face = settings->cursiveFontName();
3184 fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3186 case CSS_VAL_FANTASY:
3187 face = settings->fantasyFontName();
3188 fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3190 case CSS_VAL_MONOSPACE:
3191 face = settings->fixedFontName();
3192 fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3197 if (!face.isEmpty()) {
3199 // Filling in the first family.
3200 firstFamily.setFamily(face);
3201 currFamily = &firstFamily;
3204 FontFamily *newFamily = new FontFamily;
3205 newFamily->setFamily(face);
3206 currFamily->appendFamily(newFamily);
3207 currFamily = newFamily;
3210 if (style->setFontDescription(fontDescription))
3216 case CSS_PROP_QUOTES:
3217 // list of strings or i
3221 case CSS_PROP_TEXT_DECORATION: {
3223 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3224 int t = RenderStyle::initialTextDecoration();
3225 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3228 if(!value->isValueList()) return;
3229 CSSValueList *list = static_cast<CSSValueList*>(value);
3230 int len = list->length();
3231 for(int i = 0; i < len; i++)
3233 CSSValue *item = list->item(i);
3234 if(!item->isPrimitiveValue()) continue;
3235 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3236 switch(primitiveValue->getIdent())
3240 case CSS_VAL_UNDERLINE:
3241 t |= UNDERLINE; break;
3242 case CSS_VAL_OVERLINE:
3243 t |= OVERLINE; break;
3244 case CSS_VAL_LINE_THROUGH:
3245 t |= LINE_THROUGH; break;
3254 style->setTextDecoration(t);
3258 // shorthand properties
3259 case CSS_PROP_BACKGROUND:
3261 style->clearBackgroundLayers();
3264 else if (isInherit) {
3266 style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
3268 style->clearBackgroundLayers();
3272 case CSS_PROP_BORDER:
3273 case CSS_PROP_BORDER_STYLE:
3274 case CSS_PROP_BORDER_WIDTH:
3275 case CSS_PROP_BORDER_COLOR:
3276 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
3279 style->setBorderTopColor(parentStyle->borderTopColor());
3280 style->setBorderBottomColor(parentStyle->borderBottomColor());
3281 style->setBorderLeftColor(parentStyle->borderLeftColor());
3282 style->setBorderRightColor(parentStyle->borderRightColor());
3284 else if (isInitial) {
3285 style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
3286 style->setBorderBottomColor(Color());
3287 style->setBorderLeftColor(Color());
3288 style->setBorderRightColor(Color());
3291 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
3294 style->setBorderTopStyle(parentStyle->borderTopStyle());
3295 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3296 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3297 style->setBorderRightStyle(parentStyle->borderRightStyle());
3299 else if (isInitial) {