2 * This file is part of the CSS implementation for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2004 Apple Computer, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include "css/cssstyleselector.h"
24 #include "rendering/render_style.h"
25 #include "css/css_stylesheetimpl.h"
26 #include "css/css_ruleimpl.h"
27 #include "css/css_valueimpl.h"
28 #include "css/csshelper.h"
29 #include "rendering/render_object.h"
30 #include "html/html_documentimpl.h"
31 #include "html/html_elementimpl.h"
32 #include "xml/dom_elementimpl.h"
33 #include "dom/css_rule.h"
34 #include "dom/css_value.h"
35 #include "khtml_factory.h"
36 #include "khtmlpart_p.h"
37 using namespace khtml;
40 #include "css/cssproperties.h"
41 #include "css/cssvalues.h"
43 #include "misc/khtmllayout.h"
44 #include "khtml_settings.h"
45 #include "misc/htmlhashes.h"
46 #include "misc/helper.h"
47 #include "misc/loader.h"
49 #include "rendering/font.h"
51 #include "khtmlview.h"
52 #include "khtml_part.h"
54 #include <kstandarddirs.h>
55 #include <kcharsets.h>
58 #include <qfontdatabase.h>
59 #include <qfontinfo.h>
60 #include <qvaluelist.h>
64 #include <qdatetime.h>
66 #include <qpaintdevicemetrics.h>
67 #include <qintcache.h>
70 // #define STYLE_SHARING_STATS 1
72 #define HANDLE_INHERIT(prop, Prop) \
75 style->set##Prop(parentStyle->prop());\
79 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
80 HANDLE_INHERIT(prop, Prop) \
83 style->set##Prop(RenderStyle::initial##Prop());\
87 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
88 HANDLE_INHERIT(prop, Prop) \
91 style->set##Prop(RenderStyle::initial##Value());\
95 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
97 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
98 BackgroundLayer* prevChild = 0; \
99 const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
100 while (currParent && currParent->is##Prop##Set()) { \
102 /* Need to make a new layer.*/ \
103 currChild = new BackgroundLayer(); \
104 prevChild->setNext(currChild); \
106 currChild->set##Prop(currParent->prop()); \
107 prevChild = currChild; \
108 currChild = prevChild->next(); \
109 currParent = currParent->next(); \
112 while (currChild) { \
113 /* Reset any remaining layers to not have the property set. */ \
114 currChild->clear##Prop(); \
115 currChild = currChild->next(); \
120 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
121 currChild->set##Prop(RenderStyle::initial##Prop()); \
122 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
123 currChild->clear##Prop(); \
127 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
128 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
129 if (!value->isPrimitiveValue() && !value->isValueList()) \
131 BackgroundLayer* currChild = style->accessBackgroundLayers(); \
132 BackgroundLayer* prevChild = 0; \
133 if (value->isPrimitiveValue()) { \
134 map##Prop(currChild, value); \
135 currChild = currChild->next(); \
138 /* Walk each value and put it into a layer, creating new layers as needed. */ \
139 CSSValueListImpl* valueList = static_cast<CSSValueListImpl*>(value); \
140 for (unsigned int i = 0; i < valueList->length(); i++) { \
142 /* Need to make a new layer to hold this value */ \
143 currChild = new BackgroundLayer(); \
144 prevChild->setNext(currChild); \
146 map##Prop(currChild, valueList->item(i)); \
147 prevChild = currChild; \
148 currChild = currChild->next(); \
151 while (currChild) { \
152 /* Reset all remaining layers to not have the property set. */ \
153 currChild->clear##Prop(); \
154 currChild = currChild->next(); \
157 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
160 style->set##Prop(parentStyle->prop());\
164 #define HANDLE_INITIAL_COND(propID, Prop) \
167 style->set##Prop(RenderStyle::initial##Prop());\
171 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
174 style->set##Prop(RenderStyle::initial##Value());\
180 CSSRuleSet *CSSStyleSelector::defaultStyle = 0;
181 CSSRuleSet *CSSStyleSelector::defaultQuirksStyle = 0;
182 CSSRuleSet *CSSStyleSelector::defaultPrintStyle = 0;
183 CSSStyleSheetImpl *CSSStyleSelector::defaultSheet = 0;
184 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0;
185 CSSStyleSheetImpl *CSSStyleSelector::quirksSheet = 0;
187 static CSSStyleSelector::Encodedurl *encodedurl = 0;
188 static PseudoState pseudoState;
190 CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets,
191 bool _strictParsing )
196 strictParsing = _strictParsing;
197 settings = view ? view->part()->settings() : 0;
198 if(!defaultStyle) loadDefaultStyle(settings);
199 m_medium = view ? view->mediaType() : QString("all");
203 paintDeviceMetrics = doc->paintDeviceMetrics();
205 // FIXME: This sucks! The user sheet is reparsed every time!
206 if (!userStyleSheet.isEmpty()) {
207 m_userSheet = new DOM::CSSStyleSheetImpl(doc);
208 m_userSheet->parseString(DOMString(userStyleSheet), strictParsing);
210 m_userStyle = new CSSRuleSet();
211 m_userStyle->addRulesFromSheet( m_userSheet, m_medium );
214 // add stylesheets from document
215 m_authorStyle = new CSSRuleSet();
217 QPtrListIterator<StyleSheetImpl> it(styleSheets->styleSheets);
218 for (; it.current(); ++it)
219 if (it.current()->isCSSStyleSheet())
220 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheetImpl*>(it.current()), m_medium);
222 //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl;
223 //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl;
226 CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet )
230 if(!defaultStyle) loadDefaultStyle();
231 KHTMLView *view = sheet->doc()->view();
232 m_medium = view ? view->mediaType() : QString("all");
234 m_authorStyle = new CSSRuleSet();
235 m_authorStyle->addRulesFromSheet( sheet, m_medium );
238 void CSSStyleSelector::init()
242 paintDeviceMetrics = 0;
243 m_matchedRuleCount = m_matchedDeclCount = m_tmpRuleCount = 0;
246 void CSSStyleSelector::setEncodedURL(const KURL& url)
250 u.setQuery( QString::null );
251 u.setRef( QString::null );
252 encodedurl.file = u.url();
253 int pos = encodedurl.file.findRev('/');
254 encodedurl.path = encodedurl.file;
256 encodedurl.path.truncate( pos );
257 encodedurl.path += '/';
259 u.setPath( QString::null );
260 encodedurl.host = u.url();
262 //kdDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path << endl;
265 CSSStyleSelector::~CSSStyleSelector()
267 delete m_authorStyle;
272 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s)
274 if(defaultStyle) return;
277 QFile f(locate( "data", "khtml/css/html4.css" ) );
280 QCString file( f.size()+1 );
281 int readbytes = f.readBlock( file.data(), f.size() );
283 if ( readbytes >= 0 )
284 file[readbytes] = '\0';
286 QString style = QString::fromLatin1( file.data() );
288 style += s->settingsToCSS();
289 DOMString str(style);
291 defaultSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0);
292 defaultSheet->parseString( str );
294 // Collect only strict-mode rules.
295 defaultStyle = new CSSRuleSet();
296 defaultStyle->addRulesFromSheet( defaultSheet, "screen" );
298 defaultPrintStyle = new CSSRuleSet();
299 defaultPrintStyle->addRulesFromSheet( defaultSheet, "print" );
302 QFile f(locate( "data", "khtml/css/quirks.css" ) );
305 QCString file( f.size()+1 );
306 int readbytes = f.readBlock( file.data(), f.size() );
308 if ( readbytes >= 0 )
309 file[readbytes] = '\0';
311 QString style = QString::fromLatin1( file.data() );
312 DOMString str(style);
314 quirksSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0);
315 quirksSheet->parseString( str );
317 // Collect only quirks-mode rules.
318 defaultQuirksStyle = new CSSRuleSet();
319 defaultQuirksStyle->addRulesFromSheet( quirksSheet, "screen" );
322 //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl;
325 void CSSStyleSelector::addMatchedRule(CSSRuleData* rule)
327 if (m_matchedRules.size() <= m_matchedRuleCount)
328 m_matchedRules.resize(2*m_matchedRules.size()+1);
329 m_matchedRules[m_matchedRuleCount++] = rule;
332 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclarationImpl* decl)
334 if (m_matchedDecls.size() <= m_matchedDeclCount)
335 m_matchedDecls.resize(2*m_matchedDecls.size()+1);
336 m_matchedDecls[m_matchedDeclCount++] = decl;
339 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
341 m_matchedRuleCount = 0;
342 firstRuleIndex = lastRuleIndex = -1;
343 if (!rules || !element) return;
345 // We need to collect the rules for id, class, tag, and everything else into a buffer and
346 // then sort the buffer.
347 if (element->hasID())
348 matchRulesForList(rules->getIDRules(element->getIDAttribute().implementation()),
349 firstRuleIndex, lastRuleIndex);
350 if (element->hasClass()) {
351 for (const AtomicStringList* singleClass = element->getClassList();
352 singleClass; singleClass = singleClass->next())
353 matchRulesForList(rules->getClassRules(singleClass->string().implementation()),
354 firstRuleIndex, lastRuleIndex);
356 matchRulesForList(rules->getTagRules((void*)(int)localNamePart(element->id())),
357 firstRuleIndex, lastRuleIndex);
358 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
360 // If we didn't match any rules, we're done.
361 if (m_matchedRuleCount == 0) return;
363 // Sort the set of matched rules.
364 sortMatchedRules(0, m_matchedRuleCount);
366 // Now transfer the set of matched rules over to our list of decls.
367 for (unsigned i = 0; i < m_matchedRuleCount; i++)
368 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
371 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules,
372 int& firstRuleIndex, int& lastRuleIndex)
375 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
376 CSSStyleRuleImpl* rule = d->rule();
377 Q_UINT16 cssTagId = localNamePart(element->id());
378 Q_UINT16 tag = localNamePart(d->selector()->tag);
379 if ((cssTagId == tag || tag == anyLocalName) && checkSelector(d->selector(), element)) {
380 // If the rule has no properties to apply, then ignore it.
381 CSSMutableStyleDeclarationImpl* decl = rule->declaration();
382 if (!decl || !decl->length()) continue;
384 // If we're matching normal rules, set a pseudo bit if
385 // we really just matched a pseudo-element.
386 if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO)
387 style->setHasPseudoStyle(dynamicPseudo);
389 // Update our first/last rule indices in the matched rules array.
390 lastRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
391 if (firstRuleIndex == -1) firstRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
393 // Add this rule to our list of matched rules.
400 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
402 int spec1 = r1.selector()->specificity();
403 int spec2 = r2.selector()->specificity();
404 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
406 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
411 void CSSStyleSelector::sortMatchedRules(uint start, uint end)
413 if (start >= end || (end-start == 1))
414 return; // Sanity check.
416 if (end - start <= 6) {
417 // Apply a bubble sort for smaller lists.
418 for (uint i = end-1; i > start; i--) {
420 for (uint j = start; j < i; j++) {
421 CSSRuleData* elt = m_matchedRules[j];
422 CSSRuleData* elt2 = m_matchedRules[j+1];
425 m_matchedRules[j] = elt2;
426 m_matchedRules[j+1] = elt;
434 // Peform a merge sort for larger lists.
435 uint mid = (start+end)/2;
436 sortMatchedRules(start, mid);
437 sortMatchedRules(mid, end);
439 CSSRuleData* elt = m_matchedRules[mid-1];
440 CSSRuleData* elt2 = m_matchedRules[mid];
442 // Handle the fast common case (of equal specificity). The list may already
443 // be completely sorted.
447 // We have to merge sort. Ensure our merge buffer is big enough to hold
449 m_tmpRules.resize(end - start);
453 elt = m_matchedRules[i1];
454 elt2 = m_matchedRules[i2];
456 while (i1 < mid || i2 < end) {
457 if (i1 < mid && (i2 == end || *elt <= *elt2)) {
458 m_tmpRules[m_tmpRuleCount++] = elt;
461 elt = m_matchedRules[i1];
464 m_tmpRules[m_tmpRuleCount++] = elt2;
467 elt2 = m_matchedRules[i2];
471 for (uint i = start; i < end; i++)
472 m_matchedRules[i] = m_tmpRules[i-start];
478 void CSSStyleSelector::initElementAndPseudoState(ElementImpl* e)
481 if (element && element->isHTMLElement())
482 htmlElement = static_cast<HTMLElementImpl*>(element);
485 ::encodedurl = &encodedurl;
486 pseudoState = PseudoUnknown;
489 void CSSStyleSelector::initForStyleResolve(ElementImpl* e, RenderStyle* defaultParent)
491 // set some variables we will need
492 pseudoStyle = RenderStyle::NOPSEUDO;
494 parentNode = e->parentNode();
496 parentStyle = defaultParent;
498 parentStyle = (parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
499 view = element->getDocument()->view();
500 isXMLDoc = !element->getDocument()->isHTMLDocument();
501 part = element->getDocument()->part();
502 settings = part ? part->settings() : 0;
503 paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
507 m_matchedRuleCount = 0;
508 m_matchedDeclCount = 0;
514 // modified version of the one in kurl.cpp
515 static void cleanpath(QString &path)
518 while ( (pos = path.find( "/../" )) != -1 ) {
521 prev = path.findRev( "/", pos -1 );
522 // don't remove the host, i.e. http://foo.org/../foo.html
523 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
524 path.remove( pos, 3);
526 // matching directory found ?
527 path.remove( prev, pos- prev + 3 );
531 // Don't remove "//" from an anchor identifier. -rjw
532 // Set refPos to -2 to mean "I haven't looked for the anchor yet".
533 // We don't want to waste a function call on the search for the the anchor
534 // in the vast majority of cases where there is no "//" in the path.
536 while ( (pos = path.find( "//", pos )) != -1) {
538 refPos = path.find("#", 0);
539 if (refPos > 0 && pos >= refPos)
542 if ( pos == 0 || path[pos-1] != ':' )
543 path.remove( pos, 1 );
547 while ( (pos = path.find( "/./" )) != -1)
548 path.remove( pos, 2 );
549 //kdDebug() << "checkPseudoState " << path << endl;
552 static void checkPseudoState( DOM::ElementImpl *e, bool checkVisited = true )
555 pseudoState = PseudoNone;
559 const AtomicString& attr = e->getAttribute(ATTR_HREF);
561 pseudoState = PseudoNone;
566 pseudoState = PseudoAnyLink;
570 QConstString cu(attr.unicode(), attr.length());
571 QString u = cu.string();
572 if ( !u.contains("://") ) {
574 u.prepend(encodedurl->host);
575 else if ( u[0] == '#' )
576 u.prepend(encodedurl->file);
578 u.prepend(encodedurl->path);
581 //completeURL( attr.string() );
582 pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;
585 #ifdef STYLE_SHARING_STATS
586 static int fraction = 0;
587 static int total = 0;
590 const int siblingThreshold = 10;
592 NodeImpl* CSSStyleSelector::locateCousinList(ElementImpl* parent)
594 if (parent && parent->isHTMLElement()) {
595 HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parent);
596 if (p->renderer() && !p->inlineStyleDecl() && !p->hasID()) {
597 DOM::NodeImpl* r = p->previousSibling();
599 RenderStyle* st = p->renderer()->style();
601 if (r->renderer() && r->renderer()->style() == st)
602 return r->lastChild();
603 if (subcount++ == siblingThreshold)
605 r = r->previousSibling();
608 r = locateCousinList(static_cast<ElementImpl*>(parent->parentNode()));
610 if (r->renderer() && r->renderer()->style() == st)
611 return r->lastChild();
612 if (subcount++ == siblingThreshold)
614 r = r->previousSibling();
621 bool CSSStyleSelector::canShareStyleWithElement(NodeImpl* n)
623 if (n->isHTMLElement()) {
624 bool mouseInside = element->renderer() ? element->renderer()->mouseInside() : false;
625 HTMLElementImpl* s = static_cast<HTMLElementImpl*>(n);
626 if (s->renderer() && (s->id() == element->id()) && !s->hasID() &&
627 (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
628 (s->hasMappedAttributes() == htmlElement->hasMappedAttributes()) &&
629 (s->isLink() == element->isLink()) &&
630 !s->renderer()->style()->affectedByAttributeSelectors() &&
631 (s->renderer()->mouseInside() == mouseInside) &&
632 (s->active() == element->active()) &&
633 (s->focused() == element->focused())) {
634 bool classesMatch = true;
636 const AtomicString& class1 = element->getAttribute(ATTR_CLASS);
637 const AtomicString& class2 = s->getAttribute(ATTR_CLASS);
638 classesMatch = (class1 == class2);
642 bool mappedAttrsMatch = true;
643 if (s->hasMappedAttributes())
644 mappedAttrsMatch = s->htmlAttributes()->mapsEquivalent(htmlElement->htmlAttributes());
645 if (mappedAttrsMatch) {
646 bool linksMatch = true;
648 // We need to check to see if the visited state matches.
649 QColor linkColor = element->getDocument()->linkColor();
650 QColor visitedColor = element->getDocument()->visitedLinkColor();
651 if (pseudoState == PseudoUnknown)
652 checkPseudoState(element, s->renderer()->style()->pseudoState() != PseudoAnyLink ||
653 linkColor != visitedColor);
654 linksMatch = (pseudoState == s->renderer()->style()->pseudoState());
666 RenderStyle* CSSStyleSelector::locateSharedStyle()
668 if (htmlElement && !htmlElement->inlineStyleDecl() && !htmlElement->hasID() &&
669 !htmlElement->getDocument()->usesSiblingRules()) {
670 // Check previous siblings.
673 for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
675 if (canShareStyleWithElement(n))
676 return n->renderer()->style();
677 if (count++ == siblingThreshold)
679 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
682 n = locateCousinList(static_cast<ElementImpl*>(element->parentNode()));
684 if (canShareStyleWithElement(n))
685 return n->renderer()->style();
686 if (count++ == siblingThreshold)
688 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
695 RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent, bool allowSharing)
697 if (!e->getDocument()->haveStylesheetsLoaded()) {
698 if (!styleNotYetAvailable) {
699 styleNotYetAvailable = ::new RenderStyle();
700 styleNotYetAvailable->setDisplay(NONE);
701 styleNotYetAvailable->ref();
703 return styleNotYetAvailable;
706 initElementAndPseudoState(e);
708 style = locateSharedStyle();
709 #ifdef STYLE_SHARING_STATS
710 fraction += style != 0;
712 printf("Sharing %d out of %d\n", fraction, total);
717 initForStyleResolve(e, defaultParent);
719 style = new (e->getDocument()->renderArena()) RenderStyle();
721 style->inheritFrom(parentStyle);
725 // 1. First we match rules from the user agent sheet.
726 int firstUARule = -1, lastUARule = -1;
727 matchRules(defaultStyle, firstUARule, lastUARule);
729 // 2. In quirks mode, we match rules from the quirks user agent sheet.
731 matchRules(defaultQuirksStyle, firstUARule, lastUARule);
733 // 3. If our medium is print, then we match rules from the print sheet.
734 if (m_medium == "print")
735 matchRules(defaultPrintStyle, firstUARule, lastUARule);
737 // 4. Now we check user sheet rules.
738 int firstUserRule = -1, lastUserRule = -1;
739 matchRules(m_userStyle, firstUserRule, lastUserRule);
741 // 5. Now check author rules, beginning first with presentational attributes
743 int firstAuthorRule = -1, lastAuthorRule = -1;
745 // Ask if the HTML element has mapped attributes.
746 if (htmlElement->hasMappedAttributes()) {
747 // Walk our attribute list and add in each decl.
748 const HTMLNamedAttrMapImpl* map = htmlElement->htmlAttributes();
749 for (uint i = 0; i < map->length(); i++) {
750 HTMLAttributeImpl* attr = map->attributeItem(i);
752 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
753 lastAuthorRule = m_matchedDeclCount;
754 addMatchedDeclaration(attr->decl());
759 // Now we check additional mapped declarations.
760 // Tables and table cells share an additional mapped rule that must be applied
761 // after all attributes, since their mapped style depends on the values of multiple attributes.
762 CSSMutableStyleDeclarationImpl* attributeDecl = htmlElement->additionalAttributeStyleDecl();
764 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
765 lastAuthorRule = m_matchedDeclCount;
766 addMatchedDeclaration(attributeDecl);
770 // 6. Check the rules in author sheets next.
771 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
773 // 7. Now check our inline style attribute.
775 CSSMutableStyleDeclarationImpl* inlineDecl = htmlElement->inlineStyleDecl();
777 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
778 lastAuthorRule = m_matchedDeclCount;
779 addMatchedDeclaration(inlineDecl);
783 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
784 // high-priority properties first, i.e., those properties that other properties depend on.
785 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
786 // and (4) normal important.
787 applyDeclarations(true, false, 0, m_matchedDeclCount-1);
788 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
789 applyDeclarations(true, true, firstUserRule, lastUserRule);
790 applyDeclarations(true, true, firstUARule, lastUARule);
792 // If our font got dirtied, go ahead and update it now.
794 checkForTextSizeAdjust();
795 checkForGenericFamilyChange(style, parentStyle);
796 style->htmlFont().update(paintDeviceMetrics);
800 // Now do the normal priority properties.
801 applyDeclarations(false, false, 0, m_matchedDeclCount-1);
802 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
803 applyDeclarations(false, true, firstUserRule, lastUserRule);
804 applyDeclarations(false, true, firstUARule, lastUARule);
806 // If our font got dirtied by one of the non-essential font props,
807 // go ahead and update it a second time.
809 checkForTextSizeAdjust();
810 checkForGenericFamilyChange(style, parentStyle);
811 style->htmlFont().update(paintDeviceMetrics);
815 // Clean up our style object's display and text decorations (among other fixups).
816 adjustRenderStyle(style, e);
818 // If we are a link, cache the determined pseudo-state.
820 style->setPseudoState(pseudoState);
822 // Now return the style.
826 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo,
827 ElementImpl* e, RenderStyle* parentStyle)
832 initElementAndPseudoState(e);
833 initForStyleResolve(e, parentStyle);
834 pseudoStyle = pseudo;
836 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
839 // Check UA, user and author rules.
840 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
841 matchRules(defaultStyle, firstUARule, lastUARule);
842 matchRules(m_userStyle, firstUserRule, lastUserRule);
843 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
845 if (m_matchedDeclCount == 0)
848 style = new (e->getDocument()->renderArena()) RenderStyle();
850 style->inheritFrom(parentStyle);
853 style->noninherited_flags._styleType = pseudoStyle;
855 // High-priority properties.
856 applyDeclarations(true, false, 0, m_matchedDeclCount-1);
857 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
858 applyDeclarations(true, true, firstUserRule, lastUserRule);
859 applyDeclarations(true, true, firstUARule, lastUARule);
861 // If our font got dirtied, go ahead and update it now.
863 checkForTextSizeAdjust();
864 checkForGenericFamilyChange(style, parentStyle);
865 style->htmlFont().update(paintDeviceMetrics);
869 // Now do the normal priority properties.
870 applyDeclarations(false, false, 0, m_matchedDeclCount-1);
871 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
872 applyDeclarations(false, true, firstUserRule, lastUserRule);
873 applyDeclarations(false, true, firstUARule, lastUARule);
875 // If our font got dirtied by one of the non-essential font props,
876 // go ahead and update it a second time.
878 checkForTextSizeAdjust();
879 checkForGenericFamilyChange(style, parentStyle);
880 style->htmlFont().update(paintDeviceMetrics);
884 // Clean up our style object's display and text decorations (among other fixups).
885 adjustRenderStyle(style, 0);
887 // Now return the style.
891 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
893 // Cache our original display.
894 style->setOriginalDisplay(style->display());
896 if (style->display() != NONE) {
897 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
899 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
900 // these tags to retain their display types.
901 if (!strictParsing && e) {
902 if (e->id() == ID_TD) {
903 style->setDisplay(TABLE_CELL);
904 style->setFloating(FNONE);
906 else if (e->id() == ID_TABLE)
907 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
910 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
911 // fix a crash where a site tries to position these objects. They also never honor display.
912 if (e && (e->id() == ID_FRAME || e->id() == ID_FRAMESET)) {
913 style->setPosition(STATIC);
914 style->setDisplay(BLOCK);
917 // Table headers with a text-align of auto will change the text-align to center.
918 if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
919 style->setTextAlign(CENTER);
921 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
922 // position or float an inline, compact, or run-in. Cache the original display, since it
923 // may be needed for positioned elements that have to compute their static normal flow
924 // positions. We also force inline-level roots to be block-level.
925 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
926 (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE ||
927 (e && e->getDocument()->documentElement() == e))) {
928 if (style->display() == INLINE_TABLE)
929 style->setDisplay(TABLE);
930 else if (style->display() == INLINE_BOX)
931 style->setDisplay(BOX);
932 else if (style->display() == LIST_ITEM) {
933 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
934 // but only in quirks mode.
935 if (!strictParsing && style->floating() != FNONE)
936 style->setDisplay(BLOCK);
939 style->setDisplay(BLOCK);
942 // After performing the display mutation, check table rows. We do not honor position:relative on
943 // table rows. This has been established in CSS2.1 (and caused a crash in containingBlock() on
945 if (style->display() == TABLE_ROW && style->position() == RELATIVE)
946 style->setPosition(STATIC);
949 // Make sure our z-index value is only applied if the object is positioned,
950 // relatively positioned, or transparent.
951 if (style->position() == STATIC && style->opacity() == 1.0f) {
952 if (e && e->getDocument()->documentElement() == e)
953 style->setZIndex(0); // The root has a z-index of 0 if not positioned or transparent.
955 style->setHasAutoZIndex(); // Everyone else gets an auto z-index.
958 // Auto z-index becomes 0 for transparent objects. This prevents cases where
959 // objects that should be blended as a single unit end up with a non-transparent object
960 // wedged in between them.
961 if (style->opacity() < 1.0f && style->hasAutoZIndex())
964 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
965 // tables, inline blocks, inline tables, or run-ins.
966 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
967 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
968 style->setTextDecorationsInEffect(style->textDecoration());
970 style->addToTextDecorationsInEffect(style->textDecoration());
972 // Cull out any useless layers and also repeat patterns into additional layers.
973 style->adjustBackgroundLayers();
975 // Only use slow repaints if we actually have a background image.
976 // FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to
977 // prevent the entire view from blitting on a scroll.
978 if (style->hasFixedBackgroundImage() && view)
979 view->useSlowRepaints();
984 bool CSSStyleSelector::checkSelector(CSSSelector* sel, ElementImpl *e)
986 dynamicPseudo = RenderStyle::NOPSEUDO;
990 // we have the subject part of the selector
993 // We track whether or not the rule contains only :hover and :active in a simple selector. If
994 // so, we can't allow that to apply to every element on the page. We assume the author intended
995 // to apply the rules only to links.
996 bool onlyHoverActive = (sel->tag == anyQName &&
997 (sel->match == CSSSelector::Pseudo &&
998 (sel->pseudoType() == CSSSelector::PseudoHover ||
999 sel->pseudoType() == CSSSelector::PseudoActive)));
1000 bool affectedByHover = style ? style->affectedByHoverRules() : false;
1001 bool affectedByActive = style ? style->affectedByActiveRules() : false;
1002 bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
1004 // first selector has to match
1005 if (!checkOneSelector(sel, e)) return false;
1007 // check the subselectors
1008 CSSSelector::Relation relation = sel->relation;
1009 while((sel = sel->tagHistory))
1011 if (!n->isElementNode()) return false;
1012 if (relation != CSSSelector::SubSelector) {
1014 if (havePseudo && dynamicPseudo != pseudoStyle)
1020 case CSSSelector::Descendant:
1022 // FIXME: This match needs to know how to backtrack and be non-deterministic.
1026 n = n->parentNode();
1027 if(!n || !n->isElementNode()) return false;
1028 ElementImpl *elem = static_cast<ElementImpl *>(n);
1029 if (checkOneSelector(sel, elem)) found = true;
1033 case CSSSelector::Child:
1035 n = n->parentNode();
1037 while (n && n->implicitNode()) n = n->parentNode();
1038 if(!n || !n->isElementNode()) return false;
1039 ElementImpl *elem = static_cast<ElementImpl *>(n);
1040 if (!checkOneSelector(sel, elem)) return false;
1043 case CSSSelector::Sibling:
1045 n = n->previousSibling();
1046 while( n && !n->isElementNode() )
1047 n = n->previousSibling();
1048 if( !n ) return false;
1049 ElementImpl *elem = static_cast<ElementImpl *>(n);
1050 if (!checkOneSelector(sel, elem)) return false;
1053 case CSSSelector::SubSelector:
1055 if (onlyHoverActive)
1056 onlyHoverActive = (sel->match == CSSSelector::Pseudo &&
1057 (sel->pseudoType() == CSSSelector::PseudoHover ||
1058 sel->pseudoType() == CSSSelector::PseudoActive));
1060 //kdDebug() << "CSSOrderedRule::checkSelector" << endl;
1061 ElementImpl *elem = static_cast<ElementImpl *>(n);
1062 // a selector is invalid if something follows :first-xxx
1063 if (dynamicPseudo != RenderStyle::NOPSEUDO)
1065 if (!checkOneSelector(sel, elem)) return false;
1066 //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl;
1070 relation = sel->relation;
1073 if (subject && havePseudo && dynamicPseudo != pseudoStyle)
1076 // disallow *:hover, *:active, and *:hover:active except for links
1077 if (onlyHoverActive && subject) {
1078 if (pseudoState == PseudoUnknown)
1079 checkPseudoState(e);
1081 if (pseudoState == PseudoNone) {
1082 if (!affectedByHover && style->affectedByHoverRules())
1083 style->setAffectedByHoverRules(false);
1084 if (!affectedByActive && style->affectedByActiveRules())
1085 style->setAffectedByActiveRules(false);
1093 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e)
1098 if (sel->tag != anyQName) {
1099 int eltID = e->id();
1100 Q_UINT16 localName = localNamePart(eltID);
1101 Q_UINT16 ns = namespacePart(eltID);
1102 Q_UINT16 selLocalName = localNamePart(sel->tag);
1103 Q_UINT16 selNS = namespacePart(sel->tag);
1105 if (localName <= ID_LAST_TAG && e->isHTMLElement())
1106 ns = xhtmlNamespace; // FIXME: Really want to move away from this complicated hackery and just
1107 // switch tags and attr names over to AtomicStrings.
1109 if ((selLocalName != anyLocalName && localName != selLocalName) ||
1110 (selNS != anyNamespace && ns != selNS))
1115 if (sel->match == CSSSelector::Class) {
1118 for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1119 if (c->string() == sel->value)
1123 else if (sel->match == CSSSelector::Id)
1124 return e->hasID() && e->getIDAttribute() == sel->value;
1125 else if (style && (e != element || !htmlElement || !htmlElement->isMappedAttribute(sel->attr)))
1126 style->setAffectedByAttributeSelectors();
1128 const AtomicString& value = e->getAttribute(sel->attr);
1129 if (value.isNull()) return false; // attribute is not set
1131 switch(sel->match) {
1132 case CSSSelector::Exact:
1133 if ((isXMLDoc && sel->value != value) ||
1134 (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1137 case CSSSelector::List:
1139 int spacePos = value.find(' ', 0);
1140 if (spacePos == -1) {
1141 // There is no list, just a single item. We can avoid
1142 // allocing QStrings and just treat this as an exact
1144 if ((isXMLDoc && sel->value != value) ||
1145 (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1150 // The selector's value can't contain a space, or it's totally bogus.
1151 spacePos = sel->value.find(' ');
1155 QString str = value.string();
1156 QString selStr = sel->value.string();
1157 int startSearchAt = 0;
1159 int foundPos = str.find(selStr, startSearchAt, isXMLDoc);
1160 if (foundPos == -1) return false;
1161 if (foundPos == 0 || str[foundPos-1] == ' ') {
1162 uint endStr = foundPos + selStr.length();
1163 if (endStr == str.length() || str[endStr] == ' ')
1164 break; // We found a match.
1167 // No match. Keep looking.
1168 startSearchAt = foundPos + 1;
1173 case CSSSelector::Contain:
1175 //kdDebug( 6080 ) << "checking for contains match" << endl;
1176 QString str = value.string();
1177 QString selStr = sel->value.string();
1178 int pos = str.find(selStr, 0, isXMLDoc);
1179 if(pos == -1) return false;
1182 case CSSSelector::Begin:
1184 //kdDebug( 6080 ) << "checking for beginswith match" << endl;
1185 QString str = value.string();
1186 QString selStr = sel->value.string();
1187 int pos = str.find(selStr, 0, isXMLDoc);
1188 if(pos != 0) return false;
1191 case CSSSelector::End:
1193 //kdDebug( 6080 ) << "checking for endswith match" << endl;
1194 QString str = value.string();
1195 QString selStr = sel->value.string();
1196 if (isXMLDoc && !str.endsWith(selStr)) return false;
1198 int pos = str.length() - selStr.length();
1199 if (pos < 0 || pos != str.find(selStr, pos, false) )
1204 case CSSSelector::Hyphen:
1206 //kdDebug( 6080 ) << "checking for hyphen match" << endl;
1207 QString str = value.string();
1208 QString selStr = sel->value.string();
1209 if(str.length() < selStr.length()) return false;
1210 // Check if str begins with selStr:
1211 if(str.find(selStr, 0, isXMLDoc) != 0) return false;
1212 // It does. Check for exact match or following '-':
1213 if(str.length() != selStr.length()
1214 && str[selStr.length()] != '-') return false;
1221 if(sel->match == CSSSelector::Pseudo)
1223 // Pseudo elements. We need to check first child here. No dynamic pseudo
1224 // elements for the moment
1225 // kdDebug() << "CSSOrderedRule::pseudo " << value << endl;
1226 switch (sel->pseudoType()) {
1227 case CSSSelector::PseudoEmpty:
1228 if (!e->firstChild())
1231 case CSSSelector::PseudoFirstChild: {
1232 // first-child matches the first child that is an element!
1233 if (e->parentNode()) {
1234 DOM::NodeImpl* n = e->previousSibling();
1235 while ( n && !n->isElementNode() )
1236 n = n->previousSibling();
1242 case CSSSelector::PseudoLastChild: {
1243 // last-child matches the last child that is an element!
1244 if (e->parentNode()) {
1245 DOM::NodeImpl* n = e->nextSibling();
1246 while ( n && !n->isElementNode() )
1247 n = n->nextSibling();
1253 case CSSSelector::PseudoOnlyChild: {
1254 // If both first-child and last-child apply, then only-child applies.
1255 if (e->parentNode()) {
1256 DOM::NodeImpl* n = e->previousSibling();
1257 while ( n && !n->isElementNode() )
1258 n = n->previousSibling();
1260 n = e->nextSibling();
1261 while ( n && !n->isElementNode() )
1262 n = n->nextSibling();
1269 case CSSSelector::PseudoFirstLine:
1271 dynamicPseudo=RenderStyle::FIRST_LINE;
1275 case CSSSelector::PseudoFirstLetter:
1277 dynamicPseudo=RenderStyle::FIRST_LETTER;
1281 case CSSSelector::PseudoTarget:
1282 if (e == e->getDocument()->getCSSTarget())
1285 case CSSSelector::PseudoAnyLink:
1286 if (pseudoState == PseudoUnknown)
1287 checkPseudoState(e, false);
1288 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1291 case CSSSelector::PseudoLink:
1292 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1293 checkPseudoState( e );
1294 if ( pseudoState == PseudoLink )
1297 case CSSSelector::PseudoVisited:
1298 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1299 checkPseudoState( e );
1300 if ( pseudoState == PseudoVisited )
1303 case CSSSelector::PseudoHover: {
1304 // If we're in quirks mode, then hover should never match anchors with no
1305 // href. This is important for sites like wsj.com.
1306 if (strictParsing || e->id() != ID_A || e->isLink()) {
1307 if (element == e && style)
1308 style->setAffectedByHoverRules(true);
1309 if (e->renderer()) {
1311 e->renderer()->style()->setAffectedByHoverRules(true);
1312 if (e->renderer()->mouseInside())
1318 case CSSSelector::PseudoDrag: {
1319 if (element == e && style)
1320 style->setAffectedByDragRules(true);
1321 if (e->renderer()) {
1323 e->renderer()->style()->setAffectedByDragRules(true);
1324 if (e->renderer()->isDragging())
1329 case CSSSelector::PseudoFocus:
1330 if (e && e->focused()) {
1334 case CSSSelector::PseudoActive:
1335 // If we're in quirks mode, then :active should never match anchors with no
1337 if (strictParsing || e->id() != ID_A || e->isLink()) {
1338 if (element == e && style)
1339 style->setAffectedByActiveRules(true);
1340 else if (e->renderer())
1341 e->renderer()->style()->setAffectedByActiveRules(true);
1346 case CSSSelector::PseudoRoot:
1347 if (e == e->getDocument()->documentElement())
1350 case CSSSelector::PseudoNot: {
1351 // check the simple selector
1352 for (CSSSelector* subSel = sel->simpleSelector; subSel;
1353 subSel = subSel->tagHistory) {
1354 // :not cannot nest. I don't really know why this is a restriction in CSS3,
1355 // but it is, so let's honor it.
1356 if (subSel->simpleSelector)
1358 if (!checkOneSelector(subSel, e))
1363 case CSSSelector::PseudoSelection:
1364 dynamicPseudo = RenderStyle::SELECTION;
1366 case CSSSelector::PseudoBefore:
1367 dynamicPseudo = RenderStyle::BEFORE;
1369 case CSSSelector::PseudoAfter:
1370 dynamicPseudo = RenderStyle::AFTER;
1373 case CSSSelector::PseudoNotParsed:
1376 case CSSSelector::PseudoLang:
1377 /* not supported for now */
1378 case CSSSelector::PseudoOther:
1383 // ### add the rest of the checks...
1387 // -----------------------------------------------------------------
1389 CSSRuleSet::CSSRuleSet()
1391 m_idRules.setAutoDelete(true);
1392 m_classRules.setAutoDelete(true);
1393 m_tagRules.setAutoDelete(true);
1394 m_universalRules = 0;
1398 void CSSRuleSet::addToRuleSet(void* hash, QPtrDict<CSSRuleDataList>& dict,
1399 CSSStyleRuleImpl* rule, CSSSelector* sel)
1402 CSSRuleDataList* rules = dict.find(hash);
1404 rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1405 dict.insert(hash, rules);
1408 rules->append(m_ruleCount++, rule, sel);
1411 void CSSRuleSet::addRule(CSSStyleRuleImpl* rule, CSSSelector* sel)
1413 if (sel->match == CSSSelector::Id) {
1414 addToRuleSet(sel->value.implementation(), m_idRules, rule, sel);
1417 if (sel->match == CSSSelector::Class) {
1418 addToRuleSet(sel->value.implementation(), m_classRules, rule, sel);
1422 Q_UINT16 localName = localNamePart(sel->tag);
1423 if (localName != anyLocalName) {
1424 addToRuleSet((void*)(int)localName, m_tagRules, rule, sel);
1428 // Just put it in the universal rule set.
1429 if (!m_universalRules)
1430 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1432 m_universalRules->append(m_ruleCount++, rule, sel);
1435 void CSSRuleSet::addRulesFromSheet(CSSStyleSheetImpl *sheet, const DOMString &medium)
1437 if (!sheet || !sheet->isCSSStyleSheet()) return;
1439 // No media implies "all", but if a media list exists it must
1440 // contain our current medium
1441 if (sheet->media() && !sheet->media()->contains(medium))
1442 return; // the style sheet doesn't apply
1444 int len = sheet->length();
1446 for (int i = 0; i < len; i++) {
1447 StyleBaseImpl *item = sheet->item(i);
1448 if (item->isStyleRule()) {
1449 CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(item);
1450 for (CSSSelector* s = rule->selector(); s; s = s->next())
1453 else if(item->isImportRule()) {
1454 CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
1456 //kdDebug( 6080 ) << "@import: Media: "
1457 // << import->media()->mediaText().string() << endl;
1459 if (!import->media() || import->media()->contains(medium))
1460 addRulesFromSheet(import->styleSheet(), medium);
1462 else if(item->isMediaRule()) {
1463 CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl*>(item);
1464 CSSRuleListImpl *rules = r->cssRules();
1466 //DOMString mediaText = media->mediaText();
1467 //kdDebug( 6080 ) << "@media: Media: "
1468 // << r->media()->mediaText().string() << endl;
1470 if ((!r->media() || r->media()->contains(medium)) && rules) {
1471 // Traverse child elements of the @media rule.
1472 for (unsigned j = 0; j < rules->length(); j++) {
1473 //kdDebug( 6080 ) << "*** Rule #" << j << endl;
1475 CSSRuleImpl *childItem = rules->item(j);
1476 if (childItem->isStyleRule()) {
1477 // It is a StyleRule, so append it to our list
1478 CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(childItem);
1479 for (CSSSelector* s = rule->selector(); s; s = s->next())
1485 //kdDebug( 6080 ) << "Ignoring child rule of "
1486 // "ImportRule: rule is not a StyleRule!" << endl;
1492 //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
1493 // << "rule empty or wrong medium!" << endl;
1496 // ### include other rules
1500 // -------------------------------------------------------------------------------------
1501 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1503 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
1506 if ( !primitiveValue ) {
1510 int type = primitiveValue->primitiveType();
1511 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1512 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
1513 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1514 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
1515 else if(type == CSSPrimitiveValue::CSS_NUMBER)
1516 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
1517 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
1518 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
1526 // color mapping code
1532 static const colorMap cmap[] = {
1533 { CSS_VAL_AQUA, 0xFF00FFFF },
1534 { CSS_VAL_BLACK, 0xFF000000 },
1535 { CSS_VAL_BLUE, 0xFF0000FF },
1536 { CSS_VAL_FUCHSIA, 0xFFFF00FF },
1537 { CSS_VAL_GRAY, 0xFF808080 },
1538 { CSS_VAL_GREEN, 0xFF008000 },
1539 { CSS_VAL_LIME, 0xFF00FF00 },
1540 { CSS_VAL_MAROON, 0xFF800000 },
1541 { CSS_VAL_NAVY, 0xFF000080 },
1542 { CSS_VAL_OLIVE, 0xFF808000 },
1543 { CSS_VAL_ORANGE, 0xFFFFA500 },
1544 { CSS_VAL_PURPLE, 0xFF800080 },
1545 { CSS_VAL_RED, 0xFFFF0000 },
1546 { CSS_VAL_SILVER, 0xFFC0C0C0 },
1547 { CSS_VAL_TEAL, 0xFF008080 },
1548 { CSS_VAL_WHITE, 0xFFFFFFFF },
1549 { CSS_VAL_YELLOW, 0xFFFFFF00 },
1551 { CSS_VAL_INVERT, invertedColor },
1553 { CSS_VAL_TRANSPARENT, transparentColor },
1554 { CSS_VAL_GREY, 0xFF808080 },
1556 { CSS_VAL_ACTIVEBORDER, 0xFFE0E0E0 },
1557 { CSS_VAL_ACTIVECAPTION, 0xFF000000 },
1558 { CSS_VAL_APPWORKSPACE, 0xFF000000 },
1559 { CSS_VAL_BUTTONFACE, 0xFFC0C0C0 },
1560 { CSS_VAL_BUTTONHIGHLIGHT, 0xFFE0E0E0 },
1561 { CSS_VAL_BUTTONSHADOW, 0xFFFFFFFF },
1562 { CSS_VAL_BUTTONTEXT, 0xFF000000 },
1563 { CSS_VAL_CAPTIONTEXT, 0xFF000000 },
1564 { CSS_VAL_GRAYTEXT, 0xFF000000 },
1565 { CSS_VAL_HIGHLIGHT, 0xFFFFFFFF },
1566 { CSS_VAL_HIGHLIGHTTEXT, 0xFFFFFFFF },
1567 { CSS_VAL_INACTIVEBORDER, 0xFFFFFFFF },
1568 { CSS_VAL_INACTIVECAPTION, 0xFFFFFFFF },
1569 { CSS_VAL_INACTIVECAPTIONTEXT, 0xFF000000 },
1570 { CSS_VAL_INFOBACKGROUND, 0xFF000000 },
1571 { CSS_VAL_INFOTEXT, 0xFF000000 },
1572 { CSS_VAL_MENU, 0xFFFFFFFF },
1573 { CSS_VAL_MENUTEXT, 0xFFFFFFFF },
1574 { CSS_VAL_SCROLLBAR, 0xFFFFFFFF },
1575 { CSS_VAL_TEXT, 0xFF000000 },
1576 { CSS_VAL_THREEDDARKSHADOW, 0xFF404040 },
1577 { CSS_VAL_THREEDFACE, 0xFFC0C0C0 },
1578 { CSS_VAL_THREEDHIGHLIGHT, 0xFFE0E0E0 },
1579 { CSS_VAL_THREEDLIGHTSHADOW, 0xFFC0C0C0 },
1580 { CSS_VAL_THREEDSHADOW, 0xFFFFFFFF },
1581 { CSS_VAL_WINDOW, 0xFFFFFFFF },
1582 { CSS_VAL_WINDOWFRAME, 0xFFFFFFFF },
1583 { CSS_VAL_WINDOWTEXT, 0xFF000000 },
1592 const char * configGroup;
1593 const char * configEntry;
1594 QPalette::ColorGroup group;
1595 QColorGroup::ColorRole role;
1598 const char * const wmgroup = "WM";
1599 const char * const generalgroup = "General";
1601 /* Mapping system settings to CSS 2
1602 * Tried hard to get an appropriate mapping - schlpbch
1604 static const uiColors uimap[] = {
1605 // Active window border.
1606 { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light },
1607 // Active window caption.
1608 { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text },
1609 // Text in caption, size box, and scrollbar arrow box.
1610 { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text },
1611 // Face color for three-dimensional display elements.
1612 { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1613 // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
1614 { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1615 // Shadow color for three-dimensional display elements.
1616 { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1617 // Text on push buttons.
1618 { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText },
1619 // Dark shadow for three-dimensional display elements.
1620 { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark },
1621 // Face color for three-dimensional display elements.
1622 { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1623 // Highlight color for three-dimensional display elements.
1624 { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1625 // Light color for three-dimensional display elements (for edges facing the light source).
1626 { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight },
1627 // Dark shadow for three-dimensional display elements.
1628 { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1630 // Inactive window border.
1631 { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background },
1632 // Inactive window caption.
1633 { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background },
1634 // Color of text in an inactive caption.
1635 { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text },
1636 { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text },
1639 { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1641 { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background },
1643 // Text of item(s) selected in a control.
1644 { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background },
1646 // Text of item(s) selected in a control.
1647 { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background },
1649 // Background color of multiple document interface.
1650 { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text },
1652 // Scroll bar gray area.
1653 { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1655 // Window background.
1656 { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1658 { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1660 { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text },
1661 { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text },
1662 { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles }
1665 #endif // !APPLE_CHANGES
1667 static QColor colorForCSSValue( int css_value )
1669 // try the regular ones first
1670 const colorMap *col = cmap;
1671 while ( col->css_value && col->css_value != css_value )
1673 if ( col->css_value )
1679 const uiColors *uicol = uimap;
1680 while ( uicol->css_value && uicol->css_value != css_value )
1682 if ( !uicol->css_value ) {
1683 if ( css_value == CSS_VAL_INFOBACKGROUND )
1684 return QToolTip::palette().inactive().background();
1685 else if ( css_value == CSS_VAL_INFOTEXT )
1686 return QToolTip::palette().inactive().foreground();
1687 else if ( css_value == CSS_VAL_BACKGROUND ) {
1688 KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
1689 bckgrConfig.setGroup("Desktop0");
1690 // Desktop background.
1691 return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background());
1693 return khtml::invalidColor;
1696 const QPalette &pal = qApp->palette();
1697 QColor c = pal.color( uicol->group, uicol->role );
1698 if ( uicol->configEntry ) {
1699 KConfig *globalConfig = KGlobal::config();
1700 globalConfig->setGroup( uicol->configGroup );
1701 c = globalConfig->readColorEntry( uicol->configEntry, &c );
1708 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1709 int startIndex, int endIndex)
1711 if (startIndex == -1) return;
1712 for (int i = startIndex; i <= endIndex; i++) {
1713 CSSMutableStyleDeclarationImpl* decl = m_matchedDecls[i];
1714 QValueListConstIterator<CSSProperty> end;
1715 for (QValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
1716 const CSSProperty& current = *it;
1717 // give special priority to font-xxx, color properties
1718 if (isImportant == current.isImportant()) {
1720 switch(current.id())
1722 case CSS_PROP_BACKGROUND:
1723 case CSS_PROP_BACKGROUND_IMAGE:
1724 case CSS_PROP_COLOR:
1725 case CSS_PROP_DIRECTION:
1726 case CSS_PROP_DISPLAY:
1728 case CSS_PROP_FONT_SIZE:
1729 case CSS_PROP_FONT_STYLE:
1730 case CSS_PROP_FONT_FAMILY:
1731 case CSS_PROP_FONT_WEIGHT:
1733 case CSS_PROP__KHTML_TEXT_SIZE_ADJUST:
1735 // these have to be applied first, because other properties use the computed
1736 // values of these porperties.
1744 if (first == applyFirst)
1745 applyProperty(current.id(), current.value());
1751 void CSSStyleSelector::applyProperty( int id, DOM::CSSValueImpl *value )
1753 //kdDebug( 6080 ) << "applying property " << prop->m_id << endl;
1755 CSSPrimitiveValueImpl *primitiveValue = 0;
1756 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
1761 bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1762 bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
1763 (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1765 // These properties are used to set the correct margins/padding on RTL lists.
1766 if (id == CSS_PROP__KHTML_MARGIN_START)
1767 id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
1768 else if (id == CSS_PROP__KHTML_PADDING_START)
1769 id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
1771 // What follows is a list that maps the CSS properties into their corresponding front-end
1772 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
1773 // are only hit when mapping "inherit" or "initial" into front-end values.
1776 // ident only properties
1777 case CSS_PROP_BACKGROUND_ATTACHMENT:
1778 HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
1780 case CSS_PROP_BACKGROUND_REPEAT:
1781 HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
1783 case CSS_PROP_BORDER_COLLAPSE:
1784 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1785 if(!primitiveValue) break;
1786 switch(primitiveValue->getIdent())
1788 case CSS_VAL_COLLAPSE:
1789 style->setBorderCollapse(true);
1791 case CSS_VAL_SEPARATE:
1792 style->setBorderCollapse(false);
1799 case CSS_PROP_BORDER_TOP_STYLE:
1800 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1801 if (!primitiveValue) return;
1802 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1804 case CSS_PROP_BORDER_RIGHT_STYLE:
1805 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1806 if (!primitiveValue) return;
1807 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1809 case CSS_PROP_BORDER_BOTTOM_STYLE:
1810 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1811 if (!primitiveValue) return;
1812 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1814 case CSS_PROP_BORDER_LEFT_STYLE:
1815 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1816 if (!primitiveValue) return;
1817 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1819 case CSS_PROP_OUTLINE_STYLE:
1820 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1821 if (!primitiveValue) return;
1822 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1823 style->setOutlineStyle(DOTTED, true);
1825 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1827 case CSS_PROP_CAPTION_SIDE:
1829 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1830 if(!primitiveValue) break;
1831 ECaptionSide c = RenderStyle::initialCaptionSide();
1832 switch(primitiveValue->getIdent())
1837 c = CAPRIGHT; break;
1840 case CSS_VAL_BOTTOM:
1841 c = CAPBOTTOM; break;
1845 style->setCaptionSide(c);
1848 case CSS_PROP_CLEAR:
1850 HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1851 if(!primitiveValue) break;
1853 switch(primitiveValue->getIdent())
1869 case CSS_PROP_DIRECTION:
1871 HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1872 if(!primitiveValue) break;
1873 style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
1876 case CSS_PROP_DISPLAY:
1878 HANDLE_INHERIT_AND_INITIAL(display, Display)
1879 if(!primitiveValue) break;
1880 int id = primitiveValue->getIdent();
1882 if (id == CSS_VAL_NONE)
1885 d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1887 style->setDisplay(d);
1888 //kdDebug( 6080 ) << "setting display to " << d << endl;
1893 case CSS_PROP_EMPTY_CELLS:
1895 HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1896 if (!primitiveValue) break;
1897 int id = primitiveValue->getIdent();
1898 if (id == CSS_VAL_SHOW)
1899 style->setEmptyCells(SHOW);
1900 else if (id == CSS_VAL_HIDE)
1901 style->setEmptyCells(HIDE);
1904 case CSS_PROP_FLOAT:
1906 HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1907 if(!primitiveValue) return;
1909 switch(primitiveValue->getIdent())
1916 case CSS_VAL_CENTER: //Non standart CSS-Value
1922 style->setFloating(f);
1927 case CSS_PROP_FONT_STRETCH:
1928 break; /* Not supported. */
1930 case CSS_PROP_FONT_STYLE:
1932 FontDef fontDef = style->htmlFont().fontDef;
1934 fontDef.italic = parentStyle->htmlFont().fontDef.italic;
1936 fontDef.italic = false;
1938 if(!primitiveValue) return;
1939 switch(primitiveValue->getIdent()) {
1940 case CSS_VAL_OBLIQUE:
1941 // ### oblique is the same as italic for the moment...
1942 case CSS_VAL_ITALIC:
1943 fontDef.italic = true;
1945 case CSS_VAL_NORMAL:
1946 fontDef.italic = false;
1952 if (style->setFontDef( fontDef ))
1958 case CSS_PROP_FONT_VARIANT:
1960 FontDef fontDef = style->htmlFont().fontDef;
1962 fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps;
1964 fontDef.smallCaps = false;
1966 if(!primitiveValue) return;
1967 int id = primitiveValue->getIdent();
1968 if ( id == CSS_VAL_NORMAL )
1969 fontDef.smallCaps = false;
1970 else if ( id == CSS_VAL_SMALL_CAPS )
1971 fontDef.smallCaps = true;
1975 if (style->setFontDef( fontDef ))
1980 case CSS_PROP_FONT_WEIGHT:
1982 FontDef fontDef = style->htmlFont().fontDef;
1984 fontDef.weight = parentStyle->htmlFont().fontDef.weight;
1986 fontDef.weight = QFont::Normal;
1988 if(!primitiveValue) return;
1989 if(primitiveValue->getIdent())
1991 switch(primitiveValue->getIdent()) {
1992 // ### we just support normal and bold fonts at the moment...
1993 // setWeight can actually accept values between 0 and 99...
1995 case CSS_VAL_BOLDER:
2000 fontDef.weight = QFont::Bold;
2002 case CSS_VAL_NORMAL:
2003 case CSS_VAL_LIGHTER:
2009 fontDef.weight = QFont::Normal;
2017 // ### fix parsing of 100-900 values in parser, apply them here
2020 if (style->setFontDef( fontDef ))
2025 case CSS_PROP_LIST_STYLE_POSITION:
2027 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
2028 if (!primitiveValue) return;
2029 if (primitiveValue->getIdent())
2030 style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
2034 case CSS_PROP_LIST_STYLE_TYPE:
2036 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2037 if (!primitiveValue) return;
2038 if (primitiveValue->getIdent())
2041 int id = primitiveValue->getIdent();
2042 if ( id == CSS_VAL_NONE) { // important!!
2045 t = EListStyleType(id - CSS_VAL_DISC);
2047 style->setListStyleType(t);
2052 case CSS_PROP_OVERFLOW:
2054 HANDLE_INHERIT_AND_INITIAL(overflow, Overflow)
2055 if (!primitiveValue) return;
2057 switch(primitiveValue->getIdent())
2059 case CSS_VAL_VISIBLE:
2060 o = OVISIBLE; break;
2061 case CSS_VAL_HIDDEN:
2063 case CSS_VAL_SCROLL:
2067 case CSS_VAL_MARQUEE:
2068 o = OMARQUEE; break;
2069 case CSS_VAL_OVERLAY:
2070 o = OOVERLAY; break;
2074 style->setOverflow(o);
2078 case CSS_PROP_PAGE_BREAK_BEFORE:
2080 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2081 if (!primitiveValue) return;
2082 switch (primitiveValue->getIdent()) {
2084 style->setPageBreakBefore(PBAUTO);
2088 case CSS_VAL_ALWAYS:
2089 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2092 style->setPageBreakBefore(PBAVOID);
2098 case CSS_PROP_PAGE_BREAK_AFTER:
2100 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2101 if (!primitiveValue) return;
2102 switch (primitiveValue->getIdent()) {
2104 style->setPageBreakAfter(PBAUTO);
2108 case CSS_VAL_ALWAYS:
2109 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2112 style->setPageBreakAfter(PBAVOID);
2118 case CSS_PROP_PAGE_BREAK_INSIDE: {
2119 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2120 if (!primitiveValue) return;
2121 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2122 style->setPageBreakInside(PBAUTO);
2123 else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2124 style->setPageBreakInside(PBAVOID);
2129 break; /* FIXME: Not even sure what this is... -dwh */
2131 case CSS_PROP_POSITION:
2133 HANDLE_INHERIT_AND_INITIAL(position, Position)
2134 if(!primitiveValue) return;
2136 switch(primitiveValue->getIdent())
2138 case CSS_VAL_STATIC:
2140 case CSS_VAL_RELATIVE:
2141 p = RELATIVE; break;
2142 case CSS_VAL_ABSOLUTE:
2143 p = ABSOLUTE; break;
2147 view->useSlowRepaints();
2154 style->setPosition(p);
2158 case CSS_PROP_TABLE_LAYOUT: {
2159 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2161 if ( !primitiveValue->getIdent() )
2164 ETableLayout l = RenderStyle::initialTableLayout();
2165 switch( primitiveValue->getIdent() ) {
2170 style->setTableLayout( l );
2177 case CSS_PROP_UNICODE_BIDI: {
2178 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2179 switch (primitiveValue->getIdent()) {
2180 case CSS_VAL_NORMAL:
2181 style->setUnicodeBidi(UBNormal);
2184 style->setUnicodeBidi(Embed);
2186 case CSS_VAL_BIDI_OVERRIDE:
2187 style->setUnicodeBidi(Override);
2194 case CSS_PROP_TEXT_TRANSFORM: {
2195 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2197 if(!primitiveValue->getIdent()) return;
2200 switch(primitiveValue->getIdent()) {
2201 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break;
2202 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break;
2203 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break;
2205 default: tt = TTNONE; break;
2207 style->setTextTransform(tt);
2211 case CSS_PROP_VISIBILITY:
2213 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2215 switch( primitiveValue->getIdent() ) {
2216 case CSS_VAL_HIDDEN:
2217 style->setVisibility( HIDDEN );
2219 case CSS_VAL_VISIBLE:
2220 style->setVisibility( VISIBLE );
2222 case CSS_VAL_COLLAPSE:
2223 style->setVisibility( COLLAPSE );
2229 case CSS_PROP_WHITE_SPACE:
2230 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2232 if(!primitiveValue->getIdent()) return;
2235 switch(primitiveValue->getIdent()) {
2236 case CSS_VAL__KHTML_NOWRAP:
2239 case CSS_VAL_NOWRAP:
2245 case CSS_VAL_NORMAL:
2250 style->setWhiteSpace(s);
2253 case CSS_PROP_BACKGROUND_POSITION:
2254 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
2255 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
2257 case CSS_PROP_BACKGROUND_POSITION_X: {
2258 HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
2261 case CSS_PROP_BACKGROUND_POSITION_Y: {
2262 HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
2265 case CSS_PROP_BORDER_SPACING: {
2267 style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2268 style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2270 else if (isInitial) {
2271 style->setHorizontalBorderSpacing(0);
2272 style->setVerticalBorderSpacing(0);
2276 case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
2277 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2278 if (!primitiveValue) break;
2279 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
2280 style->setHorizontalBorderSpacing(spacing);
2283 case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
2284 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2285 if (!primitiveValue) break;
2286 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
2287 style->setVerticalBorderSpacing(spacing);
2290 case CSS_PROP_CURSOR:
2291 HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
2293 style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
2295 // colors || inherit
2296 case CSS_PROP_BACKGROUND_COLOR:
2297 case CSS_PROP_BORDER_TOP_COLOR:
2298 case CSS_PROP_BORDER_RIGHT_COLOR:
2299 case CSS_PROP_BORDER_BOTTOM_COLOR:
2300 case CSS_PROP_BORDER_LEFT_COLOR:
2301 case CSS_PROP_COLOR:
2302 case CSS_PROP_OUTLINE_COLOR:
2303 // this property is an extension used to get HTML4 <font> right.
2305 case CSS_PROP_SCROLLBAR_FACE_COLOR:
2306 case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2307 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2308 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2309 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2310 case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2311 case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2316 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2317 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2318 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2319 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2320 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2321 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2322 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2325 else if (isInitial) {
2326 // The border/outline colors will just map to the invalid color |col| above. This will have the
2327 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2328 // not painting the background since the color won't be valid).
2329 if (id == CSS_PROP_COLOR)
2330 col = RenderStyle::initialColor();
2335 col = getColorFromPrimitiveValue(primitiveValue);
2338 //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
2341 case CSS_PROP_BACKGROUND_COLOR:
2342 style->setBackgroundColor(col); break;
2343 case CSS_PROP_BORDER_TOP_COLOR:
2344 style->setBorderTopColor(col); break;
2345 case CSS_PROP_BORDER_RIGHT_COLOR:
2346 style->setBorderRightColor(col); break;
2347 case CSS_PROP_BORDER_BOTTOM_COLOR:
2348 style->setBorderBottomColor(col); break;
2349 case CSS_PROP_BORDER_LEFT_COLOR:
2350 style->setBorderLeftColor(col); break;
2351 case CSS_PROP_COLOR:
2352 style->setColor(col); break;
2353 case CSS_PROP_OUTLINE_COLOR:
2354 style->setOutlineColor(col); break;
2356 case CSS_PROP_SCROLLBAR_FACE_COLOR:
2357 style->setPaletteColor(QPalette::Active, QColorGroup::Button, col);
2358 style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col);
2360 case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2361 style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col);
2362 style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col);
2364 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2365 style->setPaletteColor(QPalette::Active, QColorGroup::Light, col);
2366 style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col);
2368 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2370 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2371 style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col);
2372 style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col);
2374 case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2375 style->setPaletteColor(QPalette::Active, QColorGroup::Base, col);
2376 style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col);
2377 style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col);
2378 style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col);
2379 style->setPaletteColor(QPalette::Active, QColorGroup::Background, col);
2380 style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col);
2382 case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2383 style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col);
2384 style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col);
2395 case CSS_PROP_BACKGROUND_IMAGE:
2396 HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
2398 case CSS_PROP_LIST_STYLE_IMAGE:
2400 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2401 if (!primitiveValue) return;
2402 style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)
2403 ->image(element->getDocument()->docLoader()));
2404 //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
2409 case CSS_PROP_BORDER_TOP_WIDTH:
2410 case CSS_PROP_BORDER_RIGHT_WIDTH:
2411 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2412 case CSS_PROP_BORDER_LEFT_WIDTH:
2413 case CSS_PROP_OUTLINE_WIDTH:
2416 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2417 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2418 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2419 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2420 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2423 else if (isInitial) {
2424 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2425 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2426 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2427 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2428 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2432 if(!primitiveValue) break;
2434 switch(primitiveValue->getIdent())
2439 case CSS_VAL_MEDIUM:
2445 case CSS_VAL_INVALID:
2446 width = primitiveValue->computeLength(style, paintDeviceMetrics);
2452 if(width < 0) return;
2455 case CSS_PROP_BORDER_TOP_WIDTH:
2456 style->setBorderTopWidth(width);
2458 case CSS_PROP_BORDER_RIGHT_WIDTH:
2459 style->setBorderRightWidth(width);
2461 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2462 style->setBorderBottomWidth(width);
2464 case CSS_PROP_BORDER_LEFT_WIDTH:
2465 style->setBorderLeftWidth(width);
2467 case CSS_PROP_OUTLINE_WIDTH:
2468 style->setOutlineWidth(width);
2476 case CSS_PROP_LETTER_SPACING:
2477 case CSS_PROP_WORD_SPACING:
2481 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2482 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2485 else if (isInitial) {
2486 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2487 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2492 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2495 if(!primitiveValue) return;
2496 width = primitiveValue->computeLength(style, paintDeviceMetrics);
2500 case CSS_PROP_LETTER_SPACING:
2501 style->setLetterSpacing(width);
2503 case CSS_PROP_WORD_SPACING:
2504 style->setWordSpacing(width);
2506 // ### needs the definitions in renderstyle
2512 case CSS_PROP_WORD_WRAP:
2514 HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
2516 if(!primitiveValue->getIdent()) return;
2519 switch(primitiveValue->getIdent()) {
2520 case CSS_VAL_BREAK_WORD:
2523 case CSS_VAL_NORMAL:
2528 style->setWordWrap(s);
2532 case CSS_PROP__KHTML_NBSP_MODE:
2534 HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
2536 if (!primitiveValue->getIdent()) return;
2539 switch(primitiveValue->getIdent()) {
2543 case CSS_VAL_NORMAL:
2548 style->setNBSPMode(m);
2552 case CSS_PROP__KHTML_LINE_BREAK:
2554 HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
2556 if (!primitiveValue->getIdent()) return;
2559 switch(primitiveValue->getIdent()) {
2560 case CSS_VAL_AFTER_WHITE_SPACE:
2561 b = AFTER_WHITE_SPACE;
2563 case CSS_VAL_NORMAL:
2568 style->setKHTMLLineBreak(b);
2572 case CSS_PROP__KHTML_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR:
2574 HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2576 if (!primitiveValue->getIdent()) return;
2578 EMatchNearestMailBlockquoteColor c;
2579 switch(primitiveValue->getIdent()) {
2580 case CSS_VAL_NORMAL:
2588 style->setMatchNearestMailBlockquoteColor(c);
2593 case CSS_PROP_MAX_WIDTH:
2595 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2599 case CSS_PROP_RIGHT:
2600 case CSS_PROP_BOTTOM:
2601 case CSS_PROP_WIDTH:
2602 case CSS_PROP_MIN_WIDTH:
2603 case CSS_PROP_MARGIN_TOP:
2604 case CSS_PROP_MARGIN_RIGHT:
2605 case CSS_PROP_MARGIN_BOTTOM:
2606 case CSS_PROP_MARGIN_LEFT:
2608 if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2609 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2610 l = Length(Intrinsic);
2613 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2614 l = Length(MinIntrinsic);
2618 if (id != CSS_PROP_MAX_WIDTH && primitiveValue &&
2619 primitiveValue->getIdent() == CSS_VAL_AUTO)
2621 //kdDebug( 6080 ) << "found value=auto" << endl;
2624 case CSS_PROP_PADDING_TOP:
2625 case CSS_PROP_PADDING_RIGHT:
2626 case CSS_PROP_PADDING_BOTTOM:
2627 case CSS_PROP_PADDING_LEFT:
2628 case CSS_PROP_TEXT_INDENT:
2632 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2633 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2634 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2635 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2636 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2637 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2638 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2639 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2640 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2641 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2642 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2643 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2644 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2645 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2646 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2647 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2650 else if (isInitial) {
2651 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2652 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2653 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2654 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2655 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2656 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2657 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2658 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2659 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2660 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2661 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2662 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2663 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2664 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2665 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2666 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2670 if (primitiveValue && !apply) {
2671 int type = primitiveValue->primitiveType();
2672 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2673 // Handle our quirky margin units if we have them.
2674 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed,
2675 primitiveValue->isQuirkValue());
2676 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2677 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2678 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
2679 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
2682 if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2683 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2684 // Padding can't be negative
2685 apply = !((l.isFixed() || l.isPercent()) && l.width(100) < 0);
2692 case CSS_PROP_MAX_WIDTH:
2693 style->setMaxWidth(l); break;
2694 case CSS_PROP_BOTTOM:
2695 style->setBottom(l); break;
2697 style->setTop(l); break;
2699 style->setLeft(l); break;
2700 case CSS_PROP_RIGHT:
2701 style->setRight(l); break;
2702 case CSS_PROP_WIDTH:
2703 style->setWidth(l); break;
2704 case CSS_PROP_MIN_WIDTH:
2705 style->setMinWidth(l); break;
2706 case CSS_PROP_PADDING_TOP:
2707 style->setPaddingTop(l); break;
2708 case CSS_PROP_PADDING_RIGHT:
2709 style->setPaddingRight(l); break;
2710 case CSS_PROP_PADDING_BOTTOM:
2711 style->setPaddingBottom(l); break;
2712 case CSS_PROP_PADDING_LEFT:
2713 style->setPaddingLeft(l); break;
2714 case CSS_PROP_MARGIN_TOP:
2715 style->setMarginTop(l); break;
2716 case CSS_PROP_MARGIN_RIGHT:
2717 style->setMarginRight(l); break;
2718 case CSS_PROP_MARGIN_BOTTOM:
2719 style->setMarginBottom(l); break;
2720 case CSS_PROP_MARGIN_LEFT:
2721 style->setMarginLeft(l); break;
2722 case CSS_PROP_TEXT_INDENT:
2723 style->setTextIndent(l); break;
2729 case CSS_PROP_MAX_HEIGHT:
2730 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2732 case CSS_PROP_HEIGHT:
2733 case CSS_PROP_MIN_HEIGHT:
2734 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2735 l = Length(Intrinsic);
2738 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2739 l = Length(MinIntrinsic);
2742 if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
2743 primitiveValue->getIdent() == CSS_VAL_AUTO)
2746 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2747 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2748 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2751 else if (isInitial) {
2752 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2753 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2754 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2758 if (primitiveValue && !apply)
2760 int type = primitiveValue->primitiveType();
2761 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2762 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2763 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2765 // ### compute from parents height!!!
2766 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2775 case CSS_PROP_MAX_HEIGHT:
2776 style->setMaxHeight(l); break;
2777 case CSS_PROP_HEIGHT:
2778 style->setHeight(l); break;
2779 case CSS_PROP_MIN_HEIGHT:
2780 style->setMinHeight(l); break;
2788 case CSS_PROP_VERTICAL_ALIGN:
2789 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2790 if (!primitiveValue) return;
2791 if (primitiveValue->getIdent()) {
2792 khtml::EVerticalAlign align;
2794 switch(primitiveValue->getIdent())
2798 case CSS_VAL_BOTTOM:
2799 align = BOTTOM; break;
2800 case CSS_VAL_MIDDLE:
2801 align = MIDDLE; break;
2802 case CSS_VAL_BASELINE:
2803 align = BASELINE; break;
2804 case CSS_VAL_TEXT_BOTTOM:
2805 align = TEXT_BOTTOM; break;
2806 case CSS_VAL_TEXT_TOP:
2807 align = TEXT_TOP; break;
2811 align = SUPER; break;
2812 case CSS_VAL__KHTML_BASELINE_MIDDLE:
2813 align = BASELINE_MIDDLE; break;
2817 style->setVerticalAlign(align);
2820 int type = primitiveValue->primitiveType();
2822 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2823 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
2824 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2825 l = Length( int( primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
2827 style->setVerticalAlign( LENGTH );
2828 style->setVerticalAlignLength( l );
2832 case CSS_PROP_FONT_SIZE:
2834 FontDef fontDef = style->htmlFont().fontDef;
2838 bool parentIsAbsoluteSize = false;
2840 oldSize = parentStyle->htmlFont().fontDef.specifiedSize;
2841 parentIsAbsoluteSize = parentStyle->htmlFont().fontDef.isAbsoluteSize;
2847 size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks());
2848 else if (primitiveValue->getIdent()) {
2849 // Keywords are being used.
2850 switch (primitiveValue->getIdent()) {
2851 case CSS_VAL_XX_SMALL:
2852 case CSS_VAL_X_SMALL:
2854 case CSS_VAL_MEDIUM:
2856 case CSS_VAL_X_LARGE:
2857 case CSS_VAL_XX_LARGE:
2858 case CSS_VAL__KHTML_XXX_LARGE:
2859 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks());
2861 case CSS_VAL_LARGER:
2862 size = largerFontSize(oldSize, style->htmlHacks());
2864 case CSS_VAL_SMALLER:
2865 size = smallerFontSize(oldSize, style->htmlHacks());
2871 fontDef.isAbsoluteSize = parentIsAbsoluteSize &&
2872 (primitiveValue->getIdent() == CSS_VAL_LARGER ||
2873 primitiveValue->getIdent() == CSS_VAL_SMALLER);
2875 int type = primitiveValue->primitiveType();
2876 fontDef.isAbsoluteSize = parentIsAbsoluteSize ||
2877 (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
2878 type != CSSPrimitiveValue::CSS_EMS &&
2879 type != CSSPrimitiveValue::CSS_EXS);
2880 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2881 size = primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics, false);
2882 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2883 size = (primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
2889 if (size <= 0) return;
2891 //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
2893 setFontSize(fontDef, size);
2894 if (style->setFontDef( fontDef ))
2899 case CSS_PROP_Z_INDEX:
2901 HANDLE_INHERIT(zIndex, ZIndex)
2902 else if (isInitial) {
2903 style->setHasAutoZIndex();
2907 if (!primitiveValue)
2910 if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
2911 style->setHasAutoZIndex();
2915 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2916 return; // Error case.
2918 style->setZIndex((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2923 case CSS_PROP_WIDOWS:
2925 HANDLE_INHERIT_AND_INITIAL(widows, Widows)
2926 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2928 style->setWidows((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2932 case CSS_PROP_ORPHANS:
2934 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
2935 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2937 style->setOrphans((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2941 // length, percent, number
2942 case CSS_PROP_LINE_HEIGHT:
2944 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
2945 if(!primitiveValue) return;
2947 int type = primitiveValue->primitiveType();
2948 if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
2949 lineHeight = Length( -100, Percent );
2950 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
2951 double multiplier = 1.0;
2952 // Scale for the font zoom factor only for types other than "em" and "ex", since those are
2953 // already based on the font size.
2954 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) {
2955 multiplier = view->part()->zoomFactor() / 100.0;
2957 lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics, multiplier), Fixed);
2958 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2959 lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
2960 else if (type == CSSPrimitiveValue::CSS_NUMBER)
2961 lineHeight = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
2964 style->setLineHeight(lineHeight);
2969 case CSS_PROP_TEXT_ALIGN:
2971 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
2972 if (!primitiveValue) return;
2973 if (primitiveValue->getIdent())
2974 style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
2985 bool hasClip = true;
2987 if (parentStyle->hasClip()) {
2988 top = parentStyle->clipTop();
2989 right = parentStyle->clipRight();
2990 bottom = parentStyle->clipBottom();
2991 left = parentStyle->clipLeft();
2995 top = right = bottom = left = Length();
2997 } else if (isInitial) {
2999 top = right = bottom = left = Length();
3000 } else if ( !primitiveValue ) {
3002 } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT ) {
3003 RectImpl *rect = primitiveValue->getRectValue();
3006 top = convertToLength( rect->top(), style, paintDeviceMetrics );
3007 right = convertToLength( rect->right(), style, paintDeviceMetrics );
3008 bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
3009 left = convertToLength( rect->left(), style, paintDeviceMetrics );
3011 } else if ( primitiveValue->getIdent() != CSS_VAL_AUTO ) {
3014 // qDebug("setting clip top to %d", top.value );
3015 // qDebug("setting clip right to %d", right.value );
3016 // qDebug("setting clip bottom to %d", bottom.value );
3017 // qDebug("setting clip left to %d", left.value );
3018 style->setClip(top, right, bottom, left);
3019 style->setHasClip(hasClip);
3026 case CSS_PROP_CONTENT:
3027 // list of string, uri, counter, attr, i
3029 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
3030 // note is a reminder that eventually "inherit" needs to be supported.
3031 if (!(style->styleType()==RenderStyle::BEFORE ||
3032 style->styleType()==RenderStyle::AFTER))
3036 if (style->contentData())
3037 style->contentData()->clearContent();
3041 if(!value->isValueList()) return;
3042 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3043 int len = list->length();
3045 for(int i = 0; i < len; i++) {
3046 CSSValueImpl *item = list->item(i);
3047 if(!item->isPrimitiveValue()) continue;
3048 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
3049 if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
3051 style->setContent(val->getStringValue().implementation(), i != 0);
3053 else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
3055 // FIXME: Should work with generic XML attributes also, and not
3056 // just the hardcoded HTML set. Can a namespace be specified for
3058 int attrID = element->getDocument()->attrId(0, val->getStringValue().implementation(), false);
3060 style->setContent(element->getAttribute(attrID).implementation(), i != 0);
3062 else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
3064 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
3065 style->setContent(image->image(element->getDocument()->docLoader()), i != 0);
3072 case CSS_PROP_COUNTER_INCREMENT:
3073 // list of CSS2CounterIncrement
3074 case CSS_PROP_COUNTER_RESET:
3075 // list of CSS2CounterReset
3077 case CSS_PROP_FONT_FAMILY:
3078 // list of strings and ids
3081 FontDef parentFontDef = parentStyle->htmlFont().fontDef;
3082 FontDef fontDef = style->htmlFont().fontDef;
3083 fontDef.genericFamily = parentFontDef.genericFamily;
3084 fontDef.family = parentFontDef.family;
3085 if (style->setFontDef(fontDef))
3089 else if (isInitial) {
3090 FontDef fontDef = style->htmlFont().fontDef;
3091 FontDef initialDef = FontDef();
3092 fontDef.genericFamily = initialDef.genericFamily;
3093 fontDef.family = initialDef.firstFamily();
3094 if (style->setFontDef(fontDef))
3099 if (!value->isValueList()) return;
3100 FontDef fontDef = style->htmlFont().fontDef;
3101 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3102 int len = list->length();
3103 KWQFontFamily &firstFamily = fontDef.firstFamily();
3104 KWQFontFamily *currFamily = 0;
3106 for(int i = 0; i < len; i++) {
3107 CSSValueImpl *item = list->item(i);
3108 if(!item->isPrimitiveValue()) continue;
3109 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
3111 if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
3112 face = static_cast<FontFamilyValueImpl *>(val)->fontName();
3113 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3114 switch (val->getIdent()) {
3115 case CSS_VAL__KHTML_BODY:
3116 face = settings->stdFontName();
3119 face = settings->serifFontName();
3120 fontDef.setGenericFamily(FontDef::eSerif);
3122 case CSS_VAL_SANS_SERIF:
3123 face = settings->sansSerifFontName();
3124 fontDef.setGenericFamily(FontDef::eSansSerif);
3126 case CSS_VAL_CURSIVE:
3127 face = settings->cursiveFontName();
3128 fontDef.setGenericFamily(FontDef::eCursive);
3130 case CSS_VAL_FANTASY:
3131 face = settings->fantasyFontName();
3132 fontDef.setGenericFamily(FontDef::eFantasy);
3134 case CSS_VAL_MONOSPACE:
3135 face = settings->fixedFontName();
3136 fontDef.setGenericFamily(FontDef::eMonospace);
3141 if ( !face.isEmpty() ) {
3143 // Filling in the first family.
3144 firstFamily.setFamily(face);
3145 currFamily = &firstFamily;
3148 KWQFontFamily *newFamily = new KWQFontFamily;
3149 newFamily->setFamily(face);
3150 currFamily->appendFamily(newFamily);
3151 currFamily = newFamily;
3154 if (style->setFontDef( fontDef )) {
3161 case CSS_PROP_QUOTES:
3162 // list of strings or i
3166 case CSS_PROP_TEXT_DECORATION: {
3168 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3169 int t = RenderStyle::initialTextDecoration();
3170 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3173 if(!value->isValueList()) return;
3174 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3175 int len = list->length();
3176 for(int i = 0; i < len; i++)
3178 CSSValueImpl *item = list->item(i);
3179 if(!item->isPrimitiveValue()) continue;
3180 primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
3181 switch(primitiveValue->getIdent())
3185 case CSS_VAL_UNDERLINE:
3186 t |= UNDERLINE; break;
3187 case CSS_VAL_OVERLINE:
3188 t |= OVERLINE; break;
3189 case CSS_VAL_LINE_THROUGH:
3190 t |= LINE_THROUGH; break;
3199 style->setTextDecoration(t);
3203 // shorthand properties
3204 case CSS_PROP_BACKGROUND:
3206 style->clearBackgroundLayers();
3209 else if (isInherit) {
3211 style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
3213 style->clearBackgroundLayers();
3217 case CSS_PROP_BORDER:
3218 case CSS_PROP_BORDER_STYLE:
3219 case CSS_PROP_BORDER_WIDTH:
3220 case CSS_PROP_BORDER_COLOR:
3221 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
3224 style->setBorderTopColor(parentStyle->borderTopColor());
3225 style->setBorderBottomColor(parentStyle->borderBottomColor());
3226 style->setBorderLeftColor(parentStyle->borderLeftColor());
3227 style->setBorderRightColor(parentStyle->borderRightColor());
3229 else if (isInitial) {
3230 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
3231 style->setBorderBottomColor(QColor());
3232 style->setBorderLeftColor(QColor());
3233 style->setBorderRightColor(QColor());
3236 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
3239 style->setBorderTopStyle(parentStyle->borderTopStyle());