dde4fc0ae53ed2f9605a8b9b36584013a9b26a49
[WebKit-https.git] / WebCore / css / CSSStyleSelector.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8  *
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.
13  *
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.
18  *
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., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "CSSStyleSelector.h"
27
28 #include "CSSBorderImageValue.h"
29 #include "CSSCursorImageValue.h"
30 #include "CSSFontFace.h"
31 #include "CSSFontFaceRule.h"
32 #include "CSSFontFaceSource.h"
33 #include "CSSImageValue.h"
34 #include "CSSImportRule.h"
35 #include "CSSMediaRule.h"
36 #include "CSSPrimitiveValueMappings.h"
37 #include "CSSProperty.h"
38 #include "CSSPropertyNames.h"
39 #include "CSSRuleList.h"
40 #include "CSSSelector.h"
41 #include "CSSStyleRule.h"
42 #include "CSSStyleSheet.h"
43 #include "CSSTimingFunctionValue.h"
44 #include "CSSValueList.h"
45 #include "CachedImage.h"
46 #include "Counter.h"
47 #include "DashboardRegion.h"
48 #include "FontFamilyValue.h"
49 #include "FontValue.h"
50 #include "Frame.h"
51 #include "FrameView.h"
52 #include "HTMLDocument.h"
53 #include "HTMLElement.h"
54 #include "HTMLInputElement.h"
55 #include "HTMLNames.h"
56 #include "MediaList.h"
57 #include "MediaQueryEvaluator.h"
58 #include "Page.h"
59 #include "PageGroup.h"
60 #include "Pair.h"
61 #include "Rect.h"
62 #include "RenderTheme.h"
63 #include "SelectionController.h"
64 #include "Settings.h"
65 #include "ShadowValue.h"
66 #include "StyleSheetList.h"
67 #include "Text.h"
68 #include "UserAgentStyleSheets.h"
69 #include "XMLNames.h"
70 #include "loader.h"
71 #include <wtf/Vector.h>
72
73 #if ENABLE(SVG)
74 #include "XLinkNames.h"
75 #include "SVGNames.h"
76 #endif
77
78 using namespace std;
79
80 namespace WebCore {
81
82 using namespace HTMLNames;
83
84 // #define STYLE_SHARING_STATS 1
85
86 #define HANDLE_INHERIT(prop, Prop) \
87 if (isInherit) { \
88     m_style->set##Prop(m_parentStyle->prop()); \
89     return; \
90 }
91
92 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
93 HANDLE_INHERIT(prop, Prop) \
94 if (isInitial) { \
95     m_style->set##Prop(RenderStyle::initial##Prop()); \
96     return; \
97 }
98
99 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
100 HANDLE_INHERIT(prop, Prop) \
101 if (isInitial) { \
102     m_style->set##Prop(RenderStyle::initial##Value());\
103     return;\
104 }
105
106 #define HANDLE_MULTILAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
107 if (isInherit) { \
108     LayerType* currChild = m_style->access##LayerType##s(); \
109     LayerType* prevChild = 0; \
110     const LayerType* currParent = m_parentStyle->layerType##s(); \
111     while (currParent && currParent->is##Prop##Set()) { \
112         if (!currChild) { \
113             /* Need to make a new layer.*/ \
114             currChild = new LayerType(); \
115             prevChild->setNext(currChild); \
116         } \
117         currChild->set##Prop(currParent->prop()); \
118         prevChild = currChild; \
119         currChild = prevChild->next(); \
120         currParent = currParent->next(); \
121     } \
122     \
123     while (currChild) { \
124         /* Reset any remaining layers to not have the property set. */ \
125         currChild->clear##Prop(); \
126         currChild = currChild->next(); \
127     } \
128 } else if (isInitial) { \
129     LayerType* currChild = m_style->access##LayerType##s(); \
130     currChild->set##Prop(RenderStyle::initial##Prop()); \
131     for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
132         currChild->clear##Prop(); \
133 }
134
135 #define HANDLE_MULTILAYER_VALUE(layerType, LayerType, prop, Prop, value) { \
136 HANDLE_MULTILAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
137 if (isInherit || isInitial) \
138     return; \
139 LayerType* currChild = m_style->access##LayerType##s(); \
140 LayerType* prevChild = 0; \
141 if (value->isValueList()) { \
142     /* Walk each value and put it into a layer, creating new layers as needed. */ \
143     CSSValueList* valueList = static_cast<CSSValueList*>(value); \
144     for (unsigned int i = 0; i < valueList->length(); i++) { \
145         if (!currChild) { \
146             /* Need to make a new layer to hold this value */ \
147             currChild = new LayerType(); \
148             prevChild->setNext(currChild); \
149         } \
150         map##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \
151         prevChild = currChild; \
152         currChild = currChild->next(); \
153     } \
154 } else { \
155     map##Prop(currChild, value); \
156     currChild = currChild->next(); \
157 } \
158 while (currChild) { \
159     /* Reset all remaining layers to not have the property set. */ \
160     currChild->clear##Prop(); \
161     currChild = currChild->next(); \
162 } }
163
164 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
165 HANDLE_MULTILAYER_INHERIT_AND_INITIAL(backgroundLayer, BackgroundLayer, prop, Prop)
166
167 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \
168 HANDLE_MULTILAYER_VALUE(backgroundLayer, BackgroundLayer, prop, Prop, value)
169
170 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) \
171 HANDLE_MULTILAYER_VALUE(transition, Transition, prop, Prop, value)
172
173 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
174 if (id == propID) { \
175     m_style->set##Prop(m_parentStyle->prop()); \
176     return; \
177 }
178
179 #define HANDLE_INITIAL_COND(propID, Prop) \
180 if (id == propID) { \
181     m_style->set##Prop(RenderStyle::initial##Prop()); \
182     return; \
183 }
184
185 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
186 if (id == propID) { \
187     m_style->set##Prop(RenderStyle::initial##Value()); \
188     return; \
189 }
190
191 class CSSRuleSet {
192 public:
193     CSSRuleSet();
194     ~CSSRuleSet();
195     
196     typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
197     
198     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
199     
200     void addRule(CSSStyleRule* rule, CSSSelector* sel);
201     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
202                       CSSStyleRule* rule, CSSSelector* sel);
203     
204     CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
205     CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
206     CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
207     CSSRuleDataList* getUniversalRules() { return m_universalRules; }
208     
209 public:
210     AtomRuleMap m_idRules;
211     AtomRuleMap m_classRules;
212     AtomRuleMap m_tagRules;
213     CSSRuleDataList* m_universalRules;
214     unsigned m_ruleCount;
215 };
216
217 static CSSRuleSet* defaultStyle;
218 static CSSRuleSet* defaultQuirksStyle;
219 static CSSRuleSet* defaultPrintStyle;
220 static CSSRuleSet* defaultViewSourceStyle;
221
222 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
223
224 static PseudoState pseudoState;
225
226 static void loadDefaultStyle();
227
228 static const MediaQueryEvaluator& screenEval()
229 {
230     static const MediaQueryEvaluator staticScreenEval("screen");
231     return staticScreenEval;
232 }
233
234 static const MediaQueryEvaluator& printEval()
235 {
236     static const MediaQueryEvaluator staticPrintEval("print");
237     return staticPrintEval;
238 }
239
240 CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, bool strictParsing, bool matchAuthorAndUserStyles)
241     : m_strictParsing(strictParsing)
242 {
243     init();
244     
245     m_document = doc;
246     m_fontSelector = new CSSFontSelector(doc);
247
248     m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
249
250     m_strictParsing = strictParsing;
251     if (!defaultStyle)
252         loadDefaultStyle();
253
254     m_userStyle = 0;
255
256     // construct document root element default style. this is needed
257     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
258     // This is here instead of constructor, because when constructor is run,
259     // document doesn't have documentElement
260     // NOTE: this assumes that element that gets passed to styleForElement -call
261     // is always from the document that owns the style selector
262     FrameView* view = m_document->view();
263     if (view)
264         m_medium = new MediaQueryEvaluator(view->mediaType());
265     else
266         m_medium = new MediaQueryEvaluator("all");
267
268     Element* root = doc->documentElement();
269
270     if (root)
271         m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap
272
273     if (m_rootDefaultStyle && view) {
274         delete m_medium;
275         m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle);
276     }
277
278     // FIXME: This sucks! The user sheet is reparsed every time!
279     if (!userStyleSheet.isEmpty()) {
280         m_userSheet = new CSSStyleSheet(doc);
281         m_userSheet->parseString(userStyleSheet, strictParsing);
282
283         m_userStyle = new CSSRuleSet();
284         m_userStyle->addRulesFromSheet(m_userSheet.get(), *m_medium, this);
285     }
286
287     // add stylesheets from document
288     m_authorStyle = new CSSRuleSet();
289     
290     // Add rules from elments like SVG's <font-face>
291     if (mappedElementSheet)
292         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
293
294     DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets);
295     for (; it.current(); ++it)
296         if (it.current()->isCSSStyleSheet() && !it.current()->disabled())
297             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), *m_medium, this);
298 }
299
300 void CSSStyleSelector::init()
301 {
302     m_element = 0;
303     m_matchedDecls.clear();
304     m_ruleList = 0;
305     m_collectRulesOnly = false;
306     m_rootDefaultStyle = 0;
307     m_medium = 0;
308 }
309
310 CSSStyleSelector::~CSSStyleSelector()
311 {
312     delete m_medium;
313     ::delete m_rootDefaultStyle;
314     delete m_authorStyle;
315     delete m_userStyle;
316     deleteAllValues(m_viewportDependentMediaQueryResults);
317 }
318
319 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
320 {
321     CSSStyleSheet* const parent = 0;
322     CSSStyleSheet* sheet = new CSSStyleSheet(parent);
323     sheet->ref(); // leak the sheet on purpose
324     sheet->parseString(String(characters, size));
325     return sheet;
326 }
327
328 template<typename T> CSSStyleSheet* parseUASheet(const T& array)
329 {
330     return parseUASheet(array, sizeof(array));
331 }
332
333 static void loadDefaultStyle()
334 {
335     ASSERT(!defaultStyle);
336
337     defaultStyle = new CSSRuleSet;
338     defaultPrintStyle = new CSSRuleSet;
339     defaultQuirksStyle = new CSSRuleSet;
340     defaultViewSourceStyle = new CSSRuleSet;
341
342     // Strict-mode rules.
343     CSSStyleSheet* defaultSheet = parseUASheet(html4UserAgentStyleSheet);
344     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
345     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
346
347     // Quirks-mode rules.
348     defaultQuirksStyle->addRulesFromSheet(parseUASheet(quirksUserAgentStyleSheet), screenEval());
349     
350     // View source rules.
351     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet), screenEval());
352 }
353
354 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
355 {
356     m_matchedRules.clear();
357
358     if (!rules || !m_element)
359         return;
360     
361     // We need to collect the rules for id, class, tag, and everything else into a buffer and
362     // then sort the buffer.
363     if (m_element->hasID())
364         matchRulesForList(rules->getIDRules(m_element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);
365     if (m_element->hasClass()) {
366         ASSERT(m_styledElement);
367         const ClassNames& classNames = m_styledElement->classNames();
368         size_t size = classNames.size();
369         for (size_t i = 0; i < size; ++i)
370             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex);
371     }
372     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex);
373     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
374     
375     // If we didn't match any rules, we're done.
376     if (m_matchedRules.isEmpty())
377         return;
378     
379     // Sort the set of matched rules.
380     sortMatchedRules(0, m_matchedRules.size());
381     
382     // Now transfer the set of matched rules over to our list of decls.
383     if (!m_collectRulesOnly) {
384         for (unsigned i = 0; i < m_matchedRules.size(); i++)
385             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
386     } else {
387         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
388             if (!m_ruleList)
389                 m_ruleList = new CSSRuleList();
390             m_ruleList->append(m_matchedRules[i]->rule());
391         }
392     }
393 }
394
395 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
396 {
397     if (!rules)
398         return;
399
400     for (CSSRuleData* d = rules->first(); d; d = d->next()) {
401         CSSStyleRule* rule = d->rule();
402         const AtomicString& localName = m_element->localName();
403         const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
404         if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector())) {
405             // If the rule has no properties to apply, then ignore it.
406             CSSMutableStyleDeclaration* decl = rule->declaration();
407             if (!decl || !decl->length())
408                 continue;
409             
410             // If we're matching normal rules, set a pseudo bit if 
411             // we really just matched a pseudo-element.
412             if (dynamicPseudo != RenderStyle::NOPSEUDO && m_pseudoStyle == RenderStyle::NOPSEUDO) {
413                 if (m_collectRulesOnly)
414                     return;
415                 if (dynamicPseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID)
416                     m_style->setHasPseudoStyle(dynamicPseudo);
417             } else {
418                 // Update our first/last rule indices in the matched rules array.
419                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
420                 if (firstRuleIndex == -1)
421                     firstRuleIndex = lastRuleIndex;
422
423                 // Add this rule to our list of matched rules.
424                 addMatchedRule(d);
425             }
426         }
427     }
428 }
429
430 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
431 {
432     int spec1 = r1.selector()->specificity();
433     int spec2 = r2.selector()->specificity();
434     return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; 
435 }
436 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
437 {
438     return !(r1 > r2);
439 }
440
441 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
442 {
443     if (start >= end || (end - start == 1))
444         return; // Sanity check.
445
446     if (end - start <= 6) {
447         // Apply a bubble sort for smaller lists.
448         for (unsigned i = end - 1; i > start; i--) {
449             bool sorted = true;
450             for (unsigned j = start; j < i; j++) {
451                 CSSRuleData* elt = m_matchedRules[j];
452                 CSSRuleData* elt2 = m_matchedRules[j + 1];
453                 if (*elt > *elt2) {
454                     sorted = false;
455                     m_matchedRules[j] = elt2;
456                     m_matchedRules[j + 1] = elt;
457                 }
458             }
459             if (sorted)
460                 return;
461         }
462         return;
463     }
464
465     // Peform a merge sort for larger lists.
466     unsigned mid = (start + end) / 2;
467     sortMatchedRules(start, mid);
468     sortMatchedRules(mid, end);
469     
470     CSSRuleData* elt = m_matchedRules[mid - 1];
471     CSSRuleData* elt2 = m_matchedRules[mid];
472     
473     // Handle the fast common case (of equal specificity).  The list may already
474     // be completely sorted.
475     if (*elt <= *elt2)
476         return;
477     
478     // We have to merge sort.  Ensure our merge buffer is big enough to hold
479     // all the items.
480     Vector<CSSRuleData*> rulesMergeBuffer;
481     rulesMergeBuffer.reserveCapacity(end - start); 
482
483     unsigned i1 = start;
484     unsigned i2 = mid;
485     
486     elt = m_matchedRules[i1];
487     elt2 = m_matchedRules[i2];
488     
489     while (i1 < mid || i2 < end) {
490         if (i1 < mid && (i2 == end || *elt <= *elt2)) {
491             rulesMergeBuffer.append(elt);
492             if (++i1 < mid)
493                 elt = m_matchedRules[i1];
494         } else {
495             rulesMergeBuffer.append(elt2);
496             if (++i2 < end)
497                 elt2 = m_matchedRules[i2];
498         }
499     }
500     
501     for (unsigned i = start; i < end; i++)
502         m_matchedRules[i] = rulesMergeBuffer[i - start];
503 }
504
505 void CSSStyleSelector::initElementAndPseudoState(Element* e)
506 {
507     m_element = e;
508     if (m_element && m_element->isStyledElement())
509         m_styledElement = static_cast<StyledElement*>(m_element);
510     else
511         m_styledElement = 0;
512     pseudoState = PseudoUnknown;
513 }
514
515 void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent)
516 {
517     // set some variables we will need
518     m_pseudoStyle = RenderStyle::NOPSEUDO;
519
520     m_parentNode = e->parentNode();
521
522 #if ENABLE(SVG)
523     if (!m_parentNode && e->isSVGElement() && e->isShadowNode())
524         m_parentNode = e->shadowParentNode();
525 #endif
526
527     if (defaultParent)
528         m_parentStyle = defaultParent;
529     else
530         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
531     m_isXMLDoc = !m_element->document()->isHTMLDocument();
532
533     m_style = 0;
534     
535     m_matchedDecls.clear();
536
537     m_ruleList = 0;
538
539     m_fontDirty = false;
540 }
541
542 static inline const AtomicString* linkAttribute(Node* node)
543 {
544     if (!node->isLink())
545         return 0;
546
547     ASSERT(node->isElementNode());
548     Element* element = static_cast<Element*>(node);
549     if (element->isHTMLElement())
550         return &element->getAttribute(hrefAttr);
551 #if ENABLE(SVG)
552     if (element->isSVGElement())
553         return &element->getAttribute(XLinkNames::hrefAttr);
554 #endif
555     return 0;
556 }
557
558 PseudoState CSSStyleSelector::checkPseudoState(Element* element, bool checkVisited)
559 {
560     const AtomicString* attr = linkAttribute(element);
561     if (!attr || attr->isNull())
562         return PseudoNone;
563
564     if (!checkVisited)
565         return PseudoAnyLink;
566
567     unsigned hash = m_document->visitedLinkHash(*attr);
568     if (!hash)
569         return PseudoLink;
570
571     Frame* frame = m_document->frame();
572     if (!frame)
573         return PseudoLink;
574
575     Page* page = frame->page();
576     if (!page)
577         return PseudoLink;
578
579     m_linksCheckedForVisitedState.add(hash);
580     return page->group().isLinkVisited(hash) ? PseudoVisited : PseudoLink;
581 }
582
583 // a helper function for parsing nth-arguments
584 static bool parseNth(const String& nth, int &a, int &b)
585 {
586     if (nth.isEmpty())
587         return false;
588     a = 0;
589     b = 0;
590     if (nth == "odd") {
591         a = 2;
592         b = 1;
593     } else if (nth == "even") {
594         a = 2;
595         b = 0;
596     } else {
597         int n = nth.find('n');
598         if (n != -1) {
599             if (nth[0] == '-') {
600                 if (n == 1)
601                     a = -1; // -n == -1n
602                 else
603                     a = nth.substring(0, n).toInt();
604             } else if (!n)
605                 a = 1; // n == 1n
606             else
607                 a = nth.substring(0, n).toInt();
608
609             int p = nth.find('+', n);
610             if (p != -1)
611                 b = nth.substring(p + 1, nth.length() - p - 1).toInt();
612             else {
613                 p = nth.find('-', n);
614                 b = -nth.substring(p + 1, nth.length() - p - 1).toInt();
615             }
616         } else
617             b = nth.toInt();
618     }
619     return true;
620 }
621
622 // a helper function for checking nth-arguments
623 static bool matchNth(int count, int a, int b)
624 {
625     if (!a)
626         return count == b;
627     else if (a > 0) {
628         if (count < b)
629             return false;
630         return (count - b) % a == 0;
631     } else {
632         if (count > b)
633             return false;
634         return (b - count) % (-a) == 0;
635     }
636 }
637
638
639 #ifdef STYLE_SHARING_STATS
640 static int fraction = 0;
641 static int total = 0;
642 #endif
643
644 static const unsigned cStyleSearchThreshold = 10;
645
646 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth)
647 {
648     if (parent && parent->isStyledElement()) {
649         StyledElement* p = static_cast<StyledElement*>(parent);
650         if (!p->inlineStyleDecl() && !p->hasID()) {
651             Node* r = p->previousSibling();
652             unsigned subcount = 0;
653             RenderStyle* st = p->renderStyle();
654             while (r) {
655                 if (r->renderStyle() == st)
656                     return r->lastChild();
657                 if (subcount++ == cStyleSearchThreshold)
658                     return 0;
659                 r = r->previousSibling();
660             }
661             if (!r && depth < cStyleSearchThreshold)
662                 r = locateCousinList(static_cast<Element*>(parent->parentNode()), depth + 1);
663             while (r) {
664                 if (r->renderStyle() == st)
665                     return r->lastChild();
666                 if (subcount++ == cStyleSearchThreshold)
667                     return 0;
668                 r = r->previousSibling();
669             }
670         }
671     }
672     return 0;
673 }
674
675 bool CSSStyleSelector::canShareStyleWithElement(Node* n)
676 {
677     if (n->isStyledElement()) {
678         StyledElement* s = static_cast<StyledElement*>(n);
679         RenderStyle* style = s->renderStyle();
680         if (style && !style->unique() &&
681             (s->tagQName() == m_element->tagQName()) && !s->hasID() &&
682             (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
683             (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
684             (s->isLink() == m_element->isLink()) && 
685             !style->affectedByAttributeSelectors() &&
686             (s->hovered() == m_element->hovered()) &&
687             (s->active() == m_element->active()) &&
688             (s->focused() == m_element->focused()) &&
689             (s != s->document()->getCSSTarget() && m_element != m_element->document()->getCSSTarget()) &&
690             (s->getAttribute(typeAttr) == m_element->getAttribute(typeAttr)) &&
691             (s->getAttribute(XMLNames::langAttr) == m_element->getAttribute(XMLNames::langAttr)) &&
692             (s->getAttribute(langAttr) == m_element->getAttribute(langAttr)) &&
693             (s->getAttribute(readonlyAttr) == m_element->getAttribute(readonlyAttr)) &&
694             (s->getAttribute(cellpaddingAttr) == m_element->getAttribute(cellpaddingAttr))) {
695             bool isControl = s->isControl();
696             if (isControl != m_element->isControl())
697                 return false;
698             if (isControl && (s->isEnabled() != m_element->isEnabled()) ||
699                              (s->isIndeterminate() != m_element->isIndeterminate()) ||
700                              (s->isChecked() != m_element->isChecked()))
701                 return false;
702             
703             if (style->transitions())
704                 return false;
705
706             bool classesMatch = true;
707             if (s->hasClass()) {
708                 const AtomicString& class1 = m_element->getAttribute(classAttr);
709                 const AtomicString& class2 = s->getAttribute(classAttr);
710                 classesMatch = (class1 == class2);
711             }
712             
713             if (classesMatch) {
714                 bool mappedAttrsMatch = true;
715                 if (s->hasMappedAttributes())
716                     mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes());
717                 if (mappedAttrsMatch) {
718                     bool linksMatch = true;
719
720                     if (s->isLink()) {
721                         // We need to check to see if the visited state matches.
722                         if (pseudoState == PseudoUnknown) {
723                             const Color& linkColor = m_element->document()->linkColor();
724                             const Color& visitedColor = m_element->document()->visitedLinkColor();
725                             pseudoState = checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor);
726                         }
727                         linksMatch = (pseudoState == style->pseudoState());
728                     }
729                     
730                     if (linksMatch)
731                         return true;
732                 }
733             }
734         }
735     }
736     return false;
737 }
738
739 RenderStyle* CSSStyleSelector::locateSharedStyle()
740 {
741     if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
742         // Check previous siblings.
743         unsigned count = 0;
744         Node* n;
745         for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
746         while (n) {
747             if (canShareStyleWithElement(n))
748                 return n->renderStyle();
749             if (count++ == cStyleSearchThreshold)
750                 return 0;
751             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
752         }
753         if (!n) 
754             n = locateCousinList(static_cast<Element*>(m_element->parentNode()));
755         while (n) {
756             if (canShareStyleWithElement(n))
757                 return n->renderStyle();
758             if (count++ == cStyleSearchThreshold)
759                 return 0;
760             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
761         }        
762     }
763     return 0;
764 }
765
766 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
767 {
768     // First we match rules from the user agent sheet.
769     CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
770         ? defaultPrintStyle : defaultStyle;
771     matchRules(userAgentStyleSheet, firstUARule, lastUARule);
772
773     // In quirks mode, we match rules from the quirks user agent sheet.
774     if (!m_strictParsing)
775         matchRules(defaultQuirksStyle, firstUARule, lastUARule);
776         
777     // If we're in view source mode, then we match rules from the view source style sheet.
778     if (m_document->frame() && m_document->frame()->inViewSourceMode())
779         matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
780 }
781
782 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
783 // relative units are interpreted according to document root element style, styled only with UA stylesheet
784
785 RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
786 {
787     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
788     // will vanish if a style recalc happens during loading.
789     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
790         if (!s_styleNotYetAvailable) {
791             s_styleNotYetAvailable = ::new RenderStyle;
792             s_styleNotYetAvailable->ref();
793             s_styleNotYetAvailable->setDisplay(NONE);
794             s_styleNotYetAvailable->font().update(m_fontSelector);
795         }
796         s_styleNotYetAvailable->ref();
797         e->document()->setHasNodesWithPlaceholderStyle();
798         return s_styleNotYetAvailable;
799     }
800     
801     initElementAndPseudoState(e);
802     if (allowSharing) {
803         m_style = locateSharedStyle();
804 #ifdef STYLE_SHARING_STATS
805         fraction += m_style != 0;
806         total++;
807         printf("Sharing %d out of %d\n", fraction, total);
808 #endif
809         if (m_style) {
810             m_style->ref();
811             return m_style;
812         }
813     }
814     initForStyleResolve(e, defaultParent);
815
816     if (resolveForRootDefault) {
817         m_style = ::new RenderStyle();
818         // don't ref, because we want to delete this, but we cannot unref it
819     } else {
820         m_style = new (e->document()->renderArena()) RenderStyle();
821         m_style->ref();
822     }
823     if (m_parentStyle)
824         m_style->inheritFrom(m_parentStyle);
825     else
826         m_parentStyle = m_style;
827
828 #if ENABLE(SVG)
829     static bool loadedSVGUserAgentSheet;
830     if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
831         // SVG rules.
832         loadedSVGUserAgentSheet = true;
833         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet);
834         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
835         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
836     }
837 #endif
838
839     int firstUARule = -1, lastUARule = -1;
840     int firstUserRule = -1, lastUserRule = -1;
841     int firstAuthorRule = -1, lastAuthorRule = -1;
842     matchUARules(firstUARule, lastUARule);
843
844     if (!resolveForRootDefault) {
845         // 4. Now we check user sheet rules.
846         if (m_matchAuthorAndUserStyles)
847             matchRules(m_userStyle, firstUserRule, lastUserRule);
848
849         // 5. Now check author rules, beginning first with presentational attributes
850         // mapped from HTML.
851         if (m_styledElement) {
852             // Ask if the HTML element has mapped attributes.
853             if (m_styledElement->hasMappedAttributes()) {
854                 // Walk our attribute list and add in each decl.
855                 const NamedMappedAttrMap* map = m_styledElement->mappedAttributes();
856                 for (unsigned i = 0; i < map->length(); i++) {
857                     MappedAttribute* attr = map->attributeItem(i);
858                     if (attr->decl()) {
859                         lastAuthorRule = m_matchedDecls.size();
860                         if (firstAuthorRule == -1)
861                             firstAuthorRule = lastAuthorRule;
862                         addMatchedDeclaration(attr->decl());
863                     }
864                 }
865             }
866
867             // Now we check additional mapped declarations.
868             // Tables and table cells share an additional mapped rule that must be applied
869             // after all attributes, since their mapped style depends on the values of multiple attributes.
870             if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
871                 m_additionalAttributeStyleDecls.clear();
872                 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
873                 if (!m_additionalAttributeStyleDecls.isEmpty()) {
874                     unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
875                     if (firstAuthorRule == -1)
876                         firstAuthorRule = m_matchedDecls.size();
877                     lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
878                     for (unsigned i = 0; i < additionalDeclsSize; i++)
879                         addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
880                 }
881             }
882         }
883     
884         // 6. Check the rules in author sheets next.
885         if (m_matchAuthorAndUserStyles)
886             matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
887
888         // 7. Now check our inline style attribute.
889         if (m_matchAuthorAndUserStyles && m_styledElement) {
890             CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
891             if (inlineDecl) {
892                 lastAuthorRule = m_matchedDecls.size();
893                 if (firstAuthorRule == -1)
894                     firstAuthorRule = lastAuthorRule;
895                 addMatchedDeclaration(inlineDecl);
896             }
897         }
898     }
899
900     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
901     // high-priority properties first, i.e., those properties that other properties depend on.
902     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
903     // and (4) normal important.
904     m_lineHeightValue = 0;
905     applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
906     if (!resolveForRootDefault) {
907         applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
908         applyDeclarations(true, true, firstUserRule, lastUserRule);
909     }
910     applyDeclarations(true, true, firstUARule, lastUARule);
911     
912     // If our font got dirtied, go ahead and update it now.
913     if (m_fontDirty)
914         updateFont();
915
916     // Line-height is set when we are sure we decided on the font-size
917     if (m_lineHeightValue)
918         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
919
920     // Now do the normal priority UA properties.
921     applyDeclarations(false, false, firstUARule, lastUARule);
922     
923     // Cache our border and background so that we can examine them later.
924     cacheBorderAndBackground();
925     
926     // Now do the author and user normal priority properties and all the !important properties.
927     if (!resolveForRootDefault) {
928         applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
929         applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
930         applyDeclarations(false, true, firstUserRule, lastUserRule);
931     }
932     applyDeclarations(false, true, firstUARule, lastUARule);
933     
934     // If our font got dirtied by one of the non-essential font props, 
935     // go ahead and update it a second time.
936     if (m_fontDirty)
937         updateFont();
938     
939     // Clean up our style object's display and text decorations (among other fixups).
940     adjustRenderStyle(m_style, e);
941
942     // If we are a link, cache the determined pseudo-state.
943     if (e->isLink())
944         m_style->setPseudoState(pseudoState);
945
946     // If we have first-letter pseudo style, do not share this style
947     if (m_style->hasPseudoStyle(RenderStyle::FIRST_LETTER))
948         m_style->setUnique();
949
950     // Now return the style.
951     return m_style;
952 }
953
954 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle)
955 {
956     if (!e)
957         return 0;
958
959     initElementAndPseudoState(e);
960     initForStyleResolve(e, parentStyle);
961     m_pseudoStyle = pseudo;
962     
963     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
964     // those rules.
965     
966     // Check UA, user and author rules.
967     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
968     matchUARules(firstUARule, lastUARule);
969
970     if (m_matchAuthorAndUserStyles) {
971         matchRules(m_userStyle, firstUserRule, lastUserRule);
972         matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
973     }
974
975     if (m_matchedDecls.isEmpty())
976         return 0;
977     
978     m_style = new (e->document()->renderArena()) RenderStyle();
979     m_style->ref();
980     if (parentStyle)
981         m_style->inheritFrom(parentStyle);
982     else
983         parentStyle = m_style;
984     m_style->noninherited_flags._styleType = m_pseudoStyle;
985     
986     m_lineHeightValue = 0;
987     // High-priority properties.
988     applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
989     applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
990     applyDeclarations(true, true, firstUserRule, lastUserRule);
991     applyDeclarations(true, true, firstUARule, lastUARule);
992     
993     // If our font got dirtied, go ahead and update it now.
994     if (m_fontDirty)
995         updateFont();
996
997     // Line-height is set when we are sure we decided on the font-size
998     if (m_lineHeightValue)
999         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1000     
1001     // Now do the normal priority properties.
1002     applyDeclarations(false, false, firstUARule, lastUARule);
1003     
1004     // Cache our border and background so that we can examine them later.
1005     cacheBorderAndBackground();
1006     
1007     applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
1008     applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
1009     applyDeclarations(false, true, firstUserRule, lastUserRule);
1010     applyDeclarations(false, true, firstUARule, lastUARule);
1011     
1012     // If our font got dirtied by one of the non-essential font props, 
1013     // go ahead and update it a second time.
1014     if (m_fontDirty)
1015         updateFont();
1016     // Clean up our style object's display and text decorations (among other fixups).
1017     adjustRenderStyle(m_style, 0);
1018
1019     // Now return the style.
1020     return m_style;
1021 }
1022
1023 static void addIntrinsicMargins(RenderStyle* style)
1024 {
1025     // Intrinsic margin value.
1026     const int intrinsicMargin = 2;
1027     
1028     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1029     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1030     if (style->width().isIntrinsicOrAuto()) {
1031         if (style->marginLeft().quirk())
1032             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1033         if (style->marginRight().quirk())
1034             style->setMarginRight(Length(intrinsicMargin, Fixed));
1035     }
1036
1037     if (style->height().isAuto()) {
1038         if (style->marginTop().quirk())
1039             style->setMarginTop(Length(intrinsicMargin, Fixed));
1040         if (style->marginBottom().quirk())
1041             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1042     }
1043 }
1044
1045 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
1046 {
1047     // Cache our original display.
1048     style->setOriginalDisplay(style->display());
1049
1050     if (style->display() != NONE) {
1051         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1052         // property.
1053         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1054         // these tags to retain their display types.
1055         if (!m_strictParsing && e) {
1056             if (e->hasTagName(tdTag)) {
1057                 style->setDisplay(TABLE_CELL);
1058                 style->setFloating(FNONE);
1059             }
1060             else if (e->hasTagName(tableTag))
1061                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1062         }
1063
1064         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1065         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1066             style->setTextAlign(TAAUTO);
1067
1068         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1069         // fix a crash where a site tries to position these objects.  They also never honor display.
1070         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1071             style->setPosition(StaticPosition);
1072             style->setDisplay(BLOCK);
1073         }
1074
1075         // Table headers with a text-align of auto will change the text-align to center.
1076         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1077             style->setTextAlign(CENTER);
1078         
1079         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1080         // position or float an inline, compact, or run-in.  Cache the original display, since it
1081         // may be needed for positioned elements that have to compute their static normal flow
1082         // positions.  We also force inline-level roots to be block-level.
1083         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1084             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1085              (e && e->document()->documentElement() == e))) {
1086             if (style->display() == INLINE_TABLE)
1087                 style->setDisplay(TABLE);
1088             else if (style->display() == INLINE_BOX)
1089                 style->setDisplay(BOX);
1090             else if (style->display() == LIST_ITEM) {
1091                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1092                 // but only in quirks mode.
1093                 if (!m_strictParsing && style->floating() != FNONE)
1094                     style->setDisplay(BLOCK);
1095             }
1096             else
1097                 style->setDisplay(BLOCK);
1098         }
1099         
1100         // After performing the display mutation, check table rows.  We do not honor position:relative on
1101         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1102         // on some sites).
1103         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1104              style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1105              style->position() == RelativePosition)
1106             style->setPosition(StaticPosition);
1107     }
1108
1109     // Make sure our z-index value is only applied if the object is positioned,
1110     // relatively positioned, transparent, or has a transform.
1111     if (style->position() == StaticPosition && style->opacity() == 1.0f && !style->hasTransform())
1112         style->setHasAutoZIndex();
1113
1114     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1115     // cases where objects that should be blended as a single unit end up with a non-transparent
1116     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms.
1117     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || style->hasTransform()))
1118         style->setZIndex(0);
1119     
1120     // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
1121     // This will be important when we use block flows for all form controls.
1122     if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
1123               e->hasTagName(selectTag) || e->hasTagName(textareaTag))) {
1124         if (style->width().isAuto())
1125             style->setWidth(Length(Intrinsic));
1126     }
1127
1128     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1129     // tables, inline blocks, inline tables, or run-ins.
1130     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1131         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1132         style->setTextDecorationsInEffect(style->textDecoration());
1133     else
1134         style->addToTextDecorationsInEffect(style->textDecoration());
1135     
1136     // If either overflow value is not visible, change to auto.
1137     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1138         style->setOverflowY(OMARQUEE);
1139     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1140         style->setOverflowX(OMARQUEE);
1141     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1142         style->setOverflowX(OAUTO);
1143     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1144         style->setOverflowY(OAUTO);
1145
1146     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1147     // FIXME: Eventually table sections will support auto and scroll.
1148     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1149         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1150         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) 
1151             style->setOverflowX(OVISIBLE);
1152         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) 
1153             style->setOverflowY(OVISIBLE);
1154     }
1155
1156     // Cull out any useless layers and also repeat patterns into additional layers.
1157     style->adjustBackgroundLayers();
1158
1159     // Do the same for transitions.
1160     style->adjustTransitions();
1161
1162     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1163     // alter fonts and heights/widths.
1164     if (e && e->isControl() && style->fontSize() >= 11) {
1165         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1166         // so we have to treat all image buttons as though they were explicitly sized.
1167         if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE)
1168             addIntrinsicMargins(style);
1169     }
1170
1171     // Let the theme also have a crack at adjusting the style.
1172     if (style->hasAppearance())
1173         theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1174
1175 #if ENABLE(SVG)
1176     if (e && e->isSVGElement()) {
1177         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1178         if (style->overflowY() == OSCROLL)
1179             style->setOverflowY(OHIDDEN);
1180         else if (style->overflowY() == OAUTO)
1181             style->setOverflowY(OVISIBLE);
1182
1183         if (style->overflowX() == OSCROLL)
1184             style->setOverflowX(OHIDDEN);
1185         else if (style->overflowX() == OAUTO)
1186             style->setOverflowX(OVISIBLE);
1187
1188         // Only the root <svg> element in an SVG document fragment tree honors css position
1189         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1190             style->setPosition(RenderStyle::initialPosition());
1191     }
1192 #endif
1193 }
1194
1195 void CSSStyleSelector::updateFont()
1196 {
1197     checkForTextSizeAdjust();
1198     checkForGenericFamilyChange(m_style, m_parentStyle);
1199     checkForZoomChange(m_style, m_parentStyle);
1200     m_style->font().update(m_fontSelector);
1201     m_fontDirty = false;
1202 }
1203
1204 void CSSStyleSelector::cacheBorderAndBackground()
1205 {
1206     m_hasUAAppearance = m_style->hasAppearance();
1207     if (m_hasUAAppearance) {
1208         m_borderData = m_style->border();
1209         m_backgroundData = *m_style->backgroundLayers();
1210         m_backgroundColor = m_style->backgroundColor();
1211     }
1212 }
1213
1214 RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
1215 {
1216     if (!e || !e->document()->haveStylesheetsLoaded())
1217         return 0;
1218
1219     m_collectRulesOnly = true;
1220     
1221     initElementAndPseudoState(e);
1222     initForStyleResolve(e, 0);
1223     
1224     if (!authorOnly) {
1225         int firstUARule = -1, lastUARule = -1;
1226         // First we match rules from the user agent sheet.
1227         matchUARules(firstUARule, lastUARule);
1228
1229         // Now we check user sheet rules.
1230         if (m_matchAuthorAndUserStyles) {
1231             int firstUserRule = -1, lastUserRule = -1;
1232             matchRules(m_userStyle, firstUserRule, lastUserRule);
1233         }
1234     }
1235
1236     if (m_matchAuthorAndUserStyles) {
1237         // Check the rules in author sheets.
1238         int firstAuthorRule = -1, lastAuthorRule = -1;
1239         matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1240     }
1241
1242     m_collectRulesOnly = false;
1243     
1244     return m_ruleList;
1245 }
1246
1247 RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element*, const String& pseudoStyle, bool authorOnly)
1248 {
1249     // FIXME: Implement this.
1250     return 0;
1251 }
1252
1253 bool CSSStyleSelector::checkSelector(CSSSelector* sel)
1254 {
1255     dynamicPseudo = RenderStyle::NOPSEUDO;
1256
1257     // Check the selector
1258     SelectorMatch match = checkSelector(sel, m_element, true, false);
1259     if (match != SelectorMatches)
1260         return false;
1261
1262     if (m_pseudoStyle != RenderStyle::NOPSEUDO && m_pseudoStyle != dynamicPseudo)
1263         return false;
1264
1265     return true;
1266 }
1267
1268 // Recursive check of selectors and combinators
1269 // It can return 3 different values:
1270 // * SelectorMatches         - the selector matches the element e
1271 // * SelectorFailsLocally    - the selector fails for the element e
1272 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
1273 CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(CSSSelector* sel, Element* e, bool isAncestor, bool isSubSelector)
1274 {
1275 #if ENABLE(SVG)
1276     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
1277     // because its contents are not part of the formal document structure.
1278     if (e->isSVGElement() && e->isShadowNode())
1279         return SelectorFailsCompletely;
1280 #endif
1281
1282     // first selector has to match
1283     if (!checkOneSelector(sel, e, isAncestor, isSubSelector))
1284         return SelectorFailsLocally;
1285
1286     // The rest of the selectors has to match
1287     CSSSelector::Relation relation = sel->relation();
1288
1289     // Prepare next sel
1290     sel = sel->m_tagHistory;
1291     if (!sel)
1292         return SelectorMatches;
1293
1294     if (relation != CSSSelector::SubSelector)
1295         // Bail-out if this selector is irrelevant for the pseudoStyle
1296         if (m_pseudoStyle != RenderStyle::NOPSEUDO && m_pseudoStyle != dynamicPseudo)
1297             return SelectorFailsCompletely;
1298
1299     switch (relation) {
1300         case CSSSelector::Descendant:
1301             while (true) {
1302                 Node* n = e->parentNode();
1303                 if (!n || !n->isElementNode())
1304                     return SelectorFailsCompletely;
1305                 e = static_cast<Element*>(n);
1306                 SelectorMatch match = checkSelector(sel, e, true, false);
1307                 if (match != SelectorFailsLocally)
1308                     return match;
1309             }
1310             break;
1311         case CSSSelector::Child:
1312         {
1313             Node* n = e->parentNode();
1314             if (!n || !n->isElementNode())
1315                 return SelectorFailsCompletely;
1316             e = static_cast<Element*>(n);
1317             return checkSelector(sel, e, true, false);
1318         }
1319         case CSSSelector::DirectAdjacent:
1320         {
1321             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
1322                 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1323                 if (parentStyle)
1324                     parentStyle->setChildrenAffectedByDirectAdjacentRules();
1325             }
1326             Node* n = e->previousSibling();
1327             while (n && !n->isElementNode())
1328                 n = n->previousSibling();
1329             if (!n)
1330                 return SelectorFailsLocally;
1331             e = static_cast<Element*>(n);
1332             return checkSelector(sel, e, false, false); 
1333         }
1334         case CSSSelector::IndirectAdjacent:
1335             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
1336                 RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1337                 if (parentStyle)
1338                     parentStyle->setChildrenAffectedByForwardPositionalRules();
1339             }
1340             while (true) {
1341                 Node* n = e->previousSibling();
1342                 while (n && !n->isElementNode())
1343                     n = n->previousSibling();
1344                 if (!n)
1345                     return SelectorFailsLocally;
1346                 e = static_cast<Element*>(n);
1347                 SelectorMatch match = checkSelector(sel, e, false, false);
1348                 if (match != SelectorFailsLocally)
1349                     return match;
1350             };
1351             break;
1352         case CSSSelector::SubSelector:
1353             // a selector is invalid if something follows a pseudo-element
1354             if (e == m_element && dynamicPseudo != RenderStyle::NOPSEUDO)
1355                 return SelectorFailsCompletely;
1356             return checkSelector(sel, e, isAncestor, true);
1357     }
1358
1359     return SelectorFailsCompletely;
1360 }
1361
1362 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
1363 {
1364     set->add(qName.localName().impl());
1365 }
1366
1367 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
1368 {
1369     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
1370     // Mozilla treats all other values as case-sensitive, thus so do we.
1371     HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
1372
1373     addLocalNameToSet(attrSet, accept_charsetAttr);
1374     addLocalNameToSet(attrSet, acceptAttr);
1375     addLocalNameToSet(attrSet, alignAttr);
1376     addLocalNameToSet(attrSet, alinkAttr);
1377     addLocalNameToSet(attrSet, axisAttr);
1378     addLocalNameToSet(attrSet, bgcolorAttr);
1379     addLocalNameToSet(attrSet, charsetAttr);
1380     addLocalNameToSet(attrSet, checkedAttr);
1381     addLocalNameToSet(attrSet, clearAttr);
1382     addLocalNameToSet(attrSet, codetypeAttr);
1383     addLocalNameToSet(attrSet, colorAttr);
1384     addLocalNameToSet(attrSet, compactAttr);
1385     addLocalNameToSet(attrSet, declareAttr);
1386     addLocalNameToSet(attrSet, deferAttr);
1387     addLocalNameToSet(attrSet, dirAttr);
1388     addLocalNameToSet(attrSet, disabledAttr);
1389     addLocalNameToSet(attrSet, enctypeAttr);
1390     addLocalNameToSet(attrSet, faceAttr);
1391     addLocalNameToSet(attrSet, frameAttr);
1392     addLocalNameToSet(attrSet, hreflangAttr);
1393     addLocalNameToSet(attrSet, http_equivAttr);
1394     addLocalNameToSet(attrSet, langAttr);
1395     addLocalNameToSet(attrSet, languageAttr);
1396     addLocalNameToSet(attrSet, linkAttr);
1397     addLocalNameToSet(attrSet, mediaAttr);
1398     addLocalNameToSet(attrSet, methodAttr);
1399     addLocalNameToSet(attrSet, multipleAttr);
1400     addLocalNameToSet(attrSet, nohrefAttr);
1401     addLocalNameToSet(attrSet, noresizeAttr);
1402     addLocalNameToSet(attrSet, noshadeAttr);
1403     addLocalNameToSet(attrSet, nowrapAttr);
1404     addLocalNameToSet(attrSet, readonlyAttr);
1405     addLocalNameToSet(attrSet, relAttr);
1406     addLocalNameToSet(attrSet, revAttr);
1407     addLocalNameToSet(attrSet, rulesAttr);
1408     addLocalNameToSet(attrSet, scopeAttr);
1409     addLocalNameToSet(attrSet, scrollingAttr);
1410     addLocalNameToSet(attrSet, selectedAttr);
1411     addLocalNameToSet(attrSet, shapeAttr);
1412     addLocalNameToSet(attrSet, targetAttr);
1413     addLocalNameToSet(attrSet, textAttr);
1414     addLocalNameToSet(attrSet, typeAttr);
1415     addLocalNameToSet(attrSet, valignAttr);
1416     addLocalNameToSet(attrSet, valuetypeAttr);
1417     addLocalNameToSet(attrSet, vlinkAttr);
1418
1419     return attrSet;
1420 }
1421
1422 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
1423 {
1424     static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
1425     bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
1426     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
1427 }
1428
1429 bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isAncestor, bool isSubSelector)
1430 {
1431     if (!e)
1432         return false;
1433
1434     if (sel->hasTag()) {
1435         const AtomicString& selLocalName = sel->m_tag.localName();
1436         if (selLocalName != starAtom && selLocalName != e->localName())
1437             return false;
1438         const AtomicString& selNS = sel->m_tag.namespaceURI();
1439         if (selNS != starAtom && selNS != e->namespaceURI())
1440             return false;
1441     }
1442
1443     if (sel->hasAttribute()) {
1444         if (sel->m_match == CSSSelector::Class)
1445             return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value);
1446
1447         if (sel->m_match == CSSSelector::Id)
1448             return e->hasID() && e->getIDAttribute() == sel->m_value;
1449
1450         if (m_style && (e != m_element || !m_styledElement || (!m_styledElement->isMappedAttribute(sel->m_attr) && sel->m_attr != typeAttr && sel->m_attr != readonlyAttr))) {
1451             m_style->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
1452             m_selectorAttrs.add(sel->m_attr.localName().impl());
1453         }
1454
1455         const AtomicString& value = e->getAttribute(sel->m_attr);
1456         if (value.isNull())
1457             return false; // attribute is not set
1458
1459         bool caseSensitive = m_isXMLDoc || !htmlAttributeHasCaseInsensitiveValue(sel->m_attr);
1460
1461         switch (sel->m_match) {
1462         case CSSSelector::Exact:
1463             if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
1464                 return false;
1465             break;
1466         case CSSSelector::List:
1467         {
1468             // Ignore empty selectors or selectors containing spaces
1469             if (sel->m_value.contains(' ') || sel->m_value.isEmpty())
1470                 return false;
1471
1472             int startSearchAt = 0;
1473             while (true) {
1474                 int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
1475                 if (foundPos == -1)
1476                     return false;
1477                 if (foundPos == 0 || value[foundPos-1] == ' ') {
1478                     unsigned endStr = foundPos + sel->m_value.length();
1479                     if (endStr == value.length() || value[endStr] == ' ')
1480                         break; // We found a match.
1481                 }
1482                 
1483                 // No match.  Keep looking.
1484                 startSearchAt = foundPos + 1;
1485             }
1486             break;
1487         }
1488         case CSSSelector::Contain:
1489             if (!value.contains(sel->m_value, caseSensitive))
1490                 return false;
1491             break;
1492         case CSSSelector::Begin:
1493             if (!value.startsWith(sel->m_value, caseSensitive))
1494                 return false;
1495             break;
1496         case CSSSelector::End:
1497             if (!value.endsWith(sel->m_value, caseSensitive))
1498                 return false;
1499             break;
1500         case CSSSelector::Hyphen:
1501             if (value.length() < sel->m_value.length())
1502                 return false;
1503             if (!value.startsWith(sel->m_value, caseSensitive))
1504                 return false;
1505             // It they start the same, check for exact match or following '-':
1506             if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
1507                 return false;
1508             break;
1509         case CSSSelector::PseudoClass:
1510         case CSSSelector::PseudoElement:
1511         default:
1512             break;
1513         }
1514     }
1515     if (sel->m_match == CSSSelector::PseudoClass) {
1516         switch (sel->pseudoType()) {
1517             // Pseudo classes:
1518             case CSSSelector::PseudoEmpty: {
1519                 bool result = true;
1520                 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
1521                     if (n->isElementNode()) {
1522                         result = false;
1523                         break;
1524                     } else if (n->isTextNode()) {
1525                         Text* textNode = static_cast<Text*>(n);
1526                         if (!textNode->data().isEmpty()) {
1527                             result = false;
1528                             break;
1529                         }
1530                     }
1531                 }
1532                 if (!m_collectRulesOnly) {
1533                     if (m_element == e && m_style)
1534                         m_style->setEmptyState(result);
1535                     else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
1536                         e->renderStyle()->setEmptyState(result);
1537                 }
1538                 return result;
1539             }
1540             case CSSSelector::PseudoFirstChild: {
1541                 // first-child matches the first child that is an element
1542                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1543                     bool result = false;
1544                     Node* n = e->previousSibling();
1545                     while (n && !n->isElementNode())
1546                         n = n->previousSibling();
1547                     if (!n)
1548                         result = true;
1549                     if (!m_collectRulesOnly) {
1550                         RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle();
1551                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1552                         if (parentStyle)
1553                             parentStyle->setChildrenAffectedByFirstChildRules();
1554                         if (result && childStyle)
1555                             childStyle->setFirstChildState();
1556                     }
1557                     return result;
1558                 }
1559                 break;
1560             }
1561             case CSSSelector::PseudoFirstOfType: {
1562                 // first-of-type matches the first element of its type
1563                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1564                     bool result = false;
1565                     const QualifiedName& type = e->tagQName();
1566                     Node* n = e->previousSibling();
1567                     while (n) {
1568                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1569                             break;
1570                         n = n->previousSibling();
1571                     }
1572                     if (!n)
1573                         result = true;
1574                     if (!m_collectRulesOnly) {
1575                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1576                         if (parentStyle)
1577                             parentStyle->setChildrenAffectedByForwardPositionalRules();
1578                     }
1579                     return result;
1580                 }
1581                 break;
1582             }
1583             case CSSSelector::PseudoLastChild: {
1584                 // last-child matches the last child that is an element
1585                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1586                     Element* parentNode = static_cast<Element*>(e->parentNode());
1587                     bool result = false;
1588                     if (parentNode->isFinishedParsingChildren()) {
1589                         Node* n = e->nextSibling();
1590                         while (n && !n->isElementNode())
1591                             n = n->nextSibling();
1592                         if (!n)
1593                             result = true;
1594                     }
1595                     if (!m_collectRulesOnly) {
1596                         RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle();
1597                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1598                         if (parentStyle)
1599                             parentStyle->setChildrenAffectedByLastChildRules();
1600                         if (result && childStyle)
1601                             childStyle->setLastChildState();
1602                     }
1603                     return result;
1604                 }
1605                 break;
1606             }
1607             case CSSSelector::PseudoLastOfType: {
1608                 // last-of-type matches the last element of its type
1609                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1610                     Element* parentNode = static_cast<Element*>(e->parentNode());
1611                     if (!m_collectRulesOnly) {
1612                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1613                         if (parentStyle)
1614                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
1615                     }
1616                     if (!parentNode->isFinishedParsingChildren())
1617                         return false;
1618                     bool result = false;
1619                     const QualifiedName& type = e->tagQName();
1620                     Node* n = e->nextSibling();
1621                     while (n) {
1622                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1623                             break;
1624                         n = n->nextSibling();
1625                     }
1626                     if (!n)
1627                         result = true;
1628                     return result;
1629                 }
1630                 break;
1631             }
1632             case CSSSelector::PseudoOnlyChild: {
1633                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1634                     Element* parentNode = static_cast<Element*>(e->parentNode());
1635                     bool firstChild = false;
1636                     bool lastChild = false;
1637                     
1638                     Node* n = e->previousSibling();
1639                     while (n && !n->isElementNode())
1640                         n = n->previousSibling();
1641                     if (!n)
1642                         firstChild = true;
1643                     if (firstChild && parentNode->isFinishedParsingChildren()) {
1644                         n = e->nextSibling();
1645                         while (n && !n->isElementNode())
1646                             n = n->nextSibling();
1647                         if (!n)
1648                             lastChild = true;
1649                     }
1650                     if (!m_collectRulesOnly) {
1651                         RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle();
1652                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1653                         if (parentStyle) {
1654                             parentStyle->setChildrenAffectedByFirstChildRules();
1655                             parentStyle->setChildrenAffectedByLastChildRules();
1656                         }
1657                         if (firstChild && childStyle)
1658                             childStyle->setFirstChildState();
1659                         if (lastChild && childStyle)
1660                             childStyle->setLastChildState();
1661                     }
1662                     return firstChild && lastChild;
1663                 }
1664                 break;
1665             }
1666             case CSSSelector::PseudoOnlyOfType: {
1667                 // FIXME: This selector is very slow.
1668                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1669                     Element* parentNode = static_cast<Element*>(e->parentNode());
1670                     if (!m_collectRulesOnly) {
1671                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1672                         if (parentStyle) {
1673                             parentStyle->setChildrenAffectedByForwardPositionalRules();
1674                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
1675                         }
1676                     }
1677                     if (!parentNode->isFinishedParsingChildren())
1678                         return false;
1679                     bool firstChild = false;
1680                     bool lastChild = false;
1681                     const QualifiedName& type = e->tagQName();
1682                     Node* n = e->previousSibling();
1683                     while (n) {
1684                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1685                             break;
1686                         n = n->previousSibling();
1687                     }
1688                     if (!n)
1689                         firstChild = true;
1690                     if (firstChild) {
1691                         n = e->nextSibling();
1692                         while (n) {
1693                             if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1694                                 break;
1695                             n = n->nextSibling();
1696                         }
1697                         if (!n)
1698                             lastChild = true;
1699                     }
1700                     return firstChild && lastChild;
1701                 }
1702                 break;
1703             }
1704             case CSSSelector::PseudoNthChild: {
1705                 int a, b;
1706                 // calculate a and b every time we run through checkOneSelector
1707                 // this should probably be saved after we calculate it once, but currently
1708                 // would require increasing the size of CSSSelector
1709                 if (!parseNth(sel->m_argument, a, b))
1710                     break;
1711                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1712                     int count = 1;
1713                     Node* n = e->previousSibling();
1714                     while (n) {
1715                         if (n->isElementNode()) {
1716                             RenderStyle* s = n->renderStyle();
1717                             unsigned index = s ? s->childIndex() : 0;
1718                             if (index) {
1719                                 count += index;
1720                                 break;
1721                             }
1722                             count++;
1723                         }
1724                         n = n->previousSibling();
1725                     }
1726                     
1727                     if (!m_collectRulesOnly) {
1728                         RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle();
1729                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1730                         if (childStyle)
1731                             childStyle->setChildIndex(count);
1732                         if (parentStyle)
1733                             parentStyle->setChildrenAffectedByForwardPositionalRules();
1734                     }
1735                     
1736                     if (matchNth(count, a, b))
1737                         return true;
1738                 }
1739                 break;
1740             }
1741             case CSSSelector::PseudoNthOfType: {
1742                 // FIXME: This selector is very slow.
1743                 int a, b;
1744                 // calculate a and b every time we run through checkOneSelector (see above)
1745                 if (!parseNth(sel->m_argument, a, b))
1746                     break;
1747                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1748                     int count = 1;
1749                     const QualifiedName& type = e->tagQName();
1750                     Node* n = e->previousSibling();
1751                     while (n) {
1752                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1753                             count++;
1754                         n = n->previousSibling();
1755                     }
1756                     
1757                     if (!m_collectRulesOnly) {
1758                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle();
1759                         if (parentStyle)
1760                             parentStyle->setChildrenAffectedByForwardPositionalRules();
1761                     }
1762
1763                     if (matchNth(count, a, b))
1764                         return true;
1765                 }
1766                 break;
1767             }
1768             case CSSSelector::PseudoNthLastChild: {
1769                 int a, b;
1770                 // calculate a and b every time we run through checkOneSelector
1771                 // this should probably be saved after we calculate it once, but currently
1772                 // would require increasing the size of CSSSelector
1773                 if (!parseNth(sel->m_argument, a, b))
1774                     break;
1775                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1776                     Element* parentNode = static_cast<Element*>(e->parentNode());
1777                     if (!m_collectRulesOnly) {
1778                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1779                         if (parentStyle)
1780                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
1781                     }
1782                     if (!parentNode->isFinishedParsingChildren())
1783                         return false;
1784                     int count = 1;
1785                     Node* n = e->nextSibling();
1786                     while (n) {
1787                         if (n->isElementNode())
1788                             count++;
1789                         n = n->nextSibling();
1790                     }
1791                     if (matchNth(count, a, b))
1792                         return true;
1793                 }
1794                 break;
1795             }
1796             case CSSSelector::PseudoNthLastOfType: {
1797                 // FIXME: This selector is very slow.
1798                 int a, b;
1799                 // calculate a and b every time we run through checkOneSelector (see above)
1800                 if (!parseNth(sel->m_argument, a, b))
1801                     break;
1802                 if (e->parentNode() && e->parentNode()->isElementNode()) {
1803                     Element* parentNode = static_cast<Element*>(e->parentNode());
1804                     if (!m_collectRulesOnly) {
1805                         RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle();
1806                         if (parentStyle)
1807                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
1808                     }
1809                     if (!parentNode->isFinishedParsingChildren())
1810                         return false;
1811                     int count = 1;
1812                     const QualifiedName& type = e->tagQName();
1813                     Node* n = e->nextSibling();
1814                     while (n) {
1815                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
1816                             count++;
1817                         n = n->nextSibling();
1818                     }
1819                     if (matchNth(count, a, b))
1820                         return true;
1821                 }
1822                 break;
1823             }
1824             case CSSSelector::PseudoTarget:
1825                 if (e == e->document()->getCSSTarget())
1826                     return true;
1827                 break;
1828             case CSSSelector::PseudoAnyLink:
1829                 if (pseudoState == PseudoUnknown)
1830                     pseudoState = checkPseudoState(e, false);
1831                 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1832                     return true;
1833                 break;
1834             case CSSSelector::PseudoAutofill:
1835                 if (e && e->hasTagName(inputTag))
1836                     return static_cast<HTMLInputElement*>(e)->autofilled();
1837                 break;
1838             case CSSSelector::PseudoLink:
1839                 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1840                     pseudoState = checkPseudoState(e);
1841                 if (pseudoState == PseudoLink)
1842                     return true;
1843                 break;
1844             case CSSSelector::PseudoVisited:
1845                 if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
1846                     pseudoState = checkPseudoState(e);
1847                 if (pseudoState == PseudoVisited)
1848                     return true;
1849                 break;
1850             case CSSSelector::PseudoDrag: {
1851                 if (m_element == e && m_style)
1852                     m_style->setAffectedByDragRules(true);
1853                     if (m_element != e && e->renderStyle())
1854                         e->renderStyle()->setAffectedByDragRules(true);
1855                     if (e->renderer() && e->renderer()->isDragging())
1856                         return true;
1857                 break;
1858             }
1859             case CSSSelector::PseudoFocus:
1860                 if (e && e->focused() && e->document()->frame()->selectionController()->isFocusedAndActive())
1861                     return true;
1862                 break;
1863             case CSSSelector::PseudoHover: {
1864                 // If we're in quirks mode, then hover should never match anchors with no
1865                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
1866                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1867                     if (m_element == e && m_style)
1868                         m_style->setAffectedByHoverRules(true);
1869                     if (m_element != e && e->renderStyle())
1870                         e->renderStyle()->setAffectedByHoverRules(true);
1871                     if (e->hovered())
1872                         return true;
1873                 }
1874                 break;
1875             }
1876             case CSSSelector::PseudoActive:
1877                 // If we're in quirks mode, then :active should never match anchors with no
1878                 // href and *:active should not match anything. 
1879                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
1880                     if (m_element == e && m_style)
1881                         m_style->setAffectedByActiveRules(true);
1882                     else if (e->renderStyle())
1883                         e->renderStyle()->setAffectedByActiveRules(true);
1884                     if (e->active())
1885                         return true;
1886                 }
1887                 break;
1888             case CSSSelector::PseudoEnabled:
1889                 if (e && e->isControl() && !e->isInputTypeHidden())
1890                     // The UI spec states that you can't match :enabled unless you are an object that can
1891                     // "receive focus and be activated."  We will limit matching of this pseudo-class to elements
1892                     // that are non-"hidden" controls.
1893                     return e->isEnabled();                    
1894                 break;
1895             case CSSSelector::PseudoDisabled:
1896                 if (e && e->isControl() && !e->isInputTypeHidden())
1897                     // The UI spec states that you can't match :enabled unless you are an object that can
1898                     // "receive focus and be activated."  We will limit matching of this pseudo-class to elements
1899                     // that are non-"hidden" controls.
1900                     return !e->isEnabled();                    
1901                 break;
1902             case CSSSelector::PseudoChecked:
1903                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
1904                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
1905                 // obey the CSS spec here in the test for matching the pseudo.
1906                 if (e && e->isChecked() && !e->isIndeterminate())
1907                     return true;
1908                 break;
1909             case CSSSelector::PseudoIndeterminate:
1910                 if (e && e->isIndeterminate())
1911                     return true;
1912                 break;
1913             case CSSSelector::PseudoRoot:
1914                 if (e == e->document()->documentElement())
1915                     return true;
1916                 break;
1917             case CSSSelector::PseudoLang: {
1918                 Node* n = e;
1919                 AtomicString value;
1920                 // The language property is inherited, so we iterate over the parents
1921                 // to find the first language.
1922                 while (n && value.isEmpty()) {
1923                     if (n->isElementNode()) {
1924                         // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
1925                         value = static_cast<Element*>(n)->getAttribute(XMLNames::langAttr);
1926                         if (value.isEmpty())
1927                             value = static_cast<Element*>(n)->getAttribute(langAttr);
1928                     } else if (n->isDocumentNode())
1929                         // checking the MIME content-language
1930                         value = static_cast<Document*>(n)->contentLanguage();
1931
1932                     n = n->parent();
1933                 }
1934                 if (value.isEmpty() || !value.startsWith(sel->m_argument, false))
1935                     break;
1936                 if (value.length() != sel->m_argument.length() && value[sel->m_argument.length()] != '-')
1937                     break;
1938                 return true;
1939             }
1940             case CSSSelector::PseudoNot: {
1941                 // check the simple selector
1942                 for (CSSSelector* subSel = sel->m_simpleSelector; subSel; subSel = subSel->m_tagHistory) {
1943                     // :not cannot nest. I don't really know why this is a
1944                     // restriction in CSS3, but it is, so let's honour it.
1945                     if (subSel->m_simpleSelector)
1946                         break;
1947                     if (!checkOneSelector(subSel, e, isAncestor, true))
1948                         return true;
1949                 }
1950                 break;
1951             }
1952             case CSSSelector::PseudoUnknown:
1953             case CSSSelector::PseudoNotParsed:
1954             default:
1955                 ASSERT_NOT_REACHED();
1956                 break;
1957         }
1958         return false;
1959     }
1960     if (sel->m_match == CSSSelector::PseudoElement) {
1961         if (e != m_element) return false;
1962
1963         switch (sel->pseudoType()) {
1964             // Pseudo-elements:
1965             case CSSSelector::PseudoFirstLine:
1966                 dynamicPseudo = RenderStyle::FIRST_LINE;
1967                 return true;
1968             case CSSSelector::PseudoFirstLetter:
1969                 dynamicPseudo = RenderStyle::FIRST_LETTER;
1970                 if (Document* doc = e->document())
1971                     doc->setUsesFirstLetterRules(true);
1972                 return true;
1973             case CSSSelector::PseudoSelection:
1974                 dynamicPseudo = RenderStyle::SELECTION;
1975                 return true;
1976             case CSSSelector::PseudoBefore:
1977                 dynamicPseudo = RenderStyle::BEFORE;
1978                 return true;
1979             case CSSSelector::PseudoAfter:
1980                 dynamicPseudo = RenderStyle::AFTER;
1981                 return true;
1982             case CSSSelector::PseudoFileUploadButton:
1983                 dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON;
1984                 return true;
1985             case CSSSelector::PseudoSliderThumb:
1986                 dynamicPseudo = RenderStyle::SLIDER_THUMB;
1987                 return true; 
1988             case CSSSelector::PseudoSearchCancelButton:
1989                 dynamicPseudo = RenderStyle::SEARCH_CANCEL_BUTTON;
1990                 return true; 
1991             case CSSSelector::PseudoSearchDecoration:
1992                 dynamicPseudo = RenderStyle::SEARCH_DECORATION;
1993                 return true;
1994             case CSSSelector::PseudoSearchResultsDecoration:
1995                 dynamicPseudo = RenderStyle::SEARCH_RESULTS_DECORATION;
1996                 return true;
1997             case CSSSelector::PseudoSearchResultsButton:
1998                 dynamicPseudo = RenderStyle::SEARCH_RESULTS_BUTTON;
1999                 return true;
2000             case CSSSelector::PseudoMediaControlsPanel:
2001                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PANEL;
2002                 return true;
2003             case CSSSelector::PseudoMediaControlsMuteButton:
2004                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON;
2005                 return true;
2006             case CSSSelector::PseudoMediaControlsPlayButton:
2007                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON;
2008                 return true;
2009             case CSSSelector::PseudoMediaControlsTimeDisplay:
2010                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIME_DISPLAY;
2011                 return true;
2012             case CSSSelector::PseudoMediaControlsTimeline:
2013                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIMELINE;
2014                 return true;
2015             case CSSSelector::PseudoMediaControlsSeekBackButton:
2016                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON;
2017                 return true;
2018             case CSSSelector::PseudoMediaControlsSeekForwardButton:
2019                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON;
2020                 return true;
2021             case CSSSelector::PseudoMediaControlsFullscreenButton:
2022                 dynamicPseudo = RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON;
2023                 return true;
2024             case CSSSelector::PseudoUnknown:
2025             case CSSSelector::PseudoNotParsed:
2026             default:
2027                 ASSERT_NOT_REACHED();
2028                 break;
2029         }
2030         return false;
2031     }
2032     // ### add the rest of the checks...
2033     return true;
2034 }
2035
2036 // -----------------------------------------------------------------
2037
2038 CSSRuleSet::CSSRuleSet()
2039 {
2040     m_universalRules = 0;
2041     m_ruleCount = 0;
2042 }
2043
2044 CSSRuleSet::~CSSRuleSet()
2045
2046     deleteAllValues(m_idRules);
2047     deleteAllValues(m_classRules);
2048     deleteAllValues(m_tagRules);
2049
2050     delete m_universalRules; 
2051 }
2052
2053
2054 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
2055                               CSSStyleRule* rule, CSSSelector* sel)
2056 {
2057     if (!key) return;
2058     CSSRuleDataList* rules = map.get(key);
2059     if (!rules) {
2060         rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
2061         map.set(key, rules);
2062     } else
2063         rules->append(m_ruleCount++, rule, sel);
2064 }
2065
2066 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
2067 {
2068     if (sel->m_match == CSSSelector::Id) {
2069         addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel);
2070         return;
2071     }
2072     if (sel->m_match == CSSSelector::Class) {
2073         addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel);
2074         return;
2075     }
2076      
2077     const AtomicString& localName = sel->m_tag.localName();
2078     if (localName != starAtom) {
2079         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
2080         return;
2081     }
2082     
2083     // Just put it in the universal rule set.
2084     if (!m_universalRules)
2085         m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
2086     else
2087         m_universalRules->append(m_ruleCount++, rule, sel);
2088 }
2089
2090 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
2091 {
2092     if (!sheet || !sheet->isCSSStyleSheet())
2093         return;
2094
2095     // No media implies "all", but if a media list exists it must
2096     // contain our current medium
2097     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
2098         return; // the style sheet doesn't apply
2099
2100     int len = sheet->length();
2101
2102     for (int i = 0; i < len; i++) {
2103         StyleBase* item = sheet->item(i);
2104         if (item->isStyleRule()) {
2105             CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
2106             for (CSSSelector* s = rule->selector(); s; s = s->next())
2107                 addRule(rule, s);
2108         }
2109         else if (item->isImportRule()) {
2110             CSSImportRule* import = static_cast<CSSImportRule*>(item);
2111             if (!import->media() || medium.eval(import->media(), styleSelector))
2112                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
2113         }
2114         else if (item->isMediaRule()) {
2115             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
2116             CSSRuleList* rules = r->cssRules();
2117
2118             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
2119                 // Traverse child elements of the @media rule.
2120                 for (unsigned j = 0; j < rules->length(); j++) {
2121                     CSSRule *childItem = rules->item(j);
2122                     if (childItem->isStyleRule()) {
2123                         // It is a StyleRule, so append it to our list
2124                         CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
2125                         for (CSSSelector* s = rule->selector(); s; s = s->next())
2126                             addRule(rule, s);
2127                     } else if (item->isFontFaceRule() && styleSelector) {
2128                         // Add this font face to our set.
2129                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
2130                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2131                     }
2132                 }   // for rules
2133             }   // if rules
2134         } else if (item->isFontFaceRule() && styleSelector) {
2135             // Add this font face to our set.
2136             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
2137             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2138         }
2139     }
2140 }
2141
2142 // -------------------------------------------------------------------------------------
2143 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2144
2145 static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
2146 {
2147     Length l;
2148     if (!primitiveValue) {
2149         if (ok)
2150             *ok = false;
2151     } else {
2152         int type = primitiveValue->primitiveType();
2153         if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2154             l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
2155         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2156             l = Length(primitiveValue->getDoubleValue(), Percent);
2157         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2158             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2159         else if (ok)
2160             *ok = false;
2161     }
2162     return l;
2163 }
2164
2165 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
2166                                          int startIndex, int endIndex)
2167 {
2168     if (startIndex == -1) return;
2169     for (int i = startIndex; i <= endIndex; i++) {
2170         CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
2171         DeprecatedValueListConstIterator<CSSProperty> end;
2172         for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
2173             const CSSProperty& current = *it;
2174             // give special priority to font-xxx, color properties
2175             if (isImportant == current.isImportant()) {
2176                 bool first;
2177                 switch (current.id()) {
2178                     case CSSPropertyLineHeight:
2179                         m_lineHeightValue = current.value();
2180                         first = !applyFirst; // we apply line-height later
2181                         break;
2182                     case CSSPropertyColor:
2183                     case CSSPropertyDirection:
2184                     case CSSPropertyDisplay:
2185                     case CSSPropertyFont:
2186                     case CSSPropertyFontSize:
2187                     case CSSPropertyFontStyle:
2188                     case CSSPropertyFontFamily:
2189                     case CSSPropertyFontWeight:
2190                     case CSSPropertyWebkitTextSizeAdjust:
2191                     case CSSPropertyFontVariant:
2192                     case CSSPropertyZoom:
2193                         // these have to be applied first, because other properties use the computed
2194                         // values of these porperties.
2195                         first = true;
2196                         break;
2197                     default:
2198                         first = false;
2199                         break;
2200                 }
2201                 if (first == applyFirst)
2202                     applyProperty(current.id(), current.value());
2203             }
2204         }
2205     }
2206 }
2207
2208 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
2209 {
2210     CounterDirectiveMap& map = style->accessCounterDirectives();
2211     typedef CounterDirectiveMap::iterator Iterator;
2212
2213     Iterator end = map.end();
2214     for (Iterator it = map.begin(); it != end; ++it)
2215         if (isReset)
2216             it->second.m_reset = false;
2217         else
2218             it->second.m_increment = false;
2219
2220     int length = list ? list->length() : 0;
2221     for (int i = 0; i < length; ++i) {
2222         Pair* pair = static_cast<CSSPrimitiveValue*>(list->itemWithoutBoundsCheck(i))->getPairValue();
2223         AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
2224         // FIXME: What about overflow?
2225         int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
2226         CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
2227         if (isReset) {
2228             directives.m_reset = true;
2229             directives.m_resetValue = value;
2230         } else {
2231             if (directives.m_increment)
2232                 directives.m_incrementValue += value;
2233             else {
2234                 directives.m_increment = true;
2235                 directives.m_incrementValue = value;
2236             }
2237         }
2238     }
2239 }
2240
2241 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
2242 {
2243     CSSPrimitiveValue* primitiveValue = 0;
2244     if (value->isPrimitiveValue())
2245         primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2246
2247     float zoomFactor = m_style->effectiveZoom();
2248
2249     Length l;
2250     bool apply = false;
2251
2252     unsigned short valueType = value->cssValueType();
2253
2254     bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
2255     bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
2256     
2257     // These properties are used to set the correct margins/padding on RTL lists.
2258     if (id == CSSPropertyWebkitMarginStart)
2259         id = m_style->direction() == LTR ? CSSPropertyMarginLeft : CSSPropertyMarginRight;
2260     else if (id == CSSPropertyWebkitPaddingStart)
2261         id = m_style->direction() == LTR ? CSSPropertyPaddingLeft : CSSPropertyPaddingRight;
2262
2263     // What follows is a list that maps the CSS properties into their corresponding front-end
2264     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
2265     // are only hit when mapping "inherit" or "initial" into front-end values.
2266     switch (static_cast<CSSPropertyID>(id)) {
2267 // ident only properties
2268     case CSSPropertyBackgroundAttachment:
2269         HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
2270         return;
2271     case CSSPropertyWebkitBackgroundClip:
2272         HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
2273         return;
2274     case CSSPropertyWebkitBackgroundComposite:
2275         HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value)
2276         return;
2277     case CSSPropertyWebkitBackgroundOrigin:
2278         HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
2279         return;
2280     case CSSPropertyBackgroundRepeat:
2281         HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
2282         return;
2283     case CSSPropertyWebkitBackgroundSize:
2284         HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
2285         return;
2286     case CSSPropertyBorderCollapse:
2287         HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
2288         if (!primitiveValue)
2289             return;
2290         switch (primitiveValue->getIdent()) {
2291             case CSSValueCollapse:
2292                 m_style->setBorderCollapse(true);
2293                 break;
2294             case CSSValueSeparate:
2295                 m_style->setBorderCollapse(false);
2296                 break;
2297             default:
2298                 return;
2299         }
2300         return;
2301         
2302     case CSSPropertyBorderTopStyle:
2303         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
2304         if (primitiveValue)
2305             m_style->setBorderTopStyle(*primitiveValue);
2306         return;
2307     case CSSPropertyBorderRightStyle:
2308         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
2309         if (primitiveValue)
2310             m_style->setBorderRightStyle(*primitiveValue);
2311         return;
2312     case CSSPropertyBorderBottomStyle:
2313         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
2314         if (primitiveValue)
2315             m_style->setBorderBottomStyle(*primitiveValue);
2316         return;
2317     case CSSPropertyBorderLeftStyle:
2318         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
2319         if (primitiveValue)
2320             m_style->setBorderLeftStyle(*primitiveValue);
2321         return;
2322     case CSSPropertyOutlineStyle:
2323         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
2324         if (primitiveValue) {
2325             if (primitiveValue->getIdent() == CSSValueAuto)
2326                 m_style->setOutlineStyle(DOTTED, true);
2327             else
2328                 m_style->setOutlineStyle(*primitiveValue);
2329         }
2330         return;
2331     case CSSPropertyCaptionSide:
2332     {
2333         HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
2334         if (primitiveValue)
2335             m_style->setCaptionSide(*primitiveValue);
2336         return;
2337     }
2338     case CSSPropertyClear:
2339     {
2340         HANDLE_INHERIT_AND_INITIAL(clear, Clear)
2341         if (primitiveValue)
2342             m_style->setClear(*primitiveValue);
2343         return;
2344     }
2345     case CSSPropertyDirection:
2346     {
2347         HANDLE_INHERIT_AND_INITIAL(direction, Direction)
2348         if (primitiveValue)
2349             m_style->setDirection(*primitiveValue);
2350         return;
2351     }
2352     case CSSPropertyDisplay:
2353     {
2354         HANDLE_INHERIT_AND_INITIAL(display, Display)
2355         if (primitiveValue)
2356             m_style->setDisplay(*primitiveValue);
2357         return;
2358     }
2359
2360     case CSSPropertyEmptyCells:
2361     {
2362         HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
2363         if (primitiveValue)
2364             m_style->setEmptyCells(*primitiveValue);
2365         return;
2366     }
2367     case CSSPropertyFloat:
2368     {
2369         HANDLE_INHERIT_AND_INITIAL(floating, Floating)
2370         if (primitiveValue)
2371             m_style->setFloating(*primitiveValue);
2372         return;
2373     }
2374
2375     case CSSPropertyFontStyle:
2376     {
2377         FontDescription fontDescription = m_style->fontDescription();
2378         if (isInherit)
2379             fontDescription.setItalic(m_parentStyle->fontDescription().italic());
2380         else if (isInitial)
2381             fontDescription.setItalic(false);
2382         else {
2383             if (!primitiveValue)
2384                 return;
2385             switch (primitiveValue->getIdent()) {
2386                 case CSSValueOblique:
2387                 // FIXME: oblique is the same as italic for the moment...
2388                 case CSSValueItalic:
2389                     fontDescription.setItalic(true);
2390                     break;
2391                 case CSSValueNormal:
2392                     fontDescription.setItalic(false);
2393                     break;
2394                 default:
2395                     return;
2396             }
2397         }
2398         if (m_style->setFontDescription(fontDescription))
2399             m_fontDirty = true;
2400         return;
2401     }
2402
2403     case CSSPropertyFontVariant:
2404     {
2405         FontDescription fontDescription = m_style->fontDescription();
2406         if (isInherit) 
2407             fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps());
2408         else if (isInitial)
2409             fontDescription.setSmallCaps(false);
2410         else {
2411             if (!primitiveValue)
2412                 return;
2413             int id = primitiveValue->getIdent();
2414             if (id == CSSValueNormal)
2415                 fontDescription.setSmallCaps(false);
2416             else if (id == CSSValueSmallCaps)
2417                 fontDescription.setSmallCaps(true);
2418             else
2419                 return;
2420         }
2421         if (m_style->setFontDescription(fontDescription))
2422             m_fontDirty = true;
2423         return;        
2424     }
2425
2426     case CSSPropertyFontWeight:
2427     {
2428         FontDescription fontDescription = m_style->fontDescription();
2429         if (isInherit)
2430             fontDescription.setWeight(m_parentStyle->fontDescription().weight());
2431         else if (isInitial)
2432             fontDescription.setWeight(FontWeightNormal);
2433         else {
2434             if (!primitiveValue)
2435                 return;
2436             if (primitiveValue->getIdent()) {
2437                 switch (primitiveValue->getIdent()) {
2438                     case CSSValueBolder:
2439                         fontDescription.setWeight(fontDescription.bolderWeight());
2440                         break;
2441                     case CSSValueLighter:
2442                         fontDescription.setWeight(fontDescription.lighterWeight());
2443                         break;
2444                     case CSSValueBold:
2445                     case CSSValue700:
2446                         fontDescription.setWeight(FontWeightBold);
2447                         break;
2448                     case CSSValueNormal:
2449                     case CSSValue400:
2450                         fontDescription.setWeight(FontWeightNormal);
2451                         break;
2452                     case CSSValue900:
2453                         fontDescription.setWeight(FontWeight900);
2454                         break;
2455                     case CSSValue800:
2456                         fontDescription.setWeight(FontWeight800);
2457                         break;
2458                     case CSSValue600:
2459                         fontDescription.setWeight(FontWeight600);
2460                         break;
2461                     case CSSValue500:
2462                         fontDescription.setWeight(FontWeight500);
2463                         break;
2464                     case CSSValue300:
2465                         fontDescription.setWeight(FontWeight300);
2466                         break;
2467                     case CSSValue200:
2468                         fontDescription.setWeight(FontWeight200);
2469                         break;
2470                     case CSSValue100:
2471                         fontDescription.setWeight(FontWeight100);
2472                         break;
2473                     default:
2474                         return;
2475                 }
2476             } else
2477                 ASSERT_NOT_REACHED();
2478         }
2479         if (m_style->setFontDescription(fontDescription))
2480             m_fontDirty = true;
2481         return;
2482     }
2483         
2484     case CSSPropertyListStylePosition:
2485     {
2486         HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2487         if (primitiveValue)
2488             m_style->setListStylePosition(*primitiveValue);
2489         return;
2490     }
2491
2492     case CSSPropertyListStyleType:
2493     {
2494         HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2495         if (primitiveValue)
2496             m_style->setListStyleType(*primitiveValue);
2497         return;
2498     }
2499
2500     case CSSPropertyOverflow:
2501     {
2502         if (isInherit) {
2503             m_style->setOverflowX(m_parentStyle->overflowX());
2504             m_style->setOverflowY(m_parentStyle->overflowY());
2505             return;
2506         }
2507         
2508         if (isInitial) {
2509             m_style->setOverflowX(RenderStyle::initialOverflowX());
2510             m_style->setOverflowY(RenderStyle::initialOverflowY());
2511             return;
2512         }
2513             
2514         EOverflow o = *primitiveValue;
2515
2516         m_style->setOverflowX(o);
2517         m_style->setOverflowY(o);
2518         return;
2519     }
2520
2521     case CSSPropertyOverflowX:
2522     {
2523         HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
2524         m_style->setOverflowX(*primitiveValue);
2525         return;
2526     }
2527
2528     case CSSPropertyOverflowY:
2529     {
2530         HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
2531         m_style->setOverflowY(*primitiveValue);
2532         return;
2533     }
2534
2535     case CSSPropertyPageBreakBefore:
2536     {
2537         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2538         if (primitiveValue)
2539             m_style->setPageBreakBefore(*primitiveValue);
2540         return;
2541     }
2542
2543     case CSSPropertyPageBreakAfter:
2544     {
2545         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2546         if (primitiveValue)
2547             m_style->setPageBreakAfter(*primitiveValue);
2548         return;
2549     }
2550
2551     case CSSPropertyPageBreakInside: {
2552         HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2553         if (!primitiveValue)
2554             return;
2555         EPageBreak pageBreak = *primitiveValue;
2556         if (pageBreak != PBALWAYS)
2557             m_style->setPageBreakInside(pageBreak);
2558         return;
2559     }
2560         
2561     case CSSPropertyPosition:
2562     {
2563         HANDLE_INHERIT_AND_INITIAL(position, Position)
2564         if (primitiveValue)
2565             m_style->setPosition(*primitiveValue);
2566         return;
2567     }
2568
2569     case CSSPropertyTableLayout: {
2570         HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2571
2572         ETableLayout l = *primitiveValue;
2573         if (l == TAUTO)
2574             l = RenderStyle::initialTableLayout();
2575
2576         m_style->setTableLayout(l);
2577         return;
2578     }
2579         
2580     case CSSPropertyUnicodeBidi: {
2581         HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2582         m_style->setUnicodeBidi(*primitiveValue);
2583         return;
2584     }
2585     case CSSPropertyTextTransform: {
2586         HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2587         m_style->setTextTransform(*primitiveValue);
2588         return;
2589     }
2590
2591     case CSSPropertyVisibility:
2592     {
2593         HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2594         m_style->setVisibility(*primitiveValue);
2595         return;
2596     }
2597     case CSSPropertyWhiteSpace:
2598         HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2599         m_style->setWhiteSpace(*primitiveValue);
2600         return;
2601
2602     case CSSPropertyBackgroundPosition:
2603         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2604         HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2605         return;
2606     case CSSPropertyBackgroundPositionX: {
2607         HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2608         return;
2609     }
2610     case CSSPropertyBackgroundPositionY: {
2611         HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2612         return;
2613     }
2614     case CSSPropertyBorderSpacing: {
2615         if (isInherit) {
2616             m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing());
2617             m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing());
2618         }
2619         else if (isInitial) {
2620             m_style->setHorizontalBorderSpacing(0);
2621             m_style->setVerticalBorderSpacing(0);
2622         }
2623         return;
2624     }
2625     case CSSPropertyWebkitBorderHorizontalSpacing: {
2626         HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2627         if (!primitiveValue)
2628             return;
2629         short spacing =  primitiveValue->computeLengthShort(m_style, zoomFactor);
2630         m_style->setHorizontalBorderSpacing(spacing);
2631         return;
2632     }
2633     case CSSPropertyWebkitBorderVerticalSpacing: {
2634         HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2635         if (!primitiveValue)
2636             return;
2637         short spacing =  primitiveValue->computeLengthShort(m_style, zoomFactor);
2638         m_style->setVerticalBorderSpacing(spacing);
2639         return;
2640     }
2641     case CSSPropertyCursor:
2642         if (isInherit) {
2643             m_style->setCursor(m_parentStyle->cursor());
2644             m_style->setCursorList(m_parentStyle->cursors());
2645             return;
2646         }
2647         m_style->clearCursorList();
2648         if (isInitial) {
2649             m_style->setCursor(RenderStyle::initialCursor());
2650             return;
2651         }
2652         if (value->isValueList()) {
2653             CSSValueList* list = static_cast<CSSValueList*>(value);
2654             int len = list->length();
2655             m_style->setCursor(CURSOR_AUTO);
2656             for (int i = 0; i < len; i++) {
2657                 CSSValue* item = list->itemWithoutBoundsCheck(i);
2658                 if (!item->isPrimitiveValue())
2659                     continue;
2660                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2661                 int type = primitiveValue->primitiveType();
2662                 if (type == CSSPrimitiveValue::CSS_URI) {
2663                     CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
2664                     if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style.
2665                         m_style->setUnique();
2666                     // FIXME: Temporary clumsiness to pass off a CachedImage to an API that will eventually convert to using
2667                     // StyleImage.
2668                     RefPtr<StyleCachedImage> styleCachedImage(image->cachedImage(m_element->document()->docLoader()));
2669                     if (styleCachedImage)
2670                         m_style->addCursor(styleCachedImage->cachedImage(), image->hotspot());
2671                 } else if (type == CSSPrimitiveValue::CSS_IDENT)
2672                     m_style->setCursor(*primitiveValue);
2673             }
2674         } else if (primitiveValue) {
2675             int type = primitiveValue->primitiveType();
2676             if (type == CSSPrimitiveValue::CSS_IDENT)
2677                 m_style->setCursor(*primitiveValue);
2678         }
2679         return;
2680 // colors || inherit
2681     case CSSPropertyBackgroundColor:
2682     case CSSPropertyBorderTopColor:
2683     case CSSPropertyBorderRightColor:
2684     case CSSPropertyBorderBottomColor:
2685     case CSSPropertyBorderLeftColor:
2686     case CSSPropertyColor:
2687     case CSSPropertyOutlineColor:
2688     case CSSPropertyWebkitColumnRuleColor:
2689     case CSSPropertyWebkitTextStrokeColor:
2690     case CSSPropertyWebkitTextFillColor: {
2691         Color col;
2692         if (isInherit) {
2693             HANDLE_INHERIT_COND(CSSPropertyBackgroundColor, backgroundColor, BackgroundColor)
2694             HANDLE_INHERIT_COND(CSSPropertyBorderTopColor, borderTopColor, BorderTopColor)
2695             HANDLE_INHERIT_COND(CSSPropertyBorderBottomColor, borderBottomColor, BorderBottomColor)
2696             HANDLE_INHERIT_COND(CSSPropertyBorderRightColor, borderRightColor, BorderRightColor)
2697             HANDLE_INHERIT_COND(CSSPropertyBorderLeftColor, borderLeftColor, BorderLeftColor)
2698             HANDLE_INHERIT_COND(CSSPropertyColor, color, Color)
2699             HANDLE_INHERIT_COND(CSSPropertyOutlineColor, outlineColor, OutlineColor)
2700             HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleColor, columnRuleColor, ColumnRuleColor)
2701             HANDLE_INHERIT_COND(CSSPropertyWebkitTextStrokeColor, textStrokeColor, TextStrokeColor)
2702             HANDLE_INHERIT_COND(CSSPropertyWebkitTextFillColor, textFillColor, TextFillColor)
2703             return;
2704         }
2705         if (isInitial) {
2706             // The border/outline colors will just map to the invalid color |col| above.  This will have the
2707             // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2708             // not painting the background since the color won't be valid).
2709             if (id == CSSPropertyColor)
2710                 col = RenderStyle::initialColor();
2711         } else {
2712             if (!primitiveValue)
2713                 return;
2714             col = getColorFromPrimitiveValue(primitiveValue);
2715         }
2716
2717         switch (id) {
2718         case CSSPropertyBackgroundColor:
2719             m_style->setBackgroundColor(col);
2720             break;
2721         case CSSPropertyBorderTopColor:
2722             m_style->setBorderTopColor(col);
2723             break;
2724         case CSSPropertyBorderRightColor:
2725             m_style->setBorderRightColor(col);
2726             break;
2727         case CSSPropertyBorderBottomColor:
2728             m_style->setBorderBottomColor(col);
2729             break;
2730         case CSSPropertyBorderLeftColor:
2731             m_style->setBorderLeftColor(col);
2732             break;
2733         case CSSPropertyColor:
2734             m_style->setColor(col);
2735             break;
2736         case CSSPropertyOutlineColor:
2737             m_style->setOutlineColor(col);
2738             break;
2739         case CSSPropertyWebkitColumnRuleColor:
2740             m_style->setColumnRuleColor(col);
2741             break;
2742         case CSSPropertyWebkitTextStrokeColor:
2743             m_style->setTextStrokeColor(col);
2744             break;
2745         case CSSPropertyWebkitTextFillColor:
2746             m_style->setTextFillColor(col);
2747             break;
2748         }
2749         
2750         return;
2751     }
2752     
2753 // uri || inherit
2754     case CSSPropertyBackgroundImage:
2755         HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2756         return;
2757     case CSSPropertyListStyleImage:
2758     {
2759         HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2760         m_style->setListStyleImage(styleImage(value));
2761         return;
2762     }
2763
2764 // length
2765     case CSSPropertyBorderTopWidth:
2766     case CSSPropertyBorderRightWidth:
2767     case CSSPropertyBorderBottomWidth:
2768     case CSSPropertyBorderLeftWidth:
2769     case CSSPropertyOutlineWidth:
2770     case CSSPropertyWebkitColumnRuleWidth:
2771     {
2772         if (isInherit) {
2773             HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth)
2774             HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth)
2775             HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth)
2776             HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth)
2777             HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth)
2778             HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth)
2779             return;
2780         }
2781         else if (isInitial) {
2782             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth)
2783             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth)
2784             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth)
2785             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth)
2786             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth)
2787             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth)
2788             return;
2789         }
2790
2791         if (!primitiveValue)
2792             return;
2793         short width = 3;
2794         switch (primitiveValue->getIdent()) {
2795         case CSSValueThin:
2796             width = 1;
2797             break;
2798         case CSSValueMedium:
2799             width = 3;
2800             break;
2801         case CSSValueThick:
2802             width = 5;
2803             break;
2804         case CSSValueInvalid:
2805             width = primitiveValue->computeLengthShort(m_style, zoomFactor);
2806             break;
2807         default:
2808             return;
2809         }
2810
2811         if (width < 0) return;
2812         switch (id) {
2813         case CSSPropertyBorderTopWidth:
2814             m_style->setBorderTopWidth(width);
2815             break;
2816         case CSSPropertyBorderRightWidth:
2817             m_style->setBorderRightWidth(width);
2818             break;
2819         case CSSPropertyBorderBottomWidth:
2820             m_style->setBorderBottomWidth(width);
2821             break;
2822         case CSSPropertyBorderLeftWidth:
2823             m_style->setBorderLeftWidth(width);
2824             break;
2825         case CSSPropertyOutlineWidth:
2826             m_style->setOutlineWidth(width);
2827             break;
2828         case CSSPropertyWebkitColumnRuleWidth:
2829             m_style->setColumnRuleWidth(width);
2830             break;
2831         default:
2832             return;
2833         }
2834         return;
2835     }
2836
2837     case CSSPropertyLetterSpacing:
2838     case CSSPropertyWordSpacing:
2839     {
2840         
2841         if (isInherit) {
2842             HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing)
2843             HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing)
2844             return;
2845         }
2846         else if (isInitial) {
2847             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing)
2848             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing)
2849             return;
2850         }
2851         
2852         int width = 0;
2853         if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal){
2854             width = 0;
2855         } else {
2856             if (!primitiveValue)
2857                 return;
2858             width = primitiveValue->computeLengthInt(m_style, zoomFactor);
2859         }
2860         switch (id) {
2861         case CSSPropertyLetterSpacing:
2862             m_style->setLetterSpacing(width);
2863             break;
2864         case CSSPropertyWordSpacing:
2865             m_style->setWordSpacing(width);
2866             break;
2867             // ### needs the definitions in renderstyle
2868         default: break;
2869         }
2870         return;
2871     }
2872
2873     case CSSPropertyWordBreak: {
2874         HANDLE_INHERIT_AND_INITIAL(wordBreak, WordBreak)
2875         m_style->setWordBreak(*primitiveValue);
2876         return;
2877     }
2878
2879     case CSSPropertyWordWrap: {
2880         HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2881         m_style->setWordWrap(*primitiveValue);
2882         return;
2883     }
2884
2885     case CSSPropertyWebkitNbspMode:
2886     {
2887         HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2888         m_style->setNBSPMode(*primitiveValue);
2889         return;
2890     }
2891
2892     case CSSPropertyWebkitLineBreak:
2893     {
2894         HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2895         m_style->setKHTMLLineBreak(*primitiveValue);
2896         return;
2897     }
2898
2899     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2900     {
2901         HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2902         m_style->setMatchNearestMailBlockquoteColor(*primitiveValue);
2903         return;
2904     }
2905
2906     case CSSPropertyResize:
2907     {
2908         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2909
2910         if (!primitiveValue->getIdent())
2911             return;
2912
2913         EResize r = RESIZE_NONE;
2914         if (primitiveValue->getIdent() == CSSValueAuto) {
2915             if (Settings* settings = m_document->settings())
2916                 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2917         } else
2918             r = *primitiveValue;
2919             
2920         m_style->setResize(r);
2921         return;
2922     }
2923     
2924     // length, percent
2925     case CSSPropertyMaxWidth:
2926         // +none +inherit
2927         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone)
2928             apply = true;
2929     case CSSPropertyTop:
2930     case CSSPropertyLeft:
2931     case CSSPropertyRight:
2932     case CSSPropertyBottom:
2933     case CSSPropertyWidth:
2934     case CSSPropertyMinWidth:
2935     case CSSPropertyMarginTop:
2936     case CSSPropertyMarginRight:
2937     case CSSPropertyMarginBottom:
2938     case CSSPropertyMarginLeft:
2939         // +inherit +auto
2940         if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) {
2941             if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
2942                 l = Length(Intrinsic);
2943                 apply = true;
2944             }
2945             else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
2946                 l = Length(MinIntrinsic);
2947                 apply = true;
2948             }
2949         }
2950         if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
2951             apply = true;
2952     case CSSPropertyPaddingTop:
2953     case CSSPropertyPaddingRight:
2954     case CSSPropertyPaddingBottom:
2955     case CSSPropertyPaddingLeft:
2956     case CSSPropertyTextIndent:
2957         // +inherit
2958     {
2959         if (isInherit) {
2960             HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth)
2961             HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom)
2962             HANDLE_INHERIT_COND(CSSPropertyTop, top, Top)
2963             HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left)
2964             HANDLE_INHERIT_COND(CSSPropertyRight, right, Right)
2965             HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width)
2966             HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth)
2967             HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop)
2968             HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight)
2969             HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom)
2970             HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft)
2971             HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop)
2972             HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight)
2973             HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom)
2974             HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft)
2975             HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent)
2976             return;
2977         }
2978         else if (isInitial) {
2979             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize)
2980             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset)
2981             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset)
2982             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset)
2983             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset)
2984             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size)
2985             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize)
2986             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding)
2987             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding)
2988             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding)
2989             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding)
2990             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin)
2991             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin)
2992             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin)
2993             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin)
2994             HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent)
2995             return;
2996         } 
2997
2998         if (primitiveValue && !apply) {
2999             int type = primitiveValue->primitiveType();
3000             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3001                 // Handle our quirky margin units if we have them.
3002                 l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed, 
3003                            primitiveValue->isQuirkValue());
3004             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3005                 l = Length(primitiveValue->getDoubleValue(), Percent);
3006             else
3007                 return;
3008             if (id == CSSPropertyPaddingLeft || id == CSSPropertyPaddingRight ||
3009                 id == CSSPropertyPaddingTop || id == CSSPropertyPaddingBottom)
3010                 // Padding can't be negative
3011                 apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
3012             else
3013                 apply = true;
3014         }
3015         if (!apply) return;
3016         switch (id) {
3017             case CSSPropertyMaxWidth:
3018                 m_style->setMaxWidth(l);
3019                 break;
3020             case CSSPropertyBottom:
3021                 m_style->setBottom(l);
3022                 break;
3023             case CSSPropertyTop:
3024                 m_style->setTop(l);
3025                 break;
3026             case CSSPropertyLeft:
3027                 m_style->setLeft(l);
3028                 break;
3029             case CSSPropertyRight:
3030                 m_style->setRight(l);
3031                 break;
3032             case CSSPropertyWidth:
3033                 m_style->setWidth(l);
3034                 break;
3035             case CSSPropertyMinWidth:
3036                 m_style->setMinWidth(l);
3037                 break;
3038             case CSSPropertyPaddingTop:
3039                 m_style->setPaddingTop(l);
3040                 break;
3041             case CSSPropertyPaddingRight:
3042                 m_style->setPaddingRight(l);
3043                 break;
3044             case CSSPropertyPaddingBottom:
3045                 m_style->setPaddingBottom(l);
3046                 break;
3047             case CSSPropertyPaddingLeft:
3048                 m_style->setPaddingLeft(l);
3049                 break;
3050             case CSSPropertyMarginTop:
3051                 m_style->setMarginTop(l);
3052                 break;
3053             case CSSPropertyMarginRight:
3054                 m_style->setMarginRight(l);
3055                 break;
3056             case CSSPropertyMarginBottom:
3057                 m_style->setMarginBottom(l);
3058                 break;
3059             case CSSPropertyMarginLeft:
3060                 m_style->setMarginLeft(l);
3061                 break;
3062             case CSSPropertyTextIndent:
3063                 m_style->setTextIndent(l);
3064                 break;
3065             default:
3066                 break;
3067             }
3068         return;
3069     }
3070
3071     case CSSPropertyMaxHeight:
3072         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3073             l = Length(undefinedLength, Fixed);
3074             apply = true;
3075         }
3076     case CSSPropertyHeight:
3077     case CSSPropertyMinHeight:
3078         if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
3079             l = Length(Intrinsic);
3080             apply = true;
3081         } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
3082             l = Length(MinIntrinsic);
3083             apply = true;
3084         } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
3085             apply = true;
3086         if (isInherit) {
3087             HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight)
3088             HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height)
3089             HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight)
3090             return;
3091         }
3092         if (isInitial) {
3093             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize)
3094             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size)
3095             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize)
3096             return;
3097         }
3098
3099         if (primitiveValue && !apply) {
3100             unsigned short type = primitiveValue->primitiveType();
3101             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3102                 l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
3103             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3104                 l = Length(primitiveValue->getDoubleValue(), Percent);
3105             else
3106                 return;
3107             apply = true;
3108         }
3109         if (apply)
3110             switch (id) {
3111                 case CSSPropertyMaxHeight:
3112                     m_style->setMaxHeight(l);
3113                     break;
3114                 case CSSPropertyHeight:
3115                     m_style->setHeight(l);
3116                     break;
3117                 case CSSPropertyMinHeight:
3118                     m_style->setMinHeight(l);
3119                     break;
3120             }
3121         return;
3122
3123     case CSSPropertyVerticalAlign:
3124         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
3125         if (!primitiveValue)
3126             return;
3127         if (primitiveValue->getIdent()) {
3128           EVerticalAlign align;
3129
3130           switch (primitiveValue->getIdent()) {
3131                 case CSSValueTop:
3132                     align = TOP; break;
3133                 case CSSValueBottom:
3134                     align = BOTTOM; break;
3135                 case CSSValueMiddle:
3136                     align = MIDDLE; break;
3137                 case CSSValueBaseline:
3138                     align = BASELINE; break;
3139                 case CSSValueTextBottom:
3140                     align = TEXT_BOTTOM; break;
3141                 case CSSValueTextTop:
3142                     align = TEXT_TOP; break;
3143                 case CSSValueSub:
3144                     align = SUB; break;
3145                 case CSSValueSuper:
3146                     align = SUPER; break;
3147                 case CSSValueWebkitBaselineMiddle:
3148                     align = BASELINE_MIDDLE; break;
3149                 default:
3150                     return;
3151             }
3152           m_style->setVerticalAlign(align);
3153           return;
3154         } else {
3155           int type = primitiveValue->primitiveType();
3156           Length l;
3157           if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3158             l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
3159           else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3160             l = Length(primitiveValue->getDoubleValue(), Percent);
3161
3162           m_style->setVerticalAlign(LENGTH);
3163           m_style->setVerticalAlignLength(l);
3164         }
3165         return;
3166
3167     case CSSPropertyFontSize:
3168     {
3169         FontDescription fontDescription = m_style->fontDescription();
3170         fontDescription.setKeywordSize(0);
3171         bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3172         float oldSize = 0;
3173         float size = 0;
3174         
3175         bool parentIsAbsoluteSize = false;
3176         if (m_parentNode) {
3177             oldSize = m_parentStyle->fontDescription().specifiedSize();
3178             parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
3179         }
3180
3181         if (isInherit) {
3182             size = oldSize;
3183             if (m_parentNode)
3184                 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
3185         } else if (isInitial) {
3186             size = fontSizeForKeyword(CSSValueMedium, m_style->htmlHacks(), familyIsFixed);
3187             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3188         } else if (primitiveValue->getIdent()) {
3189             // Keywords are being used.
3190             switch (primitiveValue->getIdent()) {
3191                 case CSSValueXxSmall:
3192                 case CSSValueXSmall:
3193                 case CSSValueSmall:
3194                 case CSSValueMedium:
3195                 case CSSValueLarge:
3196                 case CSSValueXLarge:
3197                 case CSSValueXxLarge:
3198                 case CSSValueWebkitXxxLarge:
3199                     size = fontSizeForKeyword(primitiveValue->getIdent(), m_style->htmlHacks(), familyIsFixed);
3200                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
3201                     break;
3202                 case CSSValueLarger:
3203                     size = largerFontSize(oldSize, m_style->htmlHacks());
3204                     break;
3205                 case CSSValueSmaller:
3206                     size = smallerFontSize(oldSize, m_style->htmlHacks());
3207                     break;
3208                 default:
3209                     return;
3210             }
3211
3212             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && 
3213                                               (primitiveValue->getIdent() == CSSValueLarger ||
3214                                                primitiveValue->getIdent() == CSSValueSmaller));
3215         } else {
3216             int type = primitiveValue->primitiveType();
3217             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
3218                                               (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
3219                                                type != CSSPrimitiveValue::CSS_EMS && 
3220                                                type != CSSPrimitiveValue::CSS_EXS));
3221             if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
3222                 size = primitiveValue->computeLengthFloat(m_parentStyle, true);
3223             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3224                 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
3225             else
3226                 return;
3227         }
3228
3229         if (size < 0)
3230             return;
3231
3232         setFontSize(fontDescription, size);
3233         if (m_style->setFontDescription(fontDescription))
3234             m_fontDirty = true;
3235         return;
3236     }
3237
3238     case CSSPropertyZIndex: {
3239         if (isInherit) {
3240             if (m_parentStyle->hasAutoZIndex())
3241                 m_style->setHasAutoZIndex();
3242             else
3243                 m_style->setZIndex(m_parentStyle->zIndex());
3244             return;
3245         } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
3246             m_style->setHasAutoZIndex();
3247             return;
3248         }
3249         
3250         // FIXME: Should clamp all sorts of other integer properties too.
3251         const double minIntAsDouble = INT_MIN;
3252         const double maxIntAsDouble = INT_MAX;
3253         m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble))));
3254         return;
3255     }
3256     case CSSPropertyWidows:
3257     {
3258         HANDLE_INHERIT_AND_INITIAL(widows, Widows)
3259         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3260             return;
3261         m_style->setWidows(primitiveValue->getIntValue());
3262         return;
3263     }
3264         
3265     case CSSPropertyOrphans:
3266     {
3267         HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
3268         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3269             return;
3270         m_style->setOrphans(primitiveValue->getIntValue());
3271         return;
3272     }        
3273
3274 // length, percent, number
3275     case CSSPropertyLineHeight:
3276     {
3277         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
3278         if (!primitiveValue)
3279             return;
3280         Length lineHeight;
3281         int type = primitiveValue->primitiveType();
3282         if (primitiveValue->getIdent() == CSSValueNormal)
3283             lineHeight = Length(-100.0, Percent);
3284         else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
3285             double multiplier = m_style->effectiveZoom();
3286             if (m_style->textSizeAdjust() && m_document->frame() && m_document->frame()->shouldApplyTextZoom())
3287                 multiplier *= m_document->frame()->textZoomFactor();
3288             lineHeight = Length(primitiveValue->computeLengthIntForLength(m_style, multiplier), Fixed);
3289         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3290             lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
3291         else if (type == CSSPrimitiveValue::CSS_NUMBER)
3292             lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
3293         else
3294             return;
3295         m_style->setLineHeight(lineHeight);
3296         return;
3297     }
3298
3299 // string
3300     case CSSPropertyTextAlign:
3301     {
3302         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
3303         if (!primitiveValue)
3304             return;
3305         int id = primitiveValue->getIdent();
3306         if (id == CSSValueStart)
3307             m_style->setTextAlign(m_style->direction() == LTR ? LEFT : RIGHT);
3308         else if (id == CSSValueEnd)
3309             m_style->setTextAlign(m_style->direction() == LTR ? RIGHT : LEFT);
3310         else
3311             m_style->setTextAlign(*primitiveValue);
3312         return;
3313     }
3314
3315 // rect
3316     case CSSPropertyClip:
3317     {
3318         Length top;
3319         Length right;
3320         Length bottom;
3321         Length left;
3322         bool hasClip = true;
3323         if (isInherit) {
3324             if (m_parentStyle->hasClip()) {
3325                 top = m_parentStyle->clipTop();
3326                 right = m_parentStyle->clipRight();
3327                 bottom = m_parentStyle->clipBottom();
3328                 left = m_parentStyle->clipLeft();
3329             }
3330             else {
3331                 hasClip = false;
3332                 top = right = bottom = left = Length();
3333             }
3334         } else if (isInitial) {
3335             hasClip = false;
3336             top = right = bottom = left = Length();
3337         } else if (!primitiveValue) {
3338             return;
3339         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
3340             Rect* rect = primitiveValue->getRectValue();
3341             if (!rect)
3342                 return;
3343             top = convertToLength(rect->top(), m_style);
3344             right = convertToLength(rect->right(), m_style);
3345             bottom = convertToLength(rect->bottom(), m_style);
3346             left = convertToLength(rect->left(), m_style);
3347
3348         } else if (primitiveValue->getIdent() != CSSValueAuto) {
3349             return;
3350         }
3351         m_style->setClip(top, right, bottom, left);
3352         m_style->setHasClip(hasClip);
3353     
3354         // rect, ident
3355         return;
3356     }
3357
3358 // lists
3359     case CSSPropertyContent:
3360         // list of string, uri, counter, attr, i
3361     {
3362         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
3363         // note is a reminder that eventually "inherit" needs to be supported.
3364
3365         if (isInitial) {
3366             m_style->clearContent();
3367             return;
3368         }
3369         
3370         if (!value->isValueList())
3371             return;
3372
3373         CSSValueList* list = static_cast<CSSValueList*>(value);
3374         int len = list->length();
3375
3376         bool didSet = false;
3377         for (int i = 0; i < len; i++) {
3378             CSSValue* item = list->itemWithoutBoundsCheck(i);
3379             if (item->isImageGeneratorValue()) {
3380                 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
3381                 didSet = true;
3382             }
3383             
3384             if (!item->isPrimitiveValue())
3385                 continue;
3386             
3387             CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item);
3388             switch (val->primitiveType()) {
3389                 case CSSPrimitiveValue::CSS_STRING:
3390                     m_style->setContent(val->getStringValue().impl(), didSet);
3391                     didSet = true;
3392                     break;
3393                 case CSSPrimitiveValue::CSS_ATTR: {
3394                     // FIXME: Can a namespace be specified for an attr(foo)?
3395                     if (m_style->styleType() == RenderStyle::NOPSEUDO)
3396                         m_style->setUnique();
3397                     else
3398                         m_parentStyle->setUnique();
3399                     QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
3400                     m_style->setContent(m_element->getAttribute(attr).impl(), didSet);
3401                     didSet = true;
3402                     // register the fact that the attribute value affects the style
3403                     m_selectorAttrs.add(attr.localName().impl());
3404                     break;
3405                 }
3406                 case CSSPrimitiveValue::CSS_URI: {
3407                     CSSImageValue* image = static_cast<CSSImageValue*>(val);
3408                     m_style->setContent(image->cachedImage(m_element->document()->docLoader()), didSet);
3409                     didSet = true;
3410                     break;
3411                 }
3412                 case CSSPrimitiveValue::CSS_COUNTER: {
3413                     Counter* counterValue = val->getCounterValue();
3414                     CounterContent* counter = new CounterContent(counterValue->identifier(),
3415                         (EListStyleType)counterValue->listStyleNumber(), counterValue->separator());
3416                     m_style->setContent(counter, didSet);
3417                     didSet = true;
3418                 }
3419             }
3420         }
3421         if (!didSet)
3422             m_style->clearContent();
3423         return;
3424     }
3425
3426     case CSSPropertyCounterIncrement:
3427         applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false);
3428         return;
3429     case CSSPropertyCounterReset:
3430         applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true);
3431         return;
3432
3433     case CSSPropertyFontFamily: {
3434         // list of strings and ids
3435         if (isInherit) {
3436             FontDescription parentFontDescription = m_parentStyle->fontDescription();
3437             FontDescription fontDescription = m_style->fontDescription();
3438             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3439             fontDescription.setFamily(parentFontDescription.firstFamily());
3440             if (m_style->setFontDescription(fontDescription))
3441                 m_fontDirty = true;
3442             return;
3443         }
3444         else if (isInitial) {
3445             FontDescription initialDesc = FontDescription();
3446             FontDescription fontDescription = m_style->fontDescription();
3447             // We need to adjust the size to account for the generic family change from monospace
3448             // to non-monospace.
3449             if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily)
3450                 setFontSize(fontDescription, fontSizeForKeyword(CSSValueXxSmall + fontDescription.keywordSize() - 1, m_style->htmlHacks(), false));
3451             fontDescription.setGenericFamily(initialDesc.genericFamily());
3452             fontDescription.setFamily(initialDesc.firstFamily());
3453             if (m_style->setFontDescription(fontDescription))
3454                 m_fontDirty = true;
3455             return;
3456         }
3457         
3458         if (!value->isValueList()) return;
3459         FontDescription fontDescription = m_style->fontDescription();
3460         CSSValueList *list = static_cast<CSSValueList*>(value);
3461         int len = list->length();
3462         FontFamily& firstFamily = fontDescription.firstFamily();
3463         FontFamily *currFamily = 0;
3464         
3465         // Before mapping in a new font-family property, we should reset the generic family.
3466         bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
3467         fontDescription.setGenericFamily(FontDescription::NoFamily);
3468
3469         for (int i = 0; i < len; i++) {
3470             CSSValue *item = list->itemWithoutBoundsCheck(i);
3471             if (!item->isPrimitiveValue()) continue;
3472             CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
3473             AtomicString face;
3474             Settings* settings = m_document->settings();
3475             if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
3476                 face = static_cast<FontFamilyValue*>(val)->familyName();
3477             else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
3478                 switch (val->getIdent()) {
3479                     case CSSValueWebkitBody:
3480                         face = settings->standardFontFamily();
3481                         break;
3482                     case CSSValueSerif:
3483                         face = "-webkit-serif";
3484                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
3485                         break;
3486                     case CSSValueSansSerif:
3487                         face = "-webkit-sans-serif";
3488                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3489                         break;
3490                     case CSSValueCursive:
3491                         face = "-webkit-cursive";
3492                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3493                         break;
3494                     case CSSValueFantasy:
3495                         face = "-webkit-fantasy";
3496                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3497                         break;
3498                     case CSSValueMonospace:
3499                         face = "-webkit-monospace";
3500                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3501                         break;
3502                 }
3503             }
3504     
3505             if (!face.isEmpty()) {
3506                 if (!currFamily) {
3507                     // Filling in the first family.
3508                     firstFamily.setFamily(face);
3509                     currFamily = &firstFamily;
3510                 }
3511                 else {
3512                     FontFamily *newFamily = new FontFamily;
3513                     newFamily->setFamily(face);
3514                     currFamily->appendFamily(newFamily);
3515                     currFamily = newFamily;
3516                 }
3517     
3518                 if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace)
3519                     setFontSize(fontDescription, fontSizeForKeyword(CSSValueXxSmall + fontDescription.keywordSize() - 1, m_style->htmlHacks(), !oldFamilyIsMonospace));
3520             
3521                 if (m_style->setFontDescription(fontDescription))
3522                     m_fontDirty = true;
3523             }
3524         }
3525       return;
3526     }
3527     case CSSPropertyTextDecoration: {
3528         // list of ident
3529         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3530         int t = RenderStyle::initialTextDecoration();
3531         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3532             // do nothing
3533         } else {
3534             if (!value->isValueList()) return;
3535             CSSValueList *list = static_cast<CSSValueList*>(value);
3536             int len = list->length();
3537             for (int i = 0; i < len; i++)
3538             {
3539                 CSSValue *item = list->itemWithoutBoundsCheck(i);
3540                 if (!item->isPrimitiveValue()) continue;
3541                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3542                 switch (primitiveValue->getIdent()) {
3543                     case CSSValueNone:
3544                         t = TDNONE; break;
3545                     case CSSValueUnderline:
3546                         t |= UNDERLINE; break;
3547                     case CSSValueOverline:
3548                         t |= OVERLINE; break;
3549                     case CSSValueLineThrough:
3550                         t |= LINE_THROUGH; break;
3551                     case CSSValueBlink:
3552                         t |= BLINK; break;
3553                     default:
3554                         return;
3555                 }
3556             }
3557         }
3558
3559         m_style->setTextDecoration(t);
3560         return;
3561     }
3562
3563     case CSSPropertyZoom:
3564     {
3565         // Reset the zoom in effect before we do anything.  This allows the setZoom method to accurately compute a new
3566         // zoom in effect.
3567         m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
3568         
3569         // Now we can handle inherit and initial.
3570         HANDLE_INHERIT_AND_INITIAL(zoom, Zoom)
3571         
3572         // Handle normal/reset, numbers and percentages.
3573         int type = primitiveValue->primitiveType();
3574         if (primitiveValue->getIdent() == CSSValueNormal)
3575             m_style->setZoom(RenderStyle::initialZoom());
3576         else if (primitiveValue->getIdent() == CSSValueReset) {
3577             m_style->setEffectiveZoom(RenderStyle::initialZoom());
3578             m_style->setZoom(RenderStyle::initialZoom());
3579         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
3580             if (primitiveValue->getFloatValue())
3581                 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f);
3582         } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
3583             if (primitiveValue->getFloatValue())
3584                 m_style->setZoom(primitiveValue->getFloatValue());
3585         }
3586         
3587         m_fontDirty = true;
3588         return;
3589     }
3590 // shorthand properties
3591     case CSSPropertyBackground:
3592         if (isInitial) {
3593             m_style->clearBackgroundLayers();
3594             m_style->setBackgroundColor(Color());
3595             return;
3596         }
3597         else if (isInherit) {
3598             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3599             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3600         }
3601         return;
3602     case CSSPropertyBorder:
3603     case CSSPropertyBorderStyle:
3604     case CSSPropertyBorderWidth:
3605     case CSSPropertyBorderColor:
3606         if (id == CSSPropertyBorder || id == CSSPropertyBorderColor)
3607         {
3608             if (isInherit) {
3609                 m_style->setBorderTopColor(m_parentStyle->borderTopColor());
3610                 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor());
3611                 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor());
3612                 m_style->setBorderRightColor(m_parentStyle->borderRightColor());
3613             }
3614             else if (isInitial) {
3615                 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
3616                 m_style->setBorderBottomColor(Color());
3617                 m_style->setBorderLeftColor(Color());
3618                 m_style->setBorderRightColor(Color());
3619             }
3620         }
3621         if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle)
3622         {
3623             if (isInherit) {
3624                 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
3625                 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
3626                 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
3627                 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
3628             }
3629             else if (isInitial) {
3630                 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle());
3631                 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
3632                 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
3633                 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle());
3634             }
3635         }
3636         if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth)
3637         {
3638             if (isInherit) {
3639                 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
3640                 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
3641                 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
3642                 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
3643             }
3644             else if (isInitial) {
3645                 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth());
3646                 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
3647                 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
3648                 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth());
3649             }
3650         }
3651         return;
3652     case CSSPropertyBorderTop:
3653         if (isInherit) {
3654             m_style->setBorderTopColor(m_parentStyle->borderTopColor());
3655             m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
3656             m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
3657         }
3658         else if (isInitial)
3659             m_style->resetBorderTop();
3660         return;
3661     case CSSPropertyBorderRight:
3662         if (isInherit) {
3663             m_style->setBorderRightColor(m_parentStyle->borderRightColor());
3664             m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
3665             m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
3666         }
3667         else if (isInitial)
3668             m_style->resetBorderRight();
3669         return;
3670     case CSSPropertyBorderBottom:
3671         if (isInherit) {
3672             m_style->setBorderBottomColor(m_parentStyle->borderBottomColor());
3673             m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
3674             m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
3675         }
3676         else if (isInitial)
3677             m_style->resetBorderBottom();
3678         return;
3679     case CSSPropertyBorderLeft:
3680         if (isInherit) {
3681             m_style->setBorderLeftColor(m_parentStyle->borderLeftColor());
3682             m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
3683             m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
3684         }
3685         else if (isInitial)
3686             m_style->resetBorderLeft();
3687         return;
3688     case CSSPropertyMargin:
3689         if (isInherit) {
3690             m_style->setMarginTop(m_parentStyle->marginTop());
3691             m_style->setMarginBottom(m_parentStyle->marginBottom());
3692             m_style->setMarginLeft(m_parentStyle->marginLeft());
3693             m_style->setMarginRight(m_parentStyle->marginRight());
3694         }
3695         else if (isInitial)
3696             m_style->resetMargin();
3697         return;
3698     case CSSPropertyPadding:
3699         if (isInherit) {
3700             m_style->setPaddingTop(m_parentStyle->paddingTop());
3701             m_style->setPaddingBottom(m_parentStyle->paddingBottom());
3702             m_style->setPaddingLeft(m_parentStyle->paddingLeft());
3703             m_style->setPaddingRight(m_parentStyle->paddingRight());
3704         }
3705         else if (isInitial)
3706             m_style->resetPadding();
3707         return;
3708     case CSSPropertyFont:
3709         if (isInherit) {
3710             FontDescription fontDescription = m_parentStyle->fontDescription();
3711             m_style->setLineHeight(m_parentStyle->lineHeight());
3712             m_lineHeightValue = 0;
3713             if (m_style->setFontDescription(fontDescription))
3714                 m_fontDirty = true;
3715         } else if (isInitial) {
3716             Settings* settings = m_document->settings();
3717             FontDescription fontDescription;
3718             fontDescription.setGenericFamily(FontDescription::StandardFamily);
3719             fontDescription.setRenderingMode(settings->fontRenderingMode());
3720             fontDescription.setUsePrinterFont(m_document->printing());
3721             const AtomicString& standardFontFamily = m_document->settings()->standardFontFamily();
3722             if (!standardFontFamily.isEmpty()) {
3723                 fontDescription.firstFamily().setFamily(standardFontFamily);
3724                 fontDescription.firstFamily().appendFamily(0);