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"
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->frame()->page(), m_rootDefaultStyle);
248 // FIXME: This sucks! The user sheet is reparsed every time!
249 if (!userStyleSheet.isEmpty()) {
250 m_userSheet = new CSSStyleSheet(doc);
251 m_userSheet->parseString(userStyleSheet, strictParsing);
253 m_userStyle = new CSSRuleSet();
254 m_userStyle->addRulesFromSheet(m_userSheet, m_medium);
257 // add stylesheets from document
258 m_authorStyle = new CSSRuleSet();
260 DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets);
261 for (; it.current(); ++it)
262 if (it.current()->isCSSStyleSheet() && !it.current()->disabled())
263 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), m_medium);
267 CSSStyleSelector::CSSStyleSelector(CSSStyleSheet *sheet)
273 FrameView *view = sheet->doc()->view();
276 m_medium = new MediaQueryEvaluator(view->mediaType());
278 m_medium = new MediaQueryEvaluator("all");
280 Element* root = sheet->doc()->documentElement();
282 m_rootDefaultStyle = styleForElement(root, 0, false, true);
284 if (m_rootDefaultStyle && view) {
286 m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame()->page(), m_rootDefaultStyle);
289 m_authorStyle = new CSSRuleSet();
290 m_authorStyle->addRulesFromSheet(sheet, m_medium);
293 void CSSStyleSelector::init()
297 m_matchedRules.clear();
298 m_matchedDecls.clear();
300 m_collectRulesOnly = false;
301 m_rootDefaultStyle = 0;
305 void CSSStyleSelector::setEncodedURL(const KURL& url)
309 u.setQuery(DeprecatedString::null);
310 u.setRef(DeprecatedString::null);
311 encodedurl.file = u.url();
312 int pos = encodedurl.file.findRev('/');
313 encodedurl.path = encodedurl.file;
315 encodedurl.path.truncate(pos);
316 encodedurl.path += '/';
318 u.setPath(DeprecatedString::null);
319 encodedurl.host = u.url();
322 CSSStyleSelector::~CSSStyleSelector()
325 ::delete m_rootDefaultStyle;
327 delete m_authorStyle;
332 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
334 CSSStyleSheet* const parent = 0;
335 CSSStyleSheet* sheet = new CSSStyleSheet(parent);
336 sheet->ref(); // leak the sheet on purpose since it will be stored in a global variable
337 sheet->parseString(String(characters, size));
341 template<typename T> CSSStyleSheet* parseUASheet(const T& array)
343 return parseUASheet(array, sizeof(array));
346 void CSSStyleSelector::loadDefaultStyle()
351 defaultStyle = new CSSRuleSet;
352 defaultPrintStyle = new CSSRuleSet;
353 defaultQuirksStyle = new CSSRuleSet;
354 defaultViewSourceStyle = new CSSRuleSet;
356 MediaQueryEvaluator screenEval("screen");
357 MediaQueryEvaluator printEval("print");
359 // Strict-mode rules.
360 defaultSheet = parseUASheet(html4UserAgentStyleSheet);
361 defaultStyle->addRulesFromSheet(defaultSheet, &screenEval);
362 defaultPrintStyle->addRulesFromSheet(defaultSheet, &printEval);
366 svgSheet = parseUASheet(svgUserAgentStyleSheet);
367 defaultStyle->addRulesFromSheet(svgSheet, &screenEval);
368 defaultPrintStyle->addRulesFromSheet(svgSheet, &printEval);
371 // Quirks-mode rules.
372 quirksSheet = parseUASheet(quirksUserAgentStyleSheet);
373 defaultQuirksStyle->addRulesFromSheet(quirksSheet, &screenEval);
375 // View source rules.
376 viewSourceSheet = parseUASheet(sourceUserAgentStyleSheet);
377 defaultViewSourceStyle->addRulesFromSheet(viewSourceSheet, &screenEval);
380 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
382 m_matchedRules.clear();
384 if (!rules || !element)
387 // We need to collect the rules for id, class, tag, and everything else into a buffer and
388 // then sort the buffer.
389 if (element->hasID())
390 matchRulesForList(rules->getIDRules(element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);
391 if (element->hasClass()) {
392 for (const AtomicStringList* singleClass = element->getClassList(); singleClass; singleClass = singleClass->next())
393 matchRulesForList(rules->getClassRules(singleClass->string().impl()), firstRuleIndex, lastRuleIndex);
395 matchRulesForList(rules->getTagRules(element->localName().impl()), firstRuleIndex, lastRuleIndex);
396 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
398 // If we didn't match any rules, we're done.
399 if (m_matchedRules.isEmpty())
402 // Sort the set of matched rules.
403 sortMatchedRules(0, m_matchedRules.size());
405 // Now transfer the set of matched rules over to our list of decls.
406 if (!m_collectRulesOnly) {
407 for (unsigned i = 0; i < m_matchedRules.size(); i++)
408 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
410 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
412 m_ruleList = new CSSRuleList();
413 m_ruleList->append(m_matchedRules[i]->rule());
418 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
423 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
424 CSSStyleRule* rule = d->rule();
425 const AtomicString& localName = element->localName();
426 const AtomicString& selectorLocalName = d->selector()->tag.localName();
427 if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector(), element)) {
428 // If the rule has no properties to apply, then ignore it.
429 CSSMutableStyleDeclaration* decl = rule->declaration();
430 if (!decl || !decl->length())
433 // If we're matching normal rules, set a pseudo bit if
434 // we really just matched a pseudo-element.
435 if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO) {
436 if (m_collectRulesOnly)
438 style->setHasPseudoStyle(dynamicPseudo);
440 // Update our first/last rule indices in the matched rules array.
441 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
442 if (firstRuleIndex == -1)
443 firstRuleIndex = lastRuleIndex;
445 // Add this rule to our list of matched rules.
452 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
454 int spec1 = r1.selector()->specificity();
455 int spec2 = r2.selector()->specificity();
456 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
458 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
463 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
465 if (start >= end || (end - start == 1))
466 return; // Sanity check.
468 if (end - start <= 6) {
469 // Apply a bubble sort for smaller lists.
470 for (unsigned i = end - 1; i > start; i--) {
472 for (unsigned j = start; j < i; j++) {
473 CSSRuleData* elt = m_matchedRules[j];
474 CSSRuleData* elt2 = m_matchedRules[j + 1];
477 m_matchedRules[j] = elt2;
478 m_matchedRules[j + 1] = elt;
487 // Peform a merge sort for larger lists.
488 unsigned mid = (start + end) / 2;
489 sortMatchedRules(start, mid);
490 sortMatchedRules(mid, end);
492 CSSRuleData* elt = m_matchedRules[mid - 1];
493 CSSRuleData* elt2 = m_matchedRules[mid];
495 // Handle the fast common case (of equal specificity). The list may already
496 // be completely sorted.
500 // We have to merge sort. Ensure our merge buffer is big enough to hold
502 Vector<CSSRuleData*> rulesMergeBuffer;
503 rulesMergeBuffer.reserveCapacity(end - start);
508 elt = m_matchedRules[i1];
509 elt2 = m_matchedRules[i2];
511 while (i1 < mid || i2 < end) {
512 if (i1 < mid && (i2 == end || *elt <= *elt2)) {
513 rulesMergeBuffer.append(elt);
515 elt = m_matchedRules[i1];
517 rulesMergeBuffer.append(elt2);
519 elt2 = m_matchedRules[i2];
523 for (unsigned i = start; i < end; i++)
524 m_matchedRules[i] = rulesMergeBuffer[i - start];
527 void CSSStyleSelector::initElementAndPseudoState(Element* e)
530 if (element && element->isStyledElement())
531 styledElement = static_cast<StyledElement*>(element);
534 currentEncodedURL = &encodedurl;
535 pseudoState = PseudoUnknown;
538 void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent)
540 // set some variables we will need
541 pseudoStyle = RenderStyle::NOPSEUDO;
543 parentNode = e->parentNode();
545 parentStyle = defaultParent;
547 parentStyle = parentNode ? parentNode->renderStyle() : 0;
548 view = element->document()->view();
549 isXMLDoc = !element->document()->isHTMLDocument();
550 frame = element->document()->frame();
551 settings = frame ? frame->settings() : 0;
555 m_matchedRules.clear();
556 m_matchedDecls.clear();
563 // modified version of the one in kurl.cpp
564 static void cleanpath(DeprecatedString &path)
567 while ((pos = path.find("/../")) != -1) {
570 prev = path.findRev("/", pos -1);
571 // don't remove the host, i.e. http://foo.org/../foo.html
572 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
575 // matching directory found ?
576 path.remove(prev, pos- prev + 3);
580 // Don't remove "//" from an anchor identifier. -rjw
581 // Set refPos to -2 to mean "I haven't looked for the anchor yet".
582 // We don't want to waste a function call on the search for the the anchor
583 // in the vast majority of cases where there is no "//" in the path.
585 while ((pos = path.find("//", pos)) != -1) {
587 refPos = path.find("#");
588 if (refPos > 0 && pos >= refPos)
591 if (pos == 0 || path[pos-1] != ':')
596 while ((pos = path.find("/./")) != -1)
600 static void checkPseudoState(Element *e, bool checkVisited = true)
603 pseudoState = PseudoNone;
607 const AtomicString& attr = e->getAttribute(hrefAttr);
609 pseudoState = PseudoNone;
614 pseudoState = PseudoAnyLink;
618 DeprecatedConstString cu(reinterpret_cast<const DeprecatedChar*>(attr.characters()), attr.length());
619 DeprecatedString u = cu.string();
620 if (!u.contains("://")) {
622 u.prepend(currentEncodedURL->host);
623 else if (u[0] == '#')
624 u.prepend(currentEncodedURL->file);
626 u.prepend(currentEncodedURL->path);
629 pseudoState = historyContains(u) ? PseudoVisited : PseudoLink;
632 #ifdef STYLE_SHARING_STATS
633 static int fraction = 0;
634 static int total = 0;
637 const int siblingThreshold = 10;
639 Node* CSSStyleSelector::locateCousinList(Element* parent)
641 if (parent && parent->isStyledElement()) {
642 StyledElement* p = static_cast<StyledElement*>(parent);
643 if (!p->inlineStyleDecl() && !p->hasID()) {
644 Node* r = p->previousSibling();
646 RenderStyle* st = p->renderStyle();
648 if (r->renderStyle() == st)
649 return r->lastChild();
650 if (subcount++ == siblingThreshold)
652 r = r->previousSibling();
655 r = locateCousinList(static_cast<Element*>(parent->parentNode()));
657 if (r->renderStyle() == st)
658 return r->lastChild();
659 if (subcount++ == siblingThreshold)
661 r = r->previousSibling();
668 bool CSSStyleSelector::canShareStyleWithElement(Node* n)
670 if (n->isStyledElement()) {
671 StyledElement* s = static_cast<StyledElement*>(n);
672 RenderStyle* style = s->renderStyle();
673 if (style && !style->unique() &&
674 (s->tagQName() == element->tagQName()) && !s->hasID() &&
675 (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
676 (s->hasMappedAttributes() == styledElement->hasMappedAttributes()) &&
677 (s->isLink() == element->isLink()) &&
678 !style->affectedByAttributeSelectors() &&
679 (s->hovered() == element->hovered()) &&
680 (s->active() == element->active()) &&
681 (s->focused() == element->focused()) &&
682 (s->isEnabled() == element->isEnabled()) &&
683 (s->isIndeterminate() == element->isIndeterminate()) &&
684 (s->isChecked() == element->isChecked()) &&
685 (s != s->document()->getCSSTarget() && element != element->document()->getCSSTarget()) &&
686 (s->getAttribute(typeAttr) == element->getAttribute(typeAttr))) {
687 bool classesMatch = true;
689 const AtomicString& class1 = element->getAttribute(classAttr);
690 const AtomicString& class2 = s->getAttribute(classAttr);
691 classesMatch = (class1 == class2);
695 bool mappedAttrsMatch = true;
696 if (s->hasMappedAttributes())
697 mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(styledElement->mappedAttributes());
698 if (mappedAttrsMatch) {
699 bool linksMatch = true;
701 // We need to check to see if the visited state matches.
702 Color linkColor = element->document()->linkColor();
703 Color visitedColor = element->document()->visitedLinkColor();
704 if (pseudoState == PseudoUnknown)
705 checkPseudoState(element, style->pseudoState() != PseudoAnyLink ||
706 linkColor != visitedColor);
707 linksMatch = (pseudoState == style->pseudoState());
719 RenderStyle* CSSStyleSelector::locateSharedStyle()
721 if (styledElement && !styledElement->inlineStyleDecl() && !styledElement->hasID() &&
722 !styledElement->document()->usesSiblingRules()) {
723 // Check previous siblings.
726 for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
728 if (canShareStyleWithElement(n))
729 return n->renderStyle();
730 if (count++ == siblingThreshold)
732 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
735 n = locateCousinList(static_cast<Element*>(element->parentNode()));
737 if (canShareStyleWithElement(n))
738 return n->renderStyle();
739 if (count++ == siblingThreshold)
741 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
747 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
749 // 1. First we match rules from the user agent sheet.
750 matchRules(defaultStyle, firstUARule, lastUARule);
752 // 2. In quirks mode, we match rules from the quirks user agent sheet.
754 matchRules(defaultQuirksStyle, firstUARule, lastUARule);
756 // 3. If our medium is print, then we match rules from the print sheet.
757 if (m_medium->mediaTypeMatch("print"))
758 matchRules(defaultPrintStyle, firstUARule, lastUARule);
760 // 4. If we're in view source mode, then we match rules from the view source style sheet.
761 if (view && view->frame() && view->frame()->inViewSourceMode())
762 matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
765 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
766 // relative units are interpreted according to document root element style, styled only with UA stylesheet
768 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
770 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
771 // will vanish if a style recalc happens during loading.
772 if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
773 if (!styleNotYetAvailable) {
774 styleNotYetAvailable = ::new RenderStyle();
775 styleNotYetAvailable->setDisplay(NONE);
776 styleNotYetAvailable->ref();
778 styleNotYetAvailable->ref();
779 return styleNotYetAvailable;
782 initElementAndPseudoState(e);
784 style = locateSharedStyle();
785 #ifdef STYLE_SHARING_STATS
786 fraction += style != 0;
788 printf("Sharing %d out of %d\n", fraction, total);
795 initForStyleResolve(e, defaultParent);
797 if (resolveForRootDefault) {
798 style = ::new RenderStyle();
799 // don't ref, because we want to delete this, but we cannot unref it
801 style = new (e->document()->renderArena()) RenderStyle();
805 style->inheritFrom(parentStyle);
809 int firstUARule = -1, lastUARule = -1;
810 int firstUserRule = -1, lastUserRule = -1;
811 int firstAuthorRule = -1, lastAuthorRule = -1;
812 matchUARules(firstUARule, lastUARule);
814 if (!resolveForRootDefault) {
815 // 4. Now we check user sheet rules.
816 matchRules(m_userStyle, firstUserRule, lastUserRule);
818 // 5. Now check author rules, beginning first with presentational attributes
821 // Ask if the HTML element has mapped attributes.
822 if (styledElement->hasMappedAttributes()) {
823 // Walk our attribute list and add in each decl.
824 const NamedMappedAttrMap* map = styledElement->mappedAttributes();
825 for (unsigned i = 0; i < map->length(); i++) {
826 MappedAttribute* attr = map->attributeItem(i);
828 lastAuthorRule = m_matchedDecls.size();
829 if (firstAuthorRule == -1)
830 firstAuthorRule = lastAuthorRule;
831 addMatchedDeclaration(attr->decl());
836 // Now we check additional mapped declarations.
837 // Tables and table cells share an additional mapped rule that must be applied
838 // after all attributes, since their mapped style depends on the values of multiple attributes.
839 CSSMutableStyleDeclaration* attributeDecl = styledElement->additionalAttributeStyleDecl();
841 lastAuthorRule = m_matchedDecls.size();
842 if (firstAuthorRule == -1)
843 firstAuthorRule = lastAuthorRule;
844 addMatchedDeclaration(attributeDecl);
848 // 6. Check the rules in author sheets next.
849 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
851 // 7. Now check our inline style attribute.
853 CSSMutableStyleDeclaration* inlineDecl = styledElement->inlineStyleDecl();
855 lastAuthorRule = m_matchedDecls.size();
856 if (firstAuthorRule == -1)
857 firstAuthorRule = lastAuthorRule;
858 addMatchedDeclaration(inlineDecl);
863 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
864 // high-priority properties first, i.e., those properties that other properties depend on.
865 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
866 // and (4) normal important.
867 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
868 if (!resolveForRootDefault) {
869 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
870 applyDeclarations(true, true, firstUserRule, lastUserRule);
872 applyDeclarations(true, true, firstUARule, lastUARule);
874 // If our font got dirtied, go ahead and update it now.
878 // Now do the normal priority UA properties.
879 applyDeclarations(false, false, firstUARule, lastUARule);
881 // Cache our border and background so that we can examine them later.
882 cacheBorderAndBackground();
884 // Now do the author and user normal priority properties and all the !important properties.
885 if (!resolveForRootDefault) {
886 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
887 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
888 applyDeclarations(false, true, firstUserRule, lastUserRule);
890 applyDeclarations(false, true, firstUARule, lastUARule);
892 // If our font got dirtied by one of the non-essential font props,
893 // go ahead and update it a second time.
897 // Clean up our style object's display and text decorations (among other fixups).
898 adjustRenderStyle(style, e);
900 // If we are a link, cache the determined pseudo-state.
902 style->setPseudoState(pseudoState);
904 // Now return the style.
908 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle)
913 initElementAndPseudoState(e);
914 initForStyleResolve(e, parentStyle);
915 pseudoStyle = pseudo;
917 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
920 // Check UA, user and author rules.
921 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
922 matchRules(defaultStyle, firstUARule, lastUARule);
923 matchRules(m_userStyle, firstUserRule, lastUserRule);
924 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
926 if (m_matchedDecls.isEmpty())
929 style = new (e->document()->renderArena()) RenderStyle();
932 style->inheritFrom(parentStyle);
935 style->noninherited_flags._styleType = pseudoStyle;
937 // High-priority properties.
938 applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
939 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
940 applyDeclarations(true, true, firstUserRule, lastUserRule);
941 applyDeclarations(true, true, firstUARule, lastUARule);
943 // If our font got dirtied, go ahead and update it now.
947 // Now do the normal priority properties.
948 applyDeclarations(false, false, firstUARule, lastUARule);
950 // Cache our border and background so that we can examine them later.
951 cacheBorderAndBackground();
953 applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
954 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
955 applyDeclarations(false, true, firstUserRule, lastUserRule);
956 applyDeclarations(false, true, firstUARule, lastUARule);
958 // If our font got dirtied by one of the non-essential font props,
959 // go ahead and update it a second time.
962 // Clean up our style object's display and text decorations (among other fixups).
963 adjustRenderStyle(style, 0);
965 // Now return the style.
969 static void addIntrinsicMargins(RenderStyle* style)
971 // Intrinsic margin value.
972 const int intrinsicMargin = 2;
974 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
975 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
976 if (style->width().isIntrinsicOrAuto()) {
977 if (style->marginLeft().quirk())
978 style->setMarginLeft(Length(intrinsicMargin, Fixed));
979 if (style->marginRight().quirk())
980 style->setMarginRight(Length(intrinsicMargin, Fixed));
983 if (style->height().isAuto()) {
984 if (style->marginTop().quirk())
985 style->setMarginTop(Length(intrinsicMargin, Fixed));
986 if (style->marginBottom().quirk())
987 style->setMarginBottom(Length(intrinsicMargin, Fixed));
991 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
993 // Cache our original display.
994 style->setOriginalDisplay(style->display());
996 if (style->display() != NONE) {
997 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
999 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1000 // these tags to retain their display types.
1001 if (!strictParsing && e) {
1002 if (e->hasTagName(tdTag)) {
1003 style->setDisplay(TABLE_CELL);
1004 style->setFloating(FNONE);
1006 else if (e->hasTagName(tableTag))
1007 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1010 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1011 // fix a crash where a site tries to position these objects. They also never honor display.
1012 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1013 style->setPosition(StaticPosition);
1014 style->setDisplay(BLOCK);
1017 // Table headers with a text-align of auto will change the text-align to center.
1018 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1019 style->setTextAlign(CENTER);
1021 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1022 // position or float an inline, compact, or run-in. Cache the original display, since it
1023 // may be needed for positioned elements that have to compute their static normal flow
1024 // positions. We also force inline-level roots to be block-level.
1025 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1026 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1027 (e && e->document()->documentElement() == e))) {
1028 if (style->display() == INLINE_TABLE)
1029 style->setDisplay(TABLE);
1030 else if (style->display() == INLINE_BOX)
1031 style->setDisplay(BOX);
1032 else if (style->display() == LIST_ITEM) {
1033 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1034 // but only in quirks mode.
1035 if (!strictParsing && style->floating() != FNONE)
1036 style->setDisplay(BLOCK);
1039 style->setDisplay(BLOCK);
1042 // After performing the display mutation, check table rows. We do not honor position:relative on
1043 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1045 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1046 style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1047 style->position() == RelativePosition)
1048 style->setPosition(StaticPosition);
1051 // Make sure our z-index value is only applied if the object is positioned,
1052 // relatively positioned, or transparent.
1053 if (style->position() == StaticPosition && style->opacity() == 1.0f)
1054 style->setHasAutoZIndex();
1056 // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1057 // cases where objects that should be blended as a single unit end up with a non-transparent
1058 // object wedged in between them.
1059 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f))
1060 style->setZIndex(0);
1062 // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
1063 // This will be important when we use block flows for all form controls.
1064 if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
1065 e->hasTagName(selectTag) || e->hasTagName(textareaTag))) {
1066 if (style->width().isAuto())
1067 style->setWidth(Length(Intrinsic));
1070 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1071 // tables, inline blocks, inline tables, or run-ins.
1072 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1073 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1074 style->setTextDecorationsInEffect(style->textDecoration());
1076 style->addToTextDecorationsInEffect(style->textDecoration());
1078 // If either overflow value is not visible, change to auto.
1079 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1080 style->setOverflowY(OMARQUEE);
1081 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1082 style->setOverflowX(OMARQUEE);
1083 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1084 style->setOverflowX(OAUTO);
1085 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1086 style->setOverflowY(OAUTO);
1088 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1089 // FIXME: Eventually table sections will support auto and scroll.
1090 if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1091 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1092 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1093 style->setOverflowX(OVISIBLE);
1094 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1095 style->setOverflowY(OVISIBLE);
1098 // Links should be user selectable when content editable
1099 if (e && e->isLink() && (e->isContentEditable() || style->userModify() == READ_WRITE || style->userModify() == READ_WRITE_PLAINTEXT_ONLY))
1100 style->setUserSelect(SELECT_AUTO);
1102 // Cull out any useless layers and also repeat patterns into additional layers.
1103 style->adjustBackgroundLayers();
1105 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1106 // alter fonts and heights/widths.
1107 if (e && e->isControl() && style->fontSize() >= 11) {
1108 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1109 // so we have to treat all image buttons as though they were explicitly sized.
1110 if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE)
1111 addIntrinsicMargins(style);
1114 // Let the theme also have a crack at adjusting the style.
1115 if (style->hasAppearance())
1116 theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1119 if (e && e->isSVGElement()) {
1120 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1121 if (style->overflowY() == OSCROLL)
1122 style->setOverflowY(OHIDDEN);
1123 else if (style->overflowY() == OAUTO)
1124 style->setOverflowY(OVISIBLE);
1126 if (style->overflowX() == OSCROLL)
1127 style->setOverflowX(OHIDDEN);
1128 else if (style->overflowX() == OAUTO)
1129 style->setOverflowX(OVISIBLE);
1134 void CSSStyleSelector::updateFont()
1136 checkForTextSizeAdjust();
1137 checkForGenericFamilyChange(style, parentStyle);
1138 style->font().update();
1142 void CSSStyleSelector::cacheBorderAndBackground()
1144 m_hasUAAppearance = style->hasAppearance();
1145 if (m_hasUAAppearance) {
1146 m_borderData = style->border();
1147 m_backgroundData = *style->backgroundLayers();
1148 m_backgroundColor = style->backgroundColor();
1152 RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
1154 if (!e->document()->haveStylesheetsLoaded())
1157 m_collectRulesOnly = true;
1159 initElementAndPseudoState(e);
1160 initForStyleResolve(e, 0);
1163 int firstUARule = -1, lastUARule = -1;
1164 // First we match rules from the user agent sheet.
1165 matchUARules(firstUARule, lastUARule);
1167 // Now we check user sheet rules.
1168 int firstUserRule = -1, lastUserRule = -1;
1169 matchRules(m_userStyle, firstUserRule, lastUserRule);
1172 // Check the rules in author sheets.
1173 int firstAuthorRule = -1, lastAuthorRule = -1;
1174 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1176 m_collectRulesOnly = false;
1181 RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, StringImpl* pseudoStyle, bool authorOnly)
1183 // FIXME: Implement this.
1187 static bool subject;
1189 bool CSSStyleSelector::checkSelector(CSSSelector* sel, Element *e)
1191 dynamicPseudo = RenderStyle::NOPSEUDO;
1195 // we have the subject part of the selector
1198 // We track whether or not the rule contains only :hover and :active in a simple selector. If
1199 // so, we can't allow that to apply to every element on the page. We assume the author intended
1200 // to apply the rules only to links.
1201 bool onlyHoverActive = (!sel->hasTag() &&
1202 (sel->match == CSSSelector::PseudoClass &&
1203 (sel->pseudoType() == CSSSelector::PseudoHover ||
1204 sel->pseudoType() == CSSSelector::PseudoActive)));
1205 bool affectedByHover = style ? style->affectedByHoverRules() : false;
1206 bool affectedByActive = style ? style->affectedByActiveRules() : false;
1207 bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
1209 // first selector has to match
1210 if (!checkOneSelector(sel, e))
1213 // check the subselectors
1214 CSSSelector::Relation relation = sel->relation();
1215 while((sel = sel->tagHistory)) {
1216 if (!n->isElementNode())
1218 if (relation != CSSSelector::SubSelector) {
1220 if (havePseudo && dynamicPseudo != pseudoStyle)
1226 case CSSSelector::Descendant:
1227 // FIXME: This match needs to know how to backtrack and be non-deterministic.
1229 n = n->parentNode();
1230 if (!n || !n->isElementNode())
1232 } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1234 case CSSSelector::Child:
1236 n = n->parentNode();
1238 while (n && n->implicitNode())
1239 n = n->parentNode();
1240 if (!n || !n->isElementNode())
1242 if (!checkOneSelector(sel, static_cast<Element*>(n)))
1246 case CSSSelector::DirectAdjacent:
1248 n = n->previousSibling();
1249 while (n && !n->isElementNode())
1250 n = n->previousSibling();
1253 if (!checkOneSelector(sel, static_cast<Element*>(n)))
1257 case CSSSelector::IndirectAdjacent:
1258 // FIXME: This match needs to know how to backtrack and be non-deterministic.
1260 n = n->previousSibling();
1261 while (n && !n->isElementNode())
1262 n = n->previousSibling();
1265 } while (!checkOneSelector(sel, static_cast<Element*>(n)));
1267 case CSSSelector::SubSelector:
1269 if (onlyHoverActive)
1270 onlyHoverActive = (sel->match == CSSSelector::PseudoClass &&
1271 (sel->pseudoType() == CSSSelector::PseudoHover ||
1272 sel->pseudoType() == CSSSelector::PseudoActive));
1274 Element *elem = static_cast<Element*>(n);
1275 // a selector is invalid if something follows :first-xxx
1276 if (elem == element && dynamicPseudo != RenderStyle::NOPSEUDO)
1278 if (!checkOneSelector(sel, elem, true))
1283 relation = sel->relation();
1286 if (subject && havePseudo && dynamicPseudo != pseudoStyle)
1289 // disallow *:hover, *:active, and *:hover:active except for links
1290 if (!strictParsing && onlyHoverActive && subject) {
1291 if (pseudoState == PseudoUnknown)
1292 checkPseudoState(e);
1294 if (pseudoState == PseudoNone) {
1295 if (!affectedByHover && style->affectedByHoverRules())
1296 style->setAffectedByHoverRules(false);
1297 if (!affectedByActive && style->affectedByActiveRules())
1298 style->setAffectedByActiveRules(false);
1306 bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSubSelector)
1311 if (sel->hasTag()) {
1312 const AtomicString& localName = e->localName();
1313 const AtomicString& ns = e->namespaceURI();
1314 const AtomicString& selLocalName = sel->tag.localName();
1315 const AtomicString& selNS = sel->tag.namespaceURI();
1317 if ((selLocalName != starAtom && localName != selLocalName) ||
1318 (selNS != starAtom && ns != selNS))
1322 if (sel->hasAttribute()) {
1323 if (sel->match == CSSSelector::Class) {
1326 for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1327 if (c->string() == sel->value)
1331 else if (sel->match == CSSSelector::Id)
1332 return e->hasID() && e->getIDAttribute() == sel->value;
1333 else if (style && (e != element || !styledElement || (!styledElement->isMappedAttribute(sel->attr) && sel->attr != typeAttr))) {
1334 style->setAffectedByAttributeSelectors(); // Special-case the "type" attribute so input form controls can share style.
1335 m_selectorAttrs.add(sel->attr.localName().impl());
1338 const AtomicString& value = e->getAttribute(sel->attr);
1340 return false; // attribute is not set
1342 switch(sel->match) {
1343 case CSSSelector::Exact:
1344 if ((isXMLDoc && sel->value != value) || (!isXMLDoc && !equalIgnoringCase(sel->value, value)))
1347 case CSSSelector::List:
1349 // The selector's value can't contain a space, or it's totally bogus.
1350 if (sel->value.contains(' '))
1353 int startSearchAt = 0;
1355 int foundPos = value.find(sel->value, startSearchAt, isXMLDoc);
1358 if (foundPos == 0 || value[foundPos-1] == ' ') {
1359 unsigned endStr = foundPos + sel->value.length();
1360 if (endStr == value.length() || value[endStr] == ' ')
1361 break; // We found a match.
1364 // No match. Keep looking.
1365 startSearchAt = foundPos + 1;
1369 case CSSSelector::Contain:
1370 if (!value.contains(sel->value, isXMLDoc))
1373 case CSSSelector::Begin:
1374 if (!value.startsWith(sel->value, isXMLDoc))
1377 case CSSSelector::End:
1378 if (!value.endsWith(sel->value, isXMLDoc))
1381 case CSSSelector::Hyphen:
1382 if (value.length() < sel->value.length())
1384 if (!value.startsWith(sel->value, isXMLDoc))
1386 // It they start the same, check for exact match or following '-':
1387 if (value.length() != sel->value.length() && value[sel->value.length()] != '-')
1390 case CSSSelector::PseudoClass:
1391 case CSSSelector::PseudoElement:
1396 if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
1398 // Pseudo elements. We need to check first child here. No dynamic pseudo
1399 // elements for the moment
1400 switch (sel->pseudoType()) {
1402 case CSSSelector::PseudoEmpty:
1403 if (!e->firstChild())
1406 case CSSSelector::PseudoFirstChild: {
1407 // first-child matches the first child that is an element!
1408 if (e->parentNode() && e->parentNode()->isElementNode()) {
1409 Node *n = e->previousSibling();
1410 while (n && !n->isElementNode())
1411 n = n->previousSibling();
1417 case CSSSelector::PseudoFirstOfType: {
1418 // first-of-type matches the first element of its type!
1419 if (e->parentNode() && e->parentNode()->isElementNode()) {
1420 const QualifiedName& type = e->tagQName();
1421 Node *n = e->previousSibling();
1423 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1425 n = n->previousSibling();
1432 case CSSSelector::PseudoLastChild: {
1433 // last-child matches the last child that is an element!
1434 if (e->parentNode() && e->parentNode()->isElementNode()) {
1435 Node *n = e->nextSibling();
1436 while (n && !n->isElementNode())
1437 n = n->nextSibling();
1443 case CSSSelector::PseudoLastOfType: {
1444 // last-of-type matches the last element of its type!
1445 if (e->parentNode() && e->parentNode()->isElementNode()) {
1446 const QualifiedName& type = e->tagQName();
1447 Node *n = e->nextSibling();
1449 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1451 n = n->nextSibling();
1458 case CSSSelector::PseudoOnlyChild: {
1459 // If both first-child and last-child apply, then only-child applies.
1460 if (e->parentNode() && e->parentNode()->isElementNode()) {
1461 Node *n = e->previousSibling();
1462 while (n && !n->isElementNode())
1463 n = n->previousSibling();
1465 n = e->nextSibling();
1466 while (n && !n->isElementNode())
1467 n = n->nextSibling();
1474 case CSSSelector::PseudoOnlyOfType: {
1475 // If both first-of-type and last-of-type apply, then only-of-type applies.
1476 if (e->parentNode() && e->parentNode()->isElementNode()) {
1477 const QualifiedName& type = e->tagQName();
1478 Node *n = e->previousSibling();
1479 while (n && !static_cast<Element*>(n)->hasTagName(type))
1480 n = n->previousSibling();
1482 n = e->nextSibling();
1483 while (n && !static_cast<Element*>(n)->hasTagName(type))
1484 n = n->nextSibling();
1491 case CSSSelector::PseudoTarget:
1492 if (e == e->document()->getCSSTarget())
1495 case CSSSelector::PseudoAnyLink:
1496 if (pseudoState == PseudoUnknown)
1497 checkPseudoState(e, false);
1498 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1501 case CSSSelector::PseudoAutofill:
1502 if (e && e->hasTagName(inputTag))
1503 return static_cast<HTMLInputElement*>(e)->autofilled();
1505 case CSSSelector::PseudoLink:
1506 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1507 checkPseudoState(e);
1508 if (pseudoState == PseudoLink)
1511 case CSSSelector::PseudoVisited:
1512 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1513 checkPseudoState(e);
1514 if (pseudoState == PseudoVisited)
1517 case CSSSelector::PseudoHover: {
1518 // If we're in quirks mode, then hover should never match anchors with no
1519 // href and *:hover should not match anything. This is important for sites like wsj.com.
1520 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1521 if (element == e && style)
1522 style->setAffectedByHoverRules(true);
1523 if (element != e && e->renderStyle())
1524 e->renderStyle()->setAffectedByHoverRules(true);
1530 case CSSSelector::PseudoDrag: {
1531 if (element == e && style)
1532 style->setAffectedByDragRules(true);
1533 if (element != e && e->renderStyle())
1534 e->renderStyle()->setAffectedByDragRules(true);
1535 if (e->renderer() && e->renderer()->isDragging())
1539 case CSSSelector::PseudoFocus:
1540 if (e && e->focused() && e->document()->frame()->isActive())
1543 case CSSSelector::PseudoActive:
1544 // If we're in quirks mode, then :active should never match anchors with no
1545 // href and *:active should not match anything.
1546 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1547 if (element == e && style)
1548 style->setAffectedByActiveRules(true);
1549 else if (e->renderStyle())
1550 e->renderStyle()->setAffectedByActiveRules(true);
1555 case CSSSelector::PseudoEnabled:
1556 if (e && e->isControl())
1557 // The UI spec states that you can't match :enabled unless you are an object that can
1558 // "receive focus and be activated." We will limit matching of this pseudo-class to elements
1559 // that are controls.
1560 return e->isEnabled();
1562 case CSSSelector::PseudoDisabled:
1563 if (e && e->isControl())
1564 // The UI spec states that you can't match :enabled unless you are an object that can
1565 // "receive focus and be activated." We will limit matching of this pseudo-class to elements
1566 // that are controls.
1567 return !e->isEnabled();
1569 case CSSSelector::PseudoChecked:
1570 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
1571 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
1572 // obey the CSS spec here in the test for matching the pseudo.
1573 if (e && e->isChecked() && !e->isIndeterminate())
1576 case CSSSelector::PseudoIndeterminate:
1577 if (e && e->isIndeterminate())
1580 case CSSSelector::PseudoRoot:
1581 if (e == e->document()->documentElement())
1584 case CSSSelector::PseudoLang: {
1585 const AtomicString& value = e->getAttribute(langAttr);
1586 if (value.isEmpty() || !value.startsWith(sel->argument, false))
1588 if (value.length() != sel->argument.length() && value[sel->argument.length()] != '-')
1592 case CSSSelector::PseudoNot: {
1593 // check the simple selector
1594 for (CSSSelector* subSel = sel->simpleSelector; subSel; subSel = subSel->tagHistory) {
1595 // :not cannot nest. I don't really know why this is a
1596 // restriction in CSS3, but it is, so let's honour it.
1597 if (subSel->simpleSelector)
1599 if (!checkOneSelector(subSel, e))
1604 case CSSSelector::PseudoOther:
1608 case CSSSelector::PseudoFirstLine:
1610 dynamicPseudo=RenderStyle::FIRST_LINE;
1614 case CSSSelector::PseudoFirstLetter:
1616 dynamicPseudo=RenderStyle::FIRST_LETTER;
1620 case CSSSelector::PseudoSelection:
1621 dynamicPseudo = RenderStyle::SELECTION;
1623 case CSSSelector::PseudoBefore:
1624 dynamicPseudo = RenderStyle::BEFORE;
1626 case CSSSelector::PseudoAfter:
1627 dynamicPseudo = RenderStyle::AFTER;
1629 case CSSSelector::PseudoFileUploadButton:
1630 dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON;
1633 case CSSSelector::PseudoNotParsed:
1639 // ### add the rest of the checks...
1643 // -----------------------------------------------------------------
1645 CSSRuleSet::CSSRuleSet()
1647 m_universalRules = 0;
1651 CSSRuleSet::~CSSRuleSet()
1653 deleteAllValues(m_idRules);
1654 deleteAllValues(m_classRules);
1655 deleteAllValues(m_tagRules);
1657 delete m_universalRules;
1661 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1662 CSSStyleRule* rule, CSSSelector* sel)
1665 CSSRuleDataList* rules = map.get(key);
1667 rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1668 map.set(key, rules);
1670 rules->append(m_ruleCount++, rule, sel);
1673 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1675 if (sel->match == CSSSelector::Id) {
1676 addToRuleSet(sel->value.impl(), m_idRules, rule, sel);
1679 if (sel->match == CSSSelector::Class) {
1680 addToRuleSet(sel->value.impl(), m_classRules, rule, sel);
1684 const AtomicString& localName = sel->tag.localName();
1685 if (localName != starAtom) {
1686 addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1690 // Just put it in the universal rule set.
1691 if (!m_universalRules)
1692 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1694 m_universalRules->append(m_ruleCount++, rule, sel);
1697 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, MediaQueryEvaluator* medium)
1699 if (!sheet || !sheet->isCSSStyleSheet())
1702 // No media implies "all", but if a media list exists it must
1703 // contain our current medium
1704 if (sheet->media() && !medium->eval(sheet->media()))
1705 return; // the style sheet doesn't apply
1707 int len = sheet->length();
1709 for (int i = 0; i < len; i++) {
1710 StyleBase* item = sheet->item(i);
1711 if (item->isStyleRule()) {
1712 CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
1713 for (CSSSelector* s = rule->selector(); s; s = s->next())
1716 else if(item->isImportRule()) {
1717 CSSImportRule* import = static_cast<CSSImportRule*>(item);
1718 if (!import->media() || medium->eval(import->media()))
1719 addRulesFromSheet(import->styleSheet(), medium);
1721 else if(item->isMediaRule()) {
1722 CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
1723 CSSRuleList* rules = r->cssRules();
1725 if ((!r->media() || medium->eval(r->media())) && rules) {
1726 // Traverse child elements of the @media rule.
1727 for (unsigned j = 0; j < rules->length(); j++) {
1728 CSSRule *childItem = rules->item(j);
1729 if (childItem->isStyleRule()) {
1730 // It is a StyleRule, so append it to our list
1731 CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
1732 for (CSSSelector* s = rule->selector(); s; s = s->next())
1742 // -------------------------------------------------------------------------------------
1743 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1745 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
1748 if (!primitiveValue) {
1752 int type = primitiveValue->primitiveType();
1753 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1754 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
1755 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1756 l = Length(int(primitiveValue->getFloatValue()), Percent);
1757 else if(type == CSSPrimitiveValue::CSS_NUMBER)
1758 l = Length(int(primitiveValue->getFloatValue() * 100), Percent);
1765 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1766 int startIndex, int endIndex)
1768 if (startIndex == -1) return;
1769 for (int i = startIndex; i <= endIndex; i++) {
1770 CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
1771 DeprecatedValueListConstIterator<CSSProperty> end;
1772 for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
1773 const CSSProperty& current = *it;
1774 // give special priority to font-xxx, color properties
1775 if (isImportant == current.isImportant()) {
1777 switch(current.id()) {
1778 case CSS_PROP_COLOR:
1779 case CSS_PROP_DIRECTION:
1780 case CSS_PROP_DISPLAY:
1782 case CSS_PROP_FONT_SIZE:
1783 case CSS_PROP_FONT_STYLE:
1784 case CSS_PROP_FONT_FAMILY:
1785 case CSS_PROP_FONT_WEIGHT:
1786 case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST:
1787 case CSS_PROP_FONT_VARIANT:
1788 // these have to be applied first, because other properties use the computed
1789 // values of these porperties.
1797 if (first == applyFirst)
1798 applyProperty(current.id(), current.value());
1804 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
1806 CSSPrimitiveValue *primitiveValue = 0;
1807 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1812 unsigned short valueType = value->cssValueType();
1814 bool isInherit = parentNode && valueType == CSSValue::CSS_INHERIT;
1815 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!parentNode && valueType == CSSValue::CSS_INHERIT);
1817 // These properties are used to set the correct margins/padding on RTL lists.
1818 if (id == CSS_PROP__WEBKIT_MARGIN_START)
1819 id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
1820 else if (id == CSS_PROP__WEBKIT_PADDING_START)
1821 id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
1823 // What follows is a list that maps the CSS properties into their corresponding front-end
1824 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
1825 // are only hit when mapping "inherit" or "initial" into front-end values.
1828 // ident only properties
1829 case CSS_PROP_BACKGROUND_ATTACHMENT:
1830 HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
1832 case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
1833 HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
1835 case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
1836 HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value)
1838 case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN:
1839 HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
1841 case CSS_PROP_BACKGROUND_REPEAT:
1842 HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
1844 case CSS_PROP__WEBKIT_BACKGROUND_SIZE:
1845 HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
1847 case CSS_PROP_BORDER_COLLAPSE:
1848 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1849 if(!primitiveValue) break;
1850 switch(primitiveValue->getIdent())
1852 case CSS_VAL_COLLAPSE:
1853 style->setBorderCollapse(true);
1855 case CSS_VAL_SEPARATE:
1856 style->setBorderCollapse(false);
1863 case CSS_PROP_BORDER_TOP_STYLE:
1864 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1865 if (!primitiveValue) return;
1866 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1868 case CSS_PROP_BORDER_RIGHT_STYLE:
1869 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1870 if (!primitiveValue) return;
1871 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1873 case CSS_PROP_BORDER_BOTTOM_STYLE:
1874 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1875 if (!primitiveValue) return;
1876 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1878 case CSS_PROP_BORDER_LEFT_STYLE:
1879 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1880 if (!primitiveValue) return;
1881 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1883 case CSS_PROP_OUTLINE_STYLE:
1884 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1885 if (!primitiveValue) return;
1886 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1887 style->setOutlineStyle(DOTTED, true);
1889 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1891 case CSS_PROP_CAPTION_SIDE:
1893 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1894 if(!primitiveValue) break;
1895 ECaptionSide c = RenderStyle::initialCaptionSide();
1896 switch(primitiveValue->getIdent())
1901 c = CAPRIGHT; break;
1904 case CSS_VAL_BOTTOM:
1905 c = CAPBOTTOM; break;
1909 style->setCaptionSide(c);
1912 case CSS_PROP_CLEAR:
1914 HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1915 if(!primitiveValue) break;
1917 switch(primitiveValue->getIdent())
1933 case CSS_PROP_DIRECTION:
1935 HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1936 if(!primitiveValue) break;
1937 style->setDirection(primitiveValue->getIdent() == CSS_VAL_LTR ? LTR : RTL);
1940 case CSS_PROP_DISPLAY:
1942 HANDLE_INHERIT_AND_INITIAL(display, Display)
1943 if(!primitiveValue) break;
1944 int id = primitiveValue->getIdent();
1946 if (id == CSS_VAL_NONE)
1949 d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1951 style->setDisplay(d);
1955 case CSS_PROP_EMPTY_CELLS:
1957 HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1958 if (!primitiveValue) break;
1959 int id = primitiveValue->getIdent();
1960 if (id == CSS_VAL_SHOW)
1961 style->setEmptyCells(SHOW);
1962 else if (id == CSS_VAL_HIDE)
1963 style->setEmptyCells(HIDE);
1966 case CSS_PROP_FLOAT:
1968 HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1969 if(!primitiveValue) return;
1971 switch(primitiveValue->getIdent())
1978 case CSS_VAL_CENTER: //Non standart CSS-Value
1984 style->setFloating(f);
1989 case CSS_PROP_FONT_STRETCH:
1990 break; /* Not supported. */
1992 case CSS_PROP_FONT_STYLE:
1994 FontDescription fontDescription = style->fontDescription();
1996 fontDescription.setItalic(parentStyle->fontDescription().italic());
1998 fontDescription.setItalic(false);
2000 if (!primitiveValue) return;
2001 switch (primitiveValue->getIdent()) {
2002 case CSS_VAL_OBLIQUE:
2003 // FIXME: oblique is the same as italic for the moment...
2004 case CSS_VAL_ITALIC:
2005 fontDescription.setItalic(true);
2007 case CSS_VAL_NORMAL:
2008 fontDescription.setItalic(false);
2014 if (style->setFontDescription(fontDescription))
2019 case CSS_PROP_FONT_VARIANT:
2021 FontDescription fontDescription = style->fontDescription();
2023 fontDescription.setSmallCaps(parentStyle->fontDescription().smallCaps());
2025 fontDescription.setSmallCaps(false);
2027 if (!primitiveValue) return;
2028 int id = primitiveValue->getIdent();
2029 if (id == CSS_VAL_NORMAL)
2030 fontDescription.setSmallCaps(false);
2031 else if (id == CSS_VAL_SMALL_CAPS)
2032 fontDescription.setSmallCaps(true);
2036 if (style->setFontDescription(fontDescription))
2041 case CSS_PROP_FONT_WEIGHT:
2043 FontDescription fontDescription = style->fontDescription();
2045 fontDescription.setWeight(parentStyle->fontDescription().weight());
2047 fontDescription.setWeight(cNormalWeight);
2049 if (!primitiveValue) return;
2050 if (primitiveValue->getIdent()) {
2051 switch (primitiveValue->getIdent()) {
2052 // FIXME: We aren't genuinely supporting specific weight values.
2054 case CSS_VAL_BOLDER:
2059 fontDescription.setWeight(cBoldWeight);
2061 case CSS_VAL_NORMAL:
2062 case CSS_VAL_LIGHTER:
2068 fontDescription.setWeight(cNormalWeight);
2076 // ### fix parsing of 100-900 values in parser, apply them here
2079 if (style->setFontDescription(fontDescription))
2084 case CSS_PROP_LIST_STYLE_POSITION:
2086 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2087 if (!primitiveValue) return;
2088 if (primitiveValue->getIdent())
2089 style->setListStylePosition((EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE));
2093 case CSS_PROP_LIST_STYLE_TYPE:
2095 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2096 if (!primitiveValue) return;
2097 if (primitiveValue->getIdent())
2100 int id = primitiveValue->getIdent();
2101 if (id == CSS_VAL_NONE) { // important!!
2104 t = EListStyleType(id - CSS_VAL_DISC);
2106 style->setListStyleType(t);
2111 case CSS_PROP_OVERFLOW:
2114 style->setOverflowX(parentStyle->overflowX());
2115 style->setOverflowY(parentStyle->overflowY());
2120 style->setOverflowX(RenderStyle::initialOverflowX());
2121 style->setOverflowY(RenderStyle::initialOverflowY());
2126 switch(primitiveValue->getIdent()) {
2127 case CSS_VAL_VISIBLE:
2128 o = OVISIBLE; break;
2129 case CSS_VAL_HIDDEN:
2131 case CSS_VAL_SCROLL:
2135 case CSS_VAL__WEBKIT_MARQUEE:
2136 o = OMARQUEE; break;
2137 case CSS_VAL_OVERLAY:
2138 o = OOVERLAY; break;
2142 style->setOverflowX(o);
2143 style->setOverflowY(o);
2147 case CSS_PROP_OVERFLOW_X:
2149 HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
2151 switch(primitiveValue->getIdent())
2153 case CSS_VAL_VISIBLE:
2154 o = OVISIBLE; break;
2155 case CSS_VAL_HIDDEN:
2157 case CSS_VAL_SCROLL:
2161 case CSS_VAL_OVERLAY:
2162 o = OOVERLAY; break;
2166 style->setOverflowX(o);
2170 case CSS_PROP_OVERFLOW_Y:
2172 HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
2174 switch(primitiveValue->getIdent())
2176 case CSS_VAL_VISIBLE:
2177 o = OVISIBLE; break;
2178 case CSS_VAL_HIDDEN:
2180 case CSS_VAL_SCROLL:
2184 case CSS_VAL_OVERLAY:
2185 o = OOVERLAY; break;
2189 style->setOverflowY(o);
2193 case CSS_PROP_PAGE_BREAK_BEFORE:
2195 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2196 if (!primitiveValue) return;
2197 switch (primitiveValue->getIdent()) {
2199 style->setPageBreakBefore(PBAUTO);
2203 case CSS_VAL_ALWAYS:
2204 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2207 style->setPageBreakBefore(PBAVOID);
2213 case CSS_PROP_PAGE_BREAK_AFTER:
2215 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2216 if (!primitiveValue) return;
2217 switch (primitiveValue->getIdent()) {
2219 style->setPageBreakAfter(PBAUTO);
2223 case CSS_VAL_ALWAYS:
2224 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2227 style->setPageBreakAfter(PBAVOID);
2233 case CSS_PROP_PAGE_BREAK_INSIDE: {
2234 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2235 if (!primitiveValue) return;
2236 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2237 style->setPageBreakInside(PBAUTO);
2238 else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2239 style->setPageBreakInside(PBAVOID);
2244 break; /* FIXME: Not even sure what this is... -dwh */
2246 case CSS_PROP_POSITION:
2248 HANDLE_INHERIT_AND_INITIAL(position, Position)
2249 if(!primitiveValue) return;
2251 switch(primitiveValue->getIdent())
2253 case CSS_VAL_STATIC:
2256 case CSS_VAL_RELATIVE:
2257 p = RelativePosition;
2259 case CSS_VAL_ABSOLUTE:
2260 p = AbsolutePosition;
2268 style->setPosition(p);
2272 case CSS_PROP_TABLE_LAYOUT: {
2273 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2275 if (!primitiveValue->getIdent())
2278 ETableLayout l = RenderStyle::initialTableLayout();
2279 switch(primitiveValue->getIdent()) {
2284 style->setTableLayout(l);
2291 case CSS_PROP_UNICODE_BIDI: {
2292 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2293 switch (primitiveValue->getIdent()) {
2294 case CSS_VAL_NORMAL:
2295 style->setUnicodeBidi(UBNormal);
2298 style->setUnicodeBidi(Embed);
2300 case CSS_VAL_BIDI_OVERRIDE:
2301 style->setUnicodeBidi(Override);
2308 case CSS_PROP_TEXT_TRANSFORM: {
2309 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2311 if(!primitiveValue->getIdent()) return;
2314 switch(primitiveValue->getIdent()) {
2315 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break;
2316 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break;
2317 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break;
2319 default: tt = TTNONE; break;
2321 style->setTextTransform(tt);
2325 case CSS_PROP_VISIBILITY:
2327 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2329 switch(primitiveValue->getIdent()) {
2330 case CSS_VAL_HIDDEN:
2331 style->setVisibility(HIDDEN);
2333 case CSS_VAL_VISIBLE:
2334 style->setVisibility(VISIBLE);
2336 case CSS_VAL_COLLAPSE:
2337 style->setVisibility(COLLAPSE);
2343 case CSS_PROP_WHITE_SPACE:
2344 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2346 if(!primitiveValue->getIdent()) return;
2349 switch(primitiveValue->getIdent()) {
2350 case CSS_VAL__WEBKIT_NOWRAP:
2353 case CSS_VAL_NOWRAP:
2359 case CSS_VAL_PRE_WRAP:
2362 case CSS_VAL_PRE_LINE:
2365 case CSS_VAL_NORMAL:
2370 style->setWhiteSpace(s);
2373 case CSS_PROP_BACKGROUND_POSITION:
2374 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2375 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2377 case CSS_PROP_BACKGROUND_POSITION_X: {
2378 HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2381 case CSS_PROP_BACKGROUND_POSITION_Y: {
2382 HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2385 case CSS_PROP_BORDER_SPACING: {
2387 style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2388 style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2390 else if (isInitial) {
2391 style->setHorizontalBorderSpacing(0);
2392 style->setVerticalBorderSpacing(0);
2396 case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: {
2397 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2398 if (!primitiveValue) break;
2399 short spacing = primitiveValue->computeLengthShort(style);
2400 style->setHorizontalBorderSpacing(spacing);
2403 case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: {
2404 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2405 if (!primitiveValue) break;
2406 short spacing = primitiveValue->computeLengthShort(style);
2407 style->setVerticalBorderSpacing(spacing);
2410 case CSS_PROP_CURSOR:
2412 style->setCursor(parentStyle->cursor());
2413 style->setCursorImage(parentStyle->cursorImage());
2417 style->setCursor(RenderStyle::initialCursor());
2418 style->setCursorImage(0);
2421 if (primitiveValue) {
2422 int type = primitiveValue->primitiveType();
2423 if (type == CSSPrimitiveValue::CSS_IDENT) {
2424 style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
2425 style->setCursorImage(0);
2426 } else if (type == CSSPrimitiveValue::CSS_URI) {
2427 CSSImageValue* image = static_cast<CSSImageValue*>(primitiveValue);
2428 style->setCursor(CURSOR_AUTO);
2429 style->setCursorImage(image->image(element->document()->docLoader()));
2433 // colors || inherit
2434 case CSS_PROP_BACKGROUND_COLOR:
2435 case CSS_PROP_BORDER_TOP_COLOR:
2436 case CSS_PROP_BORDER_RIGHT_COLOR:
2437 case CSS_PROP_BORDER_BOTTOM_COLOR:
2438 case CSS_PROP_BORDER_LEFT_COLOR:
2439 case CSS_PROP_COLOR:
2440 case CSS_PROP_OUTLINE_COLOR:
2441 // this property is an extension used to get HTML4 <font> right.
2445 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2446 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2447 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2448 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2449 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2450 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2451 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2455 // The border/outline colors will just map to the invalid color |col| above. This will have the
2456 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2457 // not painting the background since the color won't be valid).
2458 if (id == CSS_PROP_COLOR)
2459 col = RenderStyle::initialColor();
2461 if (!primitiveValue)
2463 col = getColorFromPrimitiveValue(primitiveValue);
2467 case CSS_PROP_BACKGROUND_COLOR:
2468 style->setBackgroundColor(col); break;
2469 case CSS_PROP_BORDER_TOP_COLOR:
2470 style->setBorderTopColor(col); break;
2471 case CSS_PROP_BORDER_RIGHT_COLOR:
2472 style->setBorderRightColor(col); break;
2473 case CSS_PROP_BORDER_BOTTOM_COLOR:
2474 style->setBorderBottomColor(col); break;
2475 case CSS_PROP_BORDER_LEFT_COLOR:
2476 style->setBorderLeftColor(col); break;
2477 case CSS_PROP_COLOR:
2478 style->setColor(col); break;
2479 case CSS_PROP_OUTLINE_COLOR:
2480 style->setOutlineColor(col); break;
2487 case CSS_PROP_BACKGROUND_IMAGE:
2488 HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2490 case CSS_PROP_LIST_STYLE_IMAGE:
2492 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2493 if (!primitiveValue)
2495 style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(element->document()->docLoader()));
2500 case CSS_PROP_BORDER_TOP_WIDTH:
2501 case CSS_PROP_BORDER_RIGHT_WIDTH:
2502 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2503 case CSS_PROP_BORDER_LEFT_WIDTH:
2504 case CSS_PROP_OUTLINE_WIDTH:
2507 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2508 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2509 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2510 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2511 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2514 else if (isInitial) {
2515 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2516 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2517 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2518 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2519 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2523 if(!primitiveValue) break;
2525 switch(primitiveValue->getIdent())
2530 case CSS_VAL_MEDIUM:
2536 case CSS_VAL_INVALID:
2537 width = primitiveValue->computeLengthShort(style);
2543 if(width < 0) return;
2546 case CSS_PROP_BORDER_TOP_WIDTH:
2547 style->setBorderTopWidth(width);
2549 case CSS_PROP_BORDER_RIGHT_WIDTH:
2550 style->setBorderRightWidth(width);
2552 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2553 style->setBorderBottomWidth(width);
2555 case CSS_PROP_BORDER_LEFT_WIDTH:
2556 style->setBorderLeftWidth(width);
2558 case CSS_PROP_OUTLINE_WIDTH:
2559 style->setOutlineWidth(width);
2567 case CSS_PROP_LETTER_SPACING:
2568 case CSS_PROP_WORD_SPACING:
2572 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2573 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2576 else if (isInitial) {
2577 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2578 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2583 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2586 if(!primitiveValue) return;
2587 width = primitiveValue->computeLengthInt(style);
2591 case CSS_PROP_LETTER_SPACING:
2592 style->setLetterSpacing(width);
2594 case CSS_PROP_WORD_SPACING:
2595 style->setWordSpacing(width);
2597 // ### needs the definitions in renderstyle
2603 case CSS_PROP_WORD_WRAP:
2605 HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2607 if(!primitiveValue->getIdent()) return;
2610 switch(primitiveValue->getIdent()) {
2611 case CSS_VAL_BREAK_WORD:
2614 case CSS_VAL_NORMAL:
2619 style->setWordWrap(s);
2623 case CSS_PROP__WEBKIT_NBSP_MODE:
2625 HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2627 if (!primitiveValue->getIdent()) return;
2630 switch(primitiveValue->getIdent()) {
2634 case CSS_VAL_NORMAL:
2639 style->setNBSPMode(m);
2643 case CSS_PROP__WEBKIT_LINE_BREAK:
2645 HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2647 if (!primitiveValue->getIdent()) return;
2650 switch(primitiveValue->getIdent()) {
2651 case CSS_VAL_AFTER_WHITE_SPACE:
2652 b = AFTER_WHITE_SPACE;
2654 case CSS_VAL_NORMAL:
2659 style->setKHTMLLineBreak(b);
2663 case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:
2665 HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2667 if (!primitiveValue->getIdent()) return;
2669 EMatchNearestMailBlockquoteColor c;
2670 switch(primitiveValue->getIdent()) {
2671 case CSS_VAL_NORMAL:
2679 style->setMatchNearestMailBlockquoteColor(c);
2683 case CSS_PROP_RESIZE:
2685 HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2687 if (!primitiveValue->getIdent()) return;
2690 switch(primitiveValue->getIdent()) {
2694 case CSS_VAL_HORIZONTAL:
2695 r = RESIZE_HORIZONTAL;
2697 case CSS_VAL_VERTICAL:
2698 r = RESIZE_VERTICAL;
2701 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2708 style->setResize(r);
2713 case CSS_PROP_MAX_WIDTH:
2715 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2719 case CSS_PROP_RIGHT:
2720 case CSS_PROP_BOTTOM:
2721 case CSS_PROP_WIDTH:
2722 case CSS_PROP_MIN_WIDTH:
2723 case CSS_PROP_MARGIN_TOP:
2724 case CSS_PROP_MARGIN_RIGHT:
2725 case CSS_PROP_MARGIN_BOTTOM:
2726 case CSS_PROP_MARGIN_LEFT:
2728 if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2729 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2730 l = Length(Intrinsic);
2733 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2734 l = Length(MinIntrinsic);
2738 if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2740 case CSS_PROP_PADDING_TOP:
2741 case CSS_PROP_PADDING_RIGHT:
2742 case CSS_PROP_PADDING_BOTTOM:
2743 case CSS_PROP_PADDING_LEFT:
2744 case CSS_PROP_TEXT_INDENT:
2748 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2749 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2750 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2751 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2752 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2753 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2754 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2755 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2756 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2757 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2758 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2759 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2760 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2761 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2762 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2763 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2766 else if (isInitial) {
2767 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2768 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2769 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2770 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2771 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2772 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2773 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2774 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2775 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2776 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2777 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2778 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2779 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2780 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2781 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2782 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2786 if (primitiveValue && !apply) {
2787 int type = primitiveValue->primitiveType();
2788 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2789 // Handle our quirky margin units if we have them.
2790 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed,
2791 primitiveValue->isQuirkValue());
2792 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2793 l = Length((int)primitiveValue->getFloatValue(), Percent);
2796 if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2797 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2798 // Padding can't be negative
2799 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
2806 case CSS_PROP_MAX_WIDTH:
2807 style->setMaxWidth(l); break;
2808 case CSS_PROP_BOTTOM:
2809 style->setBottom(l); break;
2811 style->setTop(l); break;
2813 style->setLeft(l); break;
2814 case CSS_PROP_RIGHT:
2815 style->setRight(l); break;
2816 case CSS_PROP_WIDTH:
2817 style->setWidth(l); break;
2818 case CSS_PROP_MIN_WIDTH:
2819 style->setMinWidth(l); break;
2820 case CSS_PROP_PADDING_TOP:
2821 style->setPaddingTop(l); break;
2822 case CSS_PROP_PADDING_RIGHT:
2823 style->setPaddingRight(l); break;
2824 case CSS_PROP_PADDING_BOTTOM:
2825 style->setPaddingBottom(l); break;
2826 case CSS_PROP_PADDING_LEFT:
2827 style->setPaddingLeft(l); break;
2828 case CSS_PROP_MARGIN_TOP:
2829 style->setMarginTop(l); break;
2830 case CSS_PROP_MARGIN_RIGHT:
2831 style->setMarginRight(l); break;
2832 case CSS_PROP_MARGIN_BOTTOM:
2833 style->setMarginBottom(l); break;
2834 case CSS_PROP_MARGIN_LEFT:
2835 style->setMarginLeft(l); break;
2836 case CSS_PROP_TEXT_INDENT:
2837 style->setTextIndent(l); break;
2843 case CSS_PROP_MAX_HEIGHT:
2844 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
2845 l = Length(undefinedLength, Fixed);
2848 case CSS_PROP_HEIGHT:
2849 case CSS_PROP_MIN_HEIGHT:
2850 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2851 l = Length(Intrinsic);
2853 } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2854 l = Length(MinIntrinsic);
2856 } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO)
2859 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2860 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2861 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2865 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2866 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2867 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2871 if (primitiveValue && !apply) {
2872 unsigned short type = primitiveValue->primitiveType();
2873 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2874 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2875 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2876 l = Length((int)primitiveValue->getFloatValue(), Percent);
2883 case CSS_PROP_MAX_HEIGHT:
2884 style->setMaxHeight(l);
2886 case CSS_PROP_HEIGHT:
2887 style->setHeight(l);
2889 case CSS_PROP_MIN_HEIGHT:
2890 style->setMinHeight(l);
2895 case CSS_PROP_VERTICAL_ALIGN:
2896 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2897 if (!primitiveValue) return;
2898 if (primitiveValue->getIdent()) {
2899 EVerticalAlign align;
2901 switch(primitiveValue->getIdent())
2905 case CSS_VAL_BOTTOM:
2906 align = BOTTOM; break;
2907 case CSS_VAL_MIDDLE:
2908 align = MIDDLE; break;
2909 case CSS_VAL_BASELINE:
2910 align = BASELINE; break;
2911 case CSS_VAL_TEXT_BOTTOM:
2912 align = TEXT_BOTTOM; break;
2913 case CSS_VAL_TEXT_TOP:
2914 align = TEXT_TOP; break;
2918 align = SUPER; break;
2919 case CSS_VAL__WEBKIT_BASELINE_MIDDLE:
2920 align = BASELINE_MIDDLE; break;
2924 style->setVerticalAlign(align);
2927 int type = primitiveValue->primitiveType();
2929 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2930 l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2931 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2932 l = Length(int(primitiveValue->getFloatValue()), Percent);
2934 style->setVerticalAlign(LENGTH);
2935 style->setVerticalAlignLength(l);
2939 case CSS_PROP_FONT_SIZE:
2941 FontDescription fontDescription = style->fontDescription();
2942 fontDescription.setKeywordSize(0);
2943 bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
2947 bool parentIsAbsoluteSize = false;
2949 oldSize = parentStyle->fontDescription().specifiedSize();
2950 parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
2956 fontDescription.setKeywordSize(parentStyle->fontDescription().keywordSize());
2957 } else if (isInitial) {
2958 size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks(), familyIsFixed);
2959 fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1);
2960 } else if (primitiveValue->getIdent()) {
2961 // Keywords are being used.
2962 switch (primitiveValue->getIdent()) {
2963 case CSS_VAL_XX_SMALL:
2964 case CSS_VAL_X_SMALL:
2966 case CSS_VAL_MEDIUM:
2968 case CSS_VAL_X_LARGE:
2969 case CSS_VAL_XX_LARGE:
2970 case CSS_VAL__WEBKIT_XXX_LARGE:
2971 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks(), familyIsFixed);
2972 fontDescription.setKeywordSize(primitiveValue->getIdent() - CSS_VAL_XX_SMALL + 1);
2974 case CSS_VAL_LARGER:
2975 size = largerFontSize(oldSize, style->htmlHacks());
2977 case CSS_VAL_SMALLER:
2978 size = smallerFontSize(oldSize, style->htmlHacks());
2984 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
2985 (primitiveValue->getIdent() == CSS_VAL_LARGER ||
2986 primitiveValue->getIdent() == CSS_VAL_SMALLER));
2988 int type = primitiveValue->primitiveType();
2989 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
2990 (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
2991 type != CSSPrimitiveValue::CSS_EMS &&
2992 type != CSSPrimitiveValue::CSS_EXS));
2993 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2994 size = primitiveValue->computeLengthFloat(parentStyle, false);
2995 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2996 size = (primitiveValue->getFloatValue() * oldSize) / 100;
3004 setFontSize(fontDescription, size);
3005 if (style->setFontDescription(fontDescription))
3010 case CSS_PROP_Z_INDEX:
3012 HANDLE_INHERIT(zIndex, ZIndex)
3013 else if (isInitial) {
3014 style->setHasAutoZIndex();
3018 if (!primitiveValue)
3021 if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
3022 style->setHasAutoZIndex();
3026 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3027 return; // Error case.
3029 style->setZIndex((int)primitiveValue->getFloatValue());
3034 case CSS_PROP_WIDOWS:
3036 HANDLE_INHERIT_AND_INITIAL(widows, Widows)
3037 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3039 style->setWidows((int)primitiveValue->getFloatValue());
3043 case CSS_PROP_ORPHANS:
3045 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
3046 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3048 style->setOrphans((int)primitiveValue->getFloatValue());
3052 // length, percent, number
3053 case CSS_PROP_LINE_HEIGHT:
3055 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
3056 if(!primitiveValue) return;
3058 int type = primitiveValue->primitiveType();
3059 if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
3060 lineHeight = Length(-100, Percent);
3061 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3062 double multiplier = 1.0;
3063 // Scale for the font zoom factor only for types other than "em" and "ex", since those are
3064 // already based on the font size.
3065 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->frame()) {
3066 multiplier = view->frame()->zoomFactor() / 100.0;
3068 lineHeight = Length(primitiveValue->computeLengthIntForLength(style, multiplier), Fixed);
3069 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3070 lineHeight = Length((style->fontSize() * int(primitiveValue->getFloatValue())) / 100, Fixed);
3071 else if (type == CSSPrimitiveValue::CSS_NUMBER)
3072 lineHeight = Length(int(primitiveValue->getFloatValue() * 100), Percent);
3075 style->setLineHeight(lineHeight);
3080 case CSS_PROP_TEXT_ALIGN:
3082 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
3083 if (!primitiveValue) return;
3084 if (primitiveValue->getIdent())
3085 style->setTextAlign((ETextAlign) (primitiveValue->getIdent() - CSS_VAL__WEBKIT_AUTO));
3096 bool hasClip = true;
3098 if (parentStyle->hasClip()) {
3099 top = parentStyle->clipTop();
3100 right = parentStyle->clipRight();
3101 bottom = parentStyle->clipBottom();
3102 left = parentStyle->clipLeft();
3106 top = right = bottom = left = Length();
3108 } else if (isInitial) {
3110 top = right = bottom = left = Length();
3111 } else if (!primitiveValue) {
3113 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3114 RectImpl* rect = primitiveValue->getRectValue();
3117 top = convertToLength(rect->top(), style);
3118 right = convertToLength(rect->right(), style);
3119 bottom = convertToLength(rect->bottom(), style);
3120 left = convertToLength(rect->left(), style);
3122 } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) {
3125 style->setClip(top, right, bottom, left);
3126 style->setHasClip(hasClip);
3133 case CSS_PROP_CONTENT:
3134 // list of string, uri, counter, attr, i
3136 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
3137 // note is a reminder that eventually "inherit" needs to be supported.
3140 if (style->contentData())
3141 style->contentData()->clearContent();
3145 if (!value->isValueList()) return;
3146 CSSValueList *list = static_cast<CSSValueList*>(value);
3147 int len = list->length();
3149 for (int i = 0; i < len; i++) {
3150 CSSValue *item = list->item(i);
3151 if (!item->isPrimitiveValue()) continue;
3152 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3153 if (val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
3154 style->setContent(val->getStringValue().impl(), i != 0);
3155 else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) {
3156 // FIXME: Can a namespace be specified for an attr(foo)?
3157 if (style->styleType() == RenderStyle::NOPSEUDO)
3160 parentStyle->setUnique();
3161 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
3162 style->setContent(element->getAttribute(attr).impl(), i != 0);
3163 // register the fact that the attribute value affects the style
3164 m_selectorAttrs.add(attr.localName().impl());
3166 else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) {
3167 CSSImageValue *image = static_cast<CSSImageValue*>(val);
3168 style->setContent(image->image(element->document()->docLoader()), i != 0);
3174 case CSS_PROP_COUNTER_INCREMENT:
3175 // list of CSS2CounterIncrement
3176 case CSS_PROP_COUNTER_RESET:
3177 // list of CSS2CounterReset
3179 case CSS_PROP_FONT_FAMILY: {
3180 // list of strings and ids
3182 FontDescription parentFontDescription = parentStyle->fontDescription();
3183 FontDescription fontDescription = style->fontDescription();
3184 fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3185 fontDescription.setFamily(parentFontDescription.firstFamily());
3186 if (style->setFontDescription(fontDescription))
3190 else if (isInitial) {
3191 FontDescription initialDesc = FontDescription();
3192 FontDescription fontDescription = style->fontDescription();
3193 // We need to adjust the size to account for the generic family change from monospace
3194 // to non-monospace.
3195 if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily)
3196 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), false));
3197 fontDescription.setGenericFamily(initialDesc.genericFamily());
3198 fontDescription.setFamily(initialDesc.firstFamily());
3199 if (style->setFontDescription(fontDescription))
3204 if (!value->isValueList()) return;
3205 FontDescription fontDescription = style->fontDescription();
3206 CSSValueList *list = static_cast<CSSValueList*>(value);
3207 int len = list->length();
3208 FontFamily& firstFamily = fontDescription.firstFamily();
3209 FontFamily *currFamily = 0;
3211 // Before mapping in a new font-family property, we should reset the generic family.
3212 bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3213 fontDescription.setGenericFamily(FontDescription::NoFamily);
3215 for(int i = 0; i < len; i++) {
3216 CSSValue *item = list->item(i);
3217 if(!item->isPrimitiveValue()) continue;
3218 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3220 if(val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
3221 face = static_cast<FontFamilyValue*>(val)->fontName();
3222 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3223 switch (val->getIdent()) {
3224 case CSS_VAL__WEBKIT_BODY:
3225 face = settings->stdFontName();
3228 face = settings->serifFontName();
3229 fontDescription.setGenericFamily(FontDescription::SerifFamily);
3231 case CSS_VAL_SANS_SERIF:
3232 face = settings->sansSerifFontName();
3233 fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3235 case CSS_VAL_CURSIVE:
3236 face = settings->cursiveFontName();
3237 fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3239 case CSS_VAL_FANTASY:
3240 face = settings->fantasyFontName();
3241 fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3243 case CSS_VAL_MONOSPACE:
3244 face = settings->fixedFontName();
3245 fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3250 if (!face.isEmpty()) {
3252 // Filling in the first family.
3253 firstFamily.setFamily(face);
3254 currFamily = &firstFamily;
3257 FontFamily *newFamily = new FontFamily;
3258 newFamily->setFamily(face);
3259 currFamily->appendFamily(newFamily);
3260 currFamily = newFamily;
3263 if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace)
3264 setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, style->htmlHacks(), !oldFamilyIsMonospace));
3266 if (style->setFontDescription(fontDescription))
3272 case CSS_PROP_QUOTES:
3273 // list of strings or i
3277 case CSS_PROP_TEXT_DECORATION: {
3279 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3280 int t = RenderStyle::initialTextDecoration();
3281 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3284 if(!value->isValueList()) return;
3285 CSSValueList *list = static_cast<CSSValueList*>(value);
3286 int len = list->length();
3287 for(int i = 0; i < len; i++)
3289 CSSValue *item = list->item(i);
3290 if(!item->isPrimitiveValue()) continue;
3291 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3292 switch(primitiveValue->getIdent())
3296 case CSS_VAL_UNDERLINE: