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_INHERIT_COND(propID, prop, Prop) \
98 style->set##Prop(parentStyle->prop());\
102 #define HANDLE_INITIAL_COND(propID, Prop) \
105 style->set##Prop(RenderStyle::initial##Prop());\
109 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
112 style->set##Prop(RenderStyle::initial##Value());\
118 CSSRuleSet *CSSStyleSelector::defaultStyle = 0;
119 CSSRuleSet *CSSStyleSelector::defaultQuirksStyle = 0;
120 CSSRuleSet *CSSStyleSelector::defaultPrintStyle = 0;
121 CSSStyleSheetImpl *CSSStyleSelector::defaultSheet = 0;
122 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0;
123 CSSStyleSheetImpl *CSSStyleSelector::quirksSheet = 0;
125 static CSSStyleSelector::Encodedurl *encodedurl = 0;
126 static PseudoState pseudoState;
128 CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets,
129 const KURL &url, bool _strictParsing )
134 strictParsing = _strictParsing;
135 settings = view ? view->part()->settings() : 0;
136 if(!defaultStyle) loadDefaultStyle(settings);
137 m_medium = view ? view->mediaType() : QString("all");
141 paintDeviceMetrics = doc->paintDeviceMetrics();
143 // FIXME: This sucks! The user sheet is reparsed every time!
144 if ( !userStyleSheet.isEmpty() ) {
145 m_userSheet = new DOM::CSSStyleSheetImpl(doc);
146 m_userSheet->parseString( DOMString( userStyleSheet ) );
148 m_userStyle = new CSSRuleSet();
149 m_userStyle->addRulesFromSheet( m_userSheet, m_medium );
152 // add stylesheets from document
153 m_authorStyle = new CSSRuleSet();
155 QPtrListIterator<StyleSheetImpl> it(styleSheets->styleSheets);
156 for (; it.current(); ++it)
157 if (it.current()->isCSSStyleSheet())
158 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheetImpl*>(it.current()), m_medium);
160 //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl;
161 //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl;
165 u.setQuery( QString::null );
166 u.setRef( QString::null );
167 encodedurl.file = u.url();
168 int pos = encodedurl.file.findRev('/');
169 encodedurl.path = encodedurl.file;
171 encodedurl.path.truncate( pos );
172 encodedurl.path += '/';
174 u.setPath( QString::null );
175 encodedurl.host = u.url();
177 //kdDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path << endl;
180 CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet )
184 if(!defaultStyle) loadDefaultStyle();
185 KHTMLView *view = sheet->doc()->view();
186 m_medium = view ? view->mediaType() : QString("all");
188 m_authorStyle = new CSSRuleSet();
189 m_authorStyle->addRulesFromSheet( sheet, m_medium );
192 void CSSStyleSelector::init()
196 paintDeviceMetrics = 0;
197 m_matchedRuleCount = m_matchedDeclCount = m_tmpRuleCount = 0;
200 CSSStyleSelector::~CSSStyleSelector()
202 delete m_authorStyle;
207 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s)
209 if(defaultStyle) return;
212 QFile f(locate( "data", "khtml/css/html4.css" ) );
215 QCString file( f.size()+1 );
216 int readbytes = f.readBlock( file.data(), f.size() );
218 if ( readbytes >= 0 )
219 file[readbytes] = '\0';
221 QString style = QString::fromLatin1( file.data() );
223 style += s->settingsToCSS();
224 DOMString str(style);
226 defaultSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0);
227 defaultSheet->parseString( str );
229 // Collect only strict-mode rules.
230 defaultStyle = new CSSRuleSet();
231 defaultStyle->addRulesFromSheet( defaultSheet, "screen" );
233 defaultPrintStyle = new CSSRuleSet();
234 defaultPrintStyle->addRulesFromSheet( defaultSheet, "print" );
237 QFile f(locate( "data", "khtml/css/quirks.css" ) );
240 QCString file( f.size()+1 );
241 int readbytes = f.readBlock( file.data(), f.size() );
243 if ( readbytes >= 0 )
244 file[readbytes] = '\0';
246 QString style = QString::fromLatin1( file.data() );
247 DOMString str(style);
249 quirksSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0);
250 quirksSheet->parseString( str );
252 // Collect only quirks-mode rules.
253 defaultQuirksStyle = new CSSRuleSet();
254 defaultQuirksStyle->addRulesFromSheet( quirksSheet, "screen" );
257 //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl;
260 void CSSStyleSelector::addMatchedRule(CSSRuleData* rule)
262 if (m_matchedRules.size() <= m_matchedRuleCount)
263 m_matchedRules.resize(2*m_matchedRules.size()+1);
264 m_matchedRules[m_matchedRuleCount++] = rule;
267 void CSSStyleSelector::addMatchedDeclaration(CSSStyleDeclarationImpl* decl)
269 if (m_matchedDecls.size() <= m_matchedDeclCount)
270 m_matchedDecls.resize(2*m_matchedDecls.size()+1);
271 m_matchedDecls[m_matchedDeclCount++] = decl;
274 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
276 m_matchedRuleCount = 0;
277 firstRuleIndex = lastRuleIndex = -1;
278 if (!rules || !element) return;
280 // We need to collect the rules for id, class, tag, and everything else into a buffer and
281 // then sort the buffer.
282 if (element->hasID())
283 matchRulesForList(rules->getIDRules(element->getIDAttribute().implementation()),
284 firstRuleIndex, lastRuleIndex);
285 if (element->hasClass()) {
286 for (const AtomicStringList* singleClass = element->getClassList();
287 singleClass; singleClass = singleClass->next())
288 matchRulesForList(rules->getClassRules(singleClass->string().implementation()),
289 firstRuleIndex, lastRuleIndex);
291 matchRulesForList(rules->getTagRules((void*)(int)localNamePart(element->id())),
292 firstRuleIndex, lastRuleIndex);
293 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
295 // If we didn't match any rules, we're done.
296 if (m_matchedRuleCount == 0) return;
298 // Sort the set of matched rules.
299 sortMatchedRules(0, m_matchedRuleCount);
301 // Now transfer the set of matched rules over to our list of decls.
302 for (unsigned i = 0; i < m_matchedRuleCount; i++)
303 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
306 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules,
307 int& firstRuleIndex, int& lastRuleIndex)
310 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
311 CSSStyleRuleImpl* rule = d->rule();
312 Q_UINT16 cssTagId = localNamePart(element->id());
313 Q_UINT16 tag = localNamePart(d->selector()->tag);
314 if ((cssTagId == tag || tag == anyLocalName) && checkSelector(d->selector(), element)) {
315 // If the rule has no properties to apply, then ignore it.
316 CSSStyleDeclarationImpl* decl = rule->declaration();
319 // If we're matching normal rules, set a pseudo bit if
320 // we really just matched a pseudo-element.
321 if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO)
322 style->setHasPseudoStyle(dynamicPseudo);
324 // Update our first/last rule indices in the matched rules array.
325 lastRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
326 if (firstRuleIndex == -1) firstRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
328 // Add this rule to our list of matched rules.
335 bool operator >(CSSRuleData& r1, CSSRuleData& r2)
337 int spec1 = r1.selector()->specificity();
338 int spec2 = r2.selector()->specificity();
339 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
341 bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
346 void CSSStyleSelector::sortMatchedRules(uint start, uint end)
348 if (start >= end || (end-start == 1))
349 return; // Sanity check.
351 if (end - start <= 6) {
352 // Apply a bubble sort for smaller lists.
353 for (uint i = end-1; i > start; i--) {
355 for (uint j = start; j < i; j++) {
356 CSSRuleData* elt = m_matchedRules[j];
357 CSSRuleData* elt2 = m_matchedRules[j+1];
360 m_matchedRules[j] = elt2;
361 m_matchedRules[j+1] = elt;
369 // Peform a merge sort for larger lists.
370 uint mid = (start+end)/2;
371 sortMatchedRules(start, mid);
372 sortMatchedRules(mid, end);
374 CSSRuleData* elt = m_matchedRules[mid-1];
375 CSSRuleData* elt2 = m_matchedRules[mid];
377 // Handle the fast common case (of equal specificity). The list may already
378 // be completely sorted.
382 // We have to merge sort. Ensure our merge buffer is big enough to hold
384 m_tmpRules.resize(end - start);
388 elt = m_matchedRules[i1];
389 elt2 = m_matchedRules[i2];
391 while (i1 < mid || i2 < end) {
392 if (i1 < mid && (i2 == end || *elt <= *elt2)) {
393 m_tmpRules[m_tmpRuleCount++] = elt;
396 elt = m_matchedRules[i1];
399 m_tmpRules[m_tmpRuleCount++] = elt2;
402 elt2 = m_matchedRules[i2];
406 for (uint i = start; i < end; i++)
407 m_matchedRules[i] = m_tmpRules[i-start];
413 void CSSStyleSelector::initElementAndPseudoState(ElementImpl* e)
416 if (element && element->isHTMLElement())
417 htmlElement = static_cast<HTMLElementImpl*>(element);
420 ::encodedurl = &encodedurl;
421 pseudoState = PseudoUnknown;
424 void CSSStyleSelector::initForStyleResolve(ElementImpl* e, RenderStyle* defaultParent)
426 // set some variables we will need
427 pseudoStyle = RenderStyle::NOPSEUDO;
429 parentNode = e->parentNode();
431 parentStyle = defaultParent;
433 parentStyle = (parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
434 view = element->getDocument()->view();
435 isXMLDoc = !element->getDocument()->isHTMLDocument();
436 part = element->getDocument()->part();
437 settings = part ? part->settings() : 0;
438 paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
442 m_matchedRuleCount = 0;
443 m_matchedDeclCount = 0;
449 // modified version of the one in kurl.cpp
450 static void cleanpath(QString &path)
453 while ( (pos = path.find( "/../" )) != -1 ) {
456 prev = path.findRev( "/", pos -1 );
457 // don't remove the host, i.e. http://foo.org/../foo.html
458 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
459 path.remove( pos, 3);
461 // matching directory found ?
462 path.remove( prev, pos- prev + 3 );
466 // Don't remove "//" from an anchor identifier. -rjw
467 // Set refPos to -2 to mean "I haven't looked for the anchor yet".
468 // We don't want to waste a function call on the search for the the anchor
469 // in the vast majority of cases where there is no "//" in the path.
471 while ( (pos = path.find( "//", pos )) != -1) {
473 refPos = path.find("#", 0);
474 if (refPos > 0 && pos >= refPos)
477 if ( pos == 0 || path[pos-1] != ':' )
478 path.remove( pos, 1 );
482 while ( (pos = path.find( "/./" )) != -1)
483 path.remove( pos, 2 );
484 //kdDebug() << "checkPseudoState " << path << endl;
487 static void checkPseudoState( DOM::ElementImpl *e, bool checkVisited = true )
489 if (!e->hasAnchor()) {
490 pseudoState = PseudoNone;
494 const AtomicString& attr = e->getAttribute(ATTR_HREF);
496 pseudoState = PseudoNone;
501 pseudoState = PseudoAnyLink;
505 QConstString cu(attr.unicode(), attr.length());
506 QString u = cu.string();
507 if ( !u.contains("://") ) {
509 u.prepend(encodedurl->host);
510 else if ( u[0] == '#' )
511 u.prepend(encodedurl->file);
513 u.prepend(encodedurl->path);
516 //completeURL( attr.string() );
517 pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;
520 #ifdef STYLE_SHARING_STATS
521 static int fraction = 0;
522 static int total = 0;
525 const int siblingThreshold = 10;
527 NodeImpl* CSSStyleSelector::locateCousinList(ElementImpl* parent)
529 if (parent && parent->isHTMLElement()) {
530 HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parent);
531 if (p->renderer() && !p->inlineStyleDecl() && !p->hasID()) {
532 DOM::NodeImpl* r = p->previousSibling();
534 RenderStyle* st = p->renderer()->style();
536 if (r->renderer() && r->renderer()->style() == st)
537 return r->lastChild();
538 if (subcount++ == siblingThreshold)
540 r = r->previousSibling();
543 r = locateCousinList(static_cast<ElementImpl*>(parent->parentNode()));
545 if (r->renderer() && r->renderer()->style() == st)
546 return r->lastChild();
547 if (subcount++ == siblingThreshold)
549 r = r->previousSibling();
556 bool CSSStyleSelector::canShareStyleWithElement(NodeImpl* n)
558 if (n->isHTMLElement()) {
559 bool mouseInside = element->renderer() ? element->renderer()->mouseInside() : false;
560 HTMLElementImpl* s = static_cast<HTMLElementImpl*>(n);
561 if (s->renderer() && (s->id() == element->id()) && !s->hasID() &&
562 (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
563 (s->hasMappedAttributes() == htmlElement->hasMappedAttributes()) &&
564 (s->hasAnchor() == element->hasAnchor()) &&
565 !s->renderer()->style()->affectedByAttributeSelectors() &&
566 (s->renderer()->mouseInside() == mouseInside) &&
567 (s->active() == element->active()) &&
568 (s->focused() == element->focused())) {
569 bool classesMatch = true;
571 const AtomicString& class1 = element->getAttribute(ATTR_CLASS);
572 const AtomicString& class2 = s->getAttribute(ATTR_CLASS);
573 classesMatch = (class1 == class2);
577 bool mappedAttrsMatch = true;
578 if (s->hasMappedAttributes())
579 mappedAttrsMatch = s->htmlAttributes()->mapsEquivalent(htmlElement->htmlAttributes());
580 if (mappedAttrsMatch) {
581 bool anchorsMatch = true;
582 if (s->hasAnchor()) {
583 // We need to check to see if the visited state matches.
584 QColor linkColor = element->getDocument()->linkColor();
585 QColor visitedColor = element->getDocument()->visitedLinkColor();
586 if (pseudoState == PseudoUnknown)
587 checkPseudoState(element, s->renderer()->style()->pseudoState() != PseudoAnyLink ||
588 linkColor != visitedColor);
589 anchorsMatch = (pseudoState == s->renderer()->style()->pseudoState());
593 #ifdef STYLE_SHARING_STATS
595 printf("Sharing %d out of %d\n", fraction, total);
606 RenderStyle* CSSStyleSelector::locateSharedStyle()
609 if (htmlElement && !htmlElement->inlineStyleDecl() && !htmlElement->hasID() &&
610 !htmlElement->getDocument()->usesSiblingRules()) {
611 // Check previous siblings.
614 for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
616 if (canShareStyleWithElement(n))
617 return n->renderer()->style();
618 if (count++ == siblingThreshold)
620 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
623 n = locateCousinList(static_cast<ElementImpl*>(element->parentNode()));
625 if (canShareStyleWithElement(n))
626 return n->renderer()->style();
627 if (count++ == siblingThreshold)
629 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
632 #ifdef STYLE_SHARING_STATS
634 printf("Sharing %d out of %d\n", fraction, total);
639 RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent, bool allowSharing)
641 if (!e->getDocument()->haveStylesheetsLoaded()) {
642 if (!styleNotYetAvailable) {
643 styleNotYetAvailable = ::new RenderStyle();
644 styleNotYetAvailable->setDisplay(NONE);
645 styleNotYetAvailable->ref();
647 return styleNotYetAvailable;
650 initElementAndPseudoState(e);
652 style = locateSharedStyle();
656 initForStyleResolve(e, defaultParent);
658 style = new (e->getDocument()->renderArena()) RenderStyle();
660 style->inheritFrom(parentStyle);
664 // 1. First we match rules from the user agent sheet.
665 int firstUARule = -1, lastUARule = -1;
666 matchRules(defaultStyle, firstUARule, lastUARule);
668 // 2. In quirks mode, we match rules from the quirks user agent sheet.
670 matchRules(defaultQuirksStyle, firstUARule, lastUARule);
672 // 3. If our medium is print, then we match rules from the print sheet.
673 if (m_medium == "print")
674 matchRules(defaultPrintStyle, firstUARule, lastUARule);
676 // 4. Now we check user sheet rules.
677 int firstUserRule = -1, lastUserRule = -1;
678 matchRules(m_userStyle, firstUserRule, lastUserRule);
680 // 5. Now check author rules, beginning first with presentational attributes
682 int firstAuthorRule = -1, lastAuthorRule = -1;
684 // Ask if the HTML element has mapped attributes.
685 if (htmlElement->hasMappedAttributes()) {
686 // Walk our attribute list and add in each decl.
687 const HTMLNamedAttrMapImpl* map = htmlElement->htmlAttributes();
688 for (uint i = 0; i < map->length(); i++) {
689 HTMLAttributeImpl* attr = map->attributeItem(i);
691 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
692 lastAuthorRule = m_matchedDeclCount;
693 addMatchedDeclaration(attr->decl());
698 // Now we check additional mapped declarations.
699 // Tables and table cells share an additional mapped rule that must be applied
700 // after all attributes, since their mapped style depends on the values of multiple attributes.
701 CSSStyleDeclarationImpl* attributeDecl = htmlElement->additionalAttributeStyleDecl();
703 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
704 lastAuthorRule = m_matchedDeclCount;
705 addMatchedDeclaration(attributeDecl);
709 // 6. Check the rules in author sheets next.
710 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
712 // 7. Now check our inline style attribute.
714 CSSStyleDeclarationImpl* inlineDecl = htmlElement->inlineStyleDecl();
716 if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
717 lastAuthorRule = m_matchedDeclCount;
718 addMatchedDeclaration(inlineDecl);
722 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
723 // high-priority properties first, i.e., those properties that other properties depend on.
724 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
725 // and (4) normal important.
726 applyDeclarations(true, false, 0, m_matchedDeclCount-1);
727 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
728 applyDeclarations(true, true, firstUserRule, lastUserRule);
729 applyDeclarations(true, true, firstUARule, lastUARule);
731 // If our font got dirtied, go ahead and update it now.
733 checkForTextSizeAdjust();
734 checkForGenericFamilyChange(style, parentStyle);
735 style->htmlFont().update(paintDeviceMetrics);
739 // Now do the normal priority properties.
740 applyDeclarations(false, false, 0, m_matchedDeclCount-1);
741 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
742 applyDeclarations(false, true, firstUserRule, lastUserRule);
743 applyDeclarations(false, true, firstUARule, lastUARule);
745 // If our font got dirtied by one of the non-essential font props,
746 // go ahead and update it a second time.
748 checkForTextSizeAdjust();
749 checkForGenericFamilyChange(style, parentStyle);
750 style->htmlFont().update(paintDeviceMetrics);
754 // Clean up our style object's display and text decorations (among other fixups).
755 adjustRenderStyle(style, e);
757 // If we are a link, cache the determined pseudo-state.
759 style->setPseudoState(pseudoState);
761 // Now return the style.
765 RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo,
766 ElementImpl* e, RenderStyle* parentStyle)
771 if (!e->getDocument()->haveStylesheetsLoaded()) {
772 if (!styleNotYetAvailable) {
773 styleNotYetAvailable = ::new RenderStyle();
774 styleNotYetAvailable->setDisplay(NONE);
775 styleNotYetAvailable->ref();
777 return styleNotYetAvailable;
780 initElementAndPseudoState(e);
781 initForStyleResolve(e, parentStyle);
782 pseudoStyle = pseudo;
784 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
787 // Check UA, user and author rules.
788 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
789 matchRules(defaultStyle, firstUARule, lastUARule);
790 matchRules(m_userStyle, firstUserRule, lastUserRule);
791 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
793 if (m_matchedDeclCount == 0)
796 style = new (e->getDocument()->renderArena()) RenderStyle();
798 style->inheritFrom(parentStyle);
801 style->noninherited_flags._styleType = pseudoStyle;
803 // High-priority properties.
804 applyDeclarations(true, false, 0, m_matchedDeclCount-1);
805 applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
806 applyDeclarations(true, true, firstUserRule, lastUserRule);
807 applyDeclarations(true, true, firstUARule, lastUARule);
809 // If our font got dirtied, go ahead and update it now.
811 checkForTextSizeAdjust();
812 checkForGenericFamilyChange(style, parentStyle);
813 style->htmlFont().update(paintDeviceMetrics);
817 // Now do the normal priority properties.
818 applyDeclarations(false, false, 0, m_matchedDeclCount-1);
819 applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
820 applyDeclarations(false, true, firstUserRule, lastUserRule);
821 applyDeclarations(false, true, firstUARule, lastUARule);
823 // If our font got dirtied by one of the non-essential font props,
824 // go ahead and update it a second time.
826 checkForTextSizeAdjust();
827 checkForGenericFamilyChange(style, parentStyle);
828 style->htmlFont().update(paintDeviceMetrics);
832 // Clean up our style object's display and text decorations (among other fixups).
833 adjustRenderStyle(style, 0);
835 // Now return the style.
839 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
841 // Cache our original display.
842 style->setOriginalDisplay(style->display());
844 if (style->display() != NONE) {
845 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
847 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
848 // these tags to retain their display types.
849 if (!strictParsing && e) {
850 if (e->id() == ID_TD) {
851 style->setDisplay(TABLE_CELL);
852 style->setFloating(FNONE);
854 else if (e->id() == ID_TABLE)
855 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
858 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
859 // fix a crash where a site tries to position these objects.
860 if (e && (e->id() == ID_FRAME || e->id() == ID_FRAMESET))
861 style->setPosition(STATIC);
863 // Table headers with a text-align of auto will change the text-align to center.
864 if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
865 style->setTextAlign(CENTER);
867 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
868 // position or float an inline, compact, or run-in. Cache the original display, since it
869 // may be needed for positioned elements that have to compute their static normal flow
870 // positions. We also force inline-level roots to be block-level.
871 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
872 (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE ||
873 (e && e->getDocument()->documentElement() == e))) {
874 if (style->display() == INLINE_TABLE)
875 style->setDisplay(TABLE);
876 else if (style->display() == INLINE_BOX)
877 style->setDisplay(BOX);
878 else if (style->display() == LIST_ITEM) {
879 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
880 // but only in quirks mode.
881 if (!strictParsing && style->floating() != FNONE)
882 style->setDisplay(BLOCK);
885 style->setDisplay(BLOCK);
888 // After performing the display mutation, check table rows. We do not honor position:relative on
889 // table rows. This has been established in CSS2.1 (and caused a crash in containingBlock() on
891 if (style->display() == TABLE_ROW && style->position() == RELATIVE)
892 style->setPosition(STATIC);
895 // Make sure our z-index value is only applied if the object is positioned,
896 // relatively positioned, or transparent.
897 if (style->position() == STATIC && style->opacity() == 1.0f) {
898 if (e && e->getDocument()->documentElement() == e)
899 style->setZIndex(0); // The root has a z-index of 0 if not positioned or transparent.
901 style->setHasAutoZIndex(); // Everyone else gets an auto z-index.
904 // Auto z-index becomes 0 for transparent objects. This prevents cases where
905 // objects that should be blended as a single unit end up with a non-transparent object
906 // wedged in between them.
907 if (style->opacity() < 1.0f && style->hasAutoZIndex())
910 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
911 // tables, inline blocks, inline tables, or run-ins.
912 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
913 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
914 style->setTextDecorationsInEffect(style->textDecoration());
916 style->addToTextDecorationsInEffect(style->textDecoration());
921 bool CSSStyleSelector::checkSelector(CSSSelector* sel, ElementImpl *e)
923 dynamicPseudo = RenderStyle::NOPSEUDO;
927 // we have the subject part of the selector
930 // We track whether or not the rule contains only :hover and :active in a simple selector. If
931 // so, we can't allow that to apply to every element on the page. We assume the author intended
932 // to apply the rules only to links.
933 bool onlyHoverActive = (sel->tag == anyQName &&
934 (sel->match == CSSSelector::Pseudo &&
935 (sel->pseudoType() == CSSSelector::PseudoHover ||
936 sel->pseudoType() == CSSSelector::PseudoActive)));
937 bool affectedByHover = style ? style->affectedByHoverRules() : false;
938 bool affectedByActive = style ? style->affectedByActiveRules() : false;
939 bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
941 // first selector has to match
942 if (!checkOneSelector(sel, e)) return false;
944 // check the subselectors
945 CSSSelector::Relation relation = sel->relation;
946 while((sel = sel->tagHistory))
948 if (!n->isElementNode()) return false;
949 if (relation != CSSSelector::SubSelector) {
951 if (havePseudo && dynamicPseudo != pseudoStyle)
957 case CSSSelector::Descendant:
959 // FIXME: This match needs to know how to backtrack and be non-deterministic.
964 if(!n || !n->isElementNode()) return false;
965 ElementImpl *elem = static_cast<ElementImpl *>(n);
966 if (checkOneSelector(sel, elem)) found = true;
970 case CSSSelector::Child:
974 while (n && n->implicitNode()) n = n->parentNode();
975 if(!n || !n->isElementNode()) return false;
976 ElementImpl *elem = static_cast<ElementImpl *>(n);
977 if (!checkOneSelector(sel, elem)) return false;
980 case CSSSelector::Sibling:
982 n = n->previousSibling();
983 while( n && !n->isElementNode() )
984 n = n->previousSibling();
985 if( !n ) return false;
986 ElementImpl *elem = static_cast<ElementImpl *>(n);
987 if (!checkOneSelector(sel, elem)) return false;
990 case CSSSelector::SubSelector:
993 onlyHoverActive = (sel->match == CSSSelector::Pseudo &&
994 (sel->pseudoType() == CSSSelector::PseudoHover ||
995 sel->pseudoType() == CSSSelector::PseudoActive));
997 //kdDebug() << "CSSOrderedRule::checkSelector" << endl;
998 ElementImpl *elem = static_cast<ElementImpl *>(n);
999 // a selector is invalid if something follows :first-xxx
1000 if (dynamicPseudo != RenderStyle::NOPSEUDO)
1002 if (!checkOneSelector(sel, elem)) return false;
1003 //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl;
1007 relation = sel->relation;
1010 if (subject && havePseudo && dynamicPseudo != pseudoStyle)
1013 // disallow *:hover, *:active, and *:hover:active except for links
1014 if (onlyHoverActive && subject) {
1015 if (pseudoState == PseudoUnknown)
1016 checkPseudoState(e);
1018 if (pseudoState == PseudoNone) {
1019 if (!affectedByHover && style->affectedByHoverRules())
1020 style->setAffectedByHoverRules(false);
1021 if (!affectedByActive && style->affectedByActiveRules())
1022 style->setAffectedByActiveRules(false);
1030 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e)
1035 if (sel->tag != anyQName) {
1036 int eltID = e->id();
1037 Q_UINT16 localName = localNamePart(eltID);
1038 Q_UINT16 ns = namespacePart(eltID);
1039 Q_UINT16 selLocalName = localNamePart(sel->tag);
1040 Q_UINT16 selNS = namespacePart(sel->tag);
1042 if (selNS == xhtmlNamespace && localName < ID_LAST_TAG)
1043 selNS = anyNamespace; // Always match HTML elements even when in HTML docs.
1045 if ((selLocalName != anyLocalName && localName != selLocalName) ||
1046 (selNS != anyNamespace && ns != selNS))
1051 if (sel->match == CSSSelector::Class) {
1054 for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
1055 if (c->string() == sel->value)
1059 else if (sel->match == CSSSelector::Id)
1060 return e->hasID() && e->getIDAttribute() == sel->value;
1061 else if (style && (e != element || !htmlElement || !htmlElement->isMappedAttribute(sel->attr)))
1062 style->setAffectedByAttributeSelectors();
1064 const AtomicString& value = e->getAttribute(sel->attr);
1065 if (value.isNull()) return false; // attribute is not set
1067 switch(sel->match) {
1068 case CSSSelector::Exact:
1069 if ((isXMLDoc && sel->value != value) ||
1070 (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1073 case CSSSelector::List:
1075 int spacePos = value.find(' ', 0);
1076 if (spacePos == -1) {
1077 // There is no list, just a single item. We can avoid
1078 // allocing QStrings and just treat this as an exact
1080 if ((isXMLDoc && sel->value != value) ||
1081 (!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
1086 // The selector's value can't contain a space, or it's totally bogus.
1087 spacePos = sel->value.find(' ');
1091 QString str = value.string();
1092 QString selStr = sel->value.string();
1093 int startSearchAt = 0;
1095 int foundPos = str.find(selStr, startSearchAt, isXMLDoc);
1096 if (foundPos == -1) return false;
1097 if (foundPos == 0 || str[foundPos-1] == ' ') {
1098 uint endStr = foundPos + selStr.length();
1099 if (endStr == str.length() || str[endStr] == ' ')
1100 break; // We found a match.
1103 // No match. Keep looking.
1104 startSearchAt = foundPos + 1;
1109 case CSSSelector::Contain:
1111 //kdDebug( 6080 ) << "checking for contains match" << endl;
1112 QString str = value.string();
1113 QString selStr = sel->value.string();
1114 int pos = str.find(selStr, 0, isXMLDoc);
1115 if(pos == -1) return false;
1118 case CSSSelector::Begin:
1120 //kdDebug( 6080 ) << "checking for beginswith match" << endl;
1121 QString str = value.string();
1122 QString selStr = sel->value.string();
1123 int pos = str.find(selStr, 0, isXMLDoc);
1124 if(pos != 0) return false;
1127 case CSSSelector::End:
1129 //kdDebug( 6080 ) << "checking for endswith match" << endl;
1130 QString str = value.string();
1131 QString selStr = sel->value.string();
1132 if (isXMLDoc && !str.endsWith(selStr)) return false;
1134 int pos = str.length() - selStr.length();
1135 if (pos < 0 || pos != str.find(selStr, pos, false) )
1140 case CSSSelector::Hyphen:
1142 //kdDebug( 6080 ) << "checking for hyphen match" << endl;
1143 QString str = value.string();
1144 QString selStr = sel->value.string();
1145 if(str.length() < selStr.length()) return false;
1146 // Check if str begins with selStr:
1147 if(str.find(selStr, 0, isXMLDoc) != 0) return false;
1148 // It does. Check for exact match or following '-':
1149 if(str.length() != selStr.length()
1150 && str[selStr.length()] != '-') return false;
1157 if(sel->match == CSSSelector::Pseudo)
1159 // Pseudo elements. We need to check first child here. No dynamic pseudo
1160 // elements for the moment
1161 // kdDebug() << "CSSOrderedRule::pseudo " << value << endl;
1162 switch (sel->pseudoType()) {
1163 case CSSSelector::PseudoEmpty:
1164 if (!e->firstChild())
1167 case CSSSelector::PseudoFirstChild: {
1168 // first-child matches the first child that is an element!
1169 if (e->parentNode()) {
1170 DOM::NodeImpl* n = e->previousSibling();
1171 while ( n && !n->isElementNode() )
1172 n = n->previousSibling();
1178 case CSSSelector::PseudoLastChild: {
1179 // last-child matches the last child that is an element!
1180 if (e->parentNode()) {
1181 DOM::NodeImpl* n = e->nextSibling();
1182 while ( n && !n->isElementNode() )
1183 n = n->nextSibling();
1189 case CSSSelector::PseudoOnlyChild: {
1190 // If both first-child and last-child apply, then only-child applies.
1191 if (e->parentNode()) {
1192 DOM::NodeImpl* n = e->previousSibling();
1193 while ( n && !n->isElementNode() )
1194 n = n->previousSibling();
1196 n = e->nextSibling();
1197 while ( n && !n->isElementNode() )
1198 n = n->nextSibling();
1205 case CSSSelector::PseudoFirstLine:
1207 dynamicPseudo=RenderStyle::FIRST_LINE;
1211 case CSSSelector::PseudoFirstLetter:
1213 dynamicPseudo=RenderStyle::FIRST_LETTER;
1217 case CSSSelector::PseudoTarget:
1218 if (e == e->getDocument()->getCSSTarget())
1221 case CSSSelector::PseudoAnyLink:
1222 if (pseudoState == PseudoUnknown)
1223 checkPseudoState(e, false);
1224 if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
1227 case CSSSelector::PseudoLink:
1228 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1229 checkPseudoState( e );
1230 if ( pseudoState == PseudoLink )
1233 case CSSSelector::PseudoVisited:
1234 if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
1235 checkPseudoState( e );
1236 if ( pseudoState == PseudoVisited )
1239 case CSSSelector::PseudoHover: {
1240 // If we're in quirks mode, then hover should never match anchors with no
1241 // href. This is important for sites like wsj.com.
1242 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
1243 if (element == e && style)
1244 style->setAffectedByHoverRules(true);
1245 if (e->renderer()) {
1247 e->renderer()->style()->setAffectedByHoverRules(true);
1248 if (e->renderer()->mouseInside())
1254 case CSSSelector::PseudoDrag: {
1255 if (element == e && style)
1256 style->setAffectedByDragRules(true);
1257 if (e->renderer()) {
1259 e->renderer()->style()->setAffectedByDragRules(true);
1260 if (e->renderer()->isDragging())
1265 case CSSSelector::PseudoFocus:
1266 if (e && e->focused()) {
1270 case CSSSelector::PseudoActive:
1271 // If we're in quirks mode, then :active should never match anchors with no
1273 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
1274 if (element == e && style)
1275 style->setAffectedByActiveRules(true);
1276 else if (e->renderer())
1277 e->renderer()->style()->setAffectedByActiveRules(true);
1282 case CSSSelector::PseudoRoot:
1283 if (e == e->getDocument()->documentElement())
1286 case CSSSelector::PseudoNot: {
1287 // check the simple selector
1288 for (CSSSelector* subSel = sel->simpleSelector; subSel;
1289 subSel = subSel->tagHistory) {
1290 // :not cannot nest. I don't really know why this is a restriction in CSS3,
1291 // but it is, so let's honor it.
1292 if (subSel->simpleSelector)
1294 if (!checkOneSelector(subSel, e))
1299 case CSSSelector::PseudoSelection:
1300 dynamicPseudo = RenderStyle::SELECTION;
1302 case CSSSelector::PseudoBefore:
1303 dynamicPseudo = RenderStyle::BEFORE;
1305 case CSSSelector::PseudoAfter:
1306 dynamicPseudo = RenderStyle::AFTER;
1309 case CSSSelector::PseudoNotParsed:
1312 case CSSSelector::PseudoLang:
1313 /* not supported for now */
1314 case CSSSelector::PseudoOther:
1319 // ### add the rest of the checks...
1323 // -----------------------------------------------------------------
1325 CSSRuleSet::CSSRuleSet()
1327 m_idRules.setAutoDelete(true);
1328 m_classRules.setAutoDelete(true);
1329 m_tagRules.setAutoDelete(true);
1330 m_universalRules = 0;
1334 void CSSRuleSet::addToRuleSet(void* hash, QPtrDict<CSSRuleDataList>& dict,
1335 CSSStyleRuleImpl* rule, CSSSelector* sel)
1338 CSSRuleDataList* rules = dict.find(hash);
1340 rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1341 dict.insert(hash, rules);
1344 rules->append(m_ruleCount++, rule, sel);
1347 void CSSRuleSet::addRule(CSSStyleRuleImpl* rule, CSSSelector* sel)
1349 if (sel->match == CSSSelector::Id) {
1350 addToRuleSet(sel->value.implementation(), m_idRules, rule, sel);
1353 if (sel->match == CSSSelector::Class) {
1354 addToRuleSet(sel->value.implementation(), m_classRules, rule, sel);
1358 Q_UINT16 localName = localNamePart(sel->tag);
1359 if (localName != anyLocalName) {
1360 addToRuleSet((void*)(int)localName, m_tagRules, rule, sel);
1364 // Just put it in the universal rule set.
1365 if (!m_universalRules)
1366 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
1368 m_universalRules->append(m_ruleCount++, rule, sel);
1371 void CSSRuleSet::addRulesFromSheet(CSSStyleSheetImpl *sheet, const DOMString &medium)
1373 if (!sheet || !sheet->isCSSStyleSheet()) return;
1375 // No media implies "all", but if a media list exists it must
1376 // contain our current medium
1377 if (sheet->media() && !sheet->media()->contains(medium))
1378 return; // the style sheet doesn't apply
1380 int len = sheet->length();
1382 for (int i = 0; i < len; i++) {
1383 StyleBaseImpl *item = sheet->item(i);
1384 if (item->isStyleRule()) {
1385 CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(item);
1386 for (CSSSelector* s = rule->selector(); s; s = s->next())
1389 else if(item->isImportRule()) {
1390 CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
1392 //kdDebug( 6080 ) << "@import: Media: "
1393 // << import->media()->mediaText().string() << endl;
1395 if (!import->media() || import->media()->contains(medium))
1396 addRulesFromSheet(import->styleSheet(), medium);
1398 else if(item->isMediaRule()) {
1399 CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl*>(item);
1400 CSSRuleListImpl *rules = r->cssRules();
1402 //DOMString mediaText = media->mediaText();
1403 //kdDebug( 6080 ) << "@media: Media: "
1404 // << r->media()->mediaText().string() << endl;
1406 if ((!r->media() || r->media()->contains(medium)) && rules) {
1407 // Traverse child elements of the @media rule.
1408 for (unsigned j = 0; j < rules->length(); j++) {
1409 //kdDebug( 6080 ) << "*** Rule #" << j << endl;
1411 CSSRuleImpl *childItem = rules->item(j);
1412 if (childItem->isStyleRule()) {
1413 // It is a StyleRule, so append it to our list
1414 CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(childItem);
1415 for (CSSSelector* s = rule->selector(); s; s = s->next())
1421 //kdDebug( 6080 ) << "Ignoring child rule of "
1422 // "ImportRule: rule is not a StyleRule!" << endl;
1428 //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
1429 // << "rule empty or wrong medium!" << endl;
1432 // ### include other rules
1436 // -------------------------------------------------------------------------------------
1437 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1439 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
1442 if ( !primitiveValue ) {
1446 int type = primitiveValue->primitiveType();
1447 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
1448 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
1449 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
1450 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
1451 else if(type == CSSPrimitiveValue::CSS_NUMBER)
1452 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
1453 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
1454 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
1462 // color mapping code
1468 static const colorMap cmap[] = {
1469 { CSS_VAL_AQUA, 0xFF00FFFF },
1470 { CSS_VAL_BLACK, 0xFF000000 },
1471 { CSS_VAL_BLUE, 0xFF0000FF },
1472 { CSS_VAL_FUCHSIA, 0xFFFF00FF },
1473 { CSS_VAL_GRAY, 0xFF808080 },
1474 { CSS_VAL_GREEN, 0xFF008000 },
1475 { CSS_VAL_LIME, 0xFF00FF00 },
1476 { CSS_VAL_MAROON, 0xFF800000 },
1477 { CSS_VAL_NAVY, 0xFF000080 },
1478 { CSS_VAL_OLIVE, 0xFF808000 },
1479 { CSS_VAL_ORANGE, 0xFFFFA500 },
1480 { CSS_VAL_PURPLE, 0xFF800080 },
1481 { CSS_VAL_RED, 0xFFFF0000 },
1482 { CSS_VAL_SILVER, 0xFFC0C0C0 },
1483 { CSS_VAL_TEAL, 0xFF008080 },
1484 { CSS_VAL_WHITE, 0xFFFFFFFF },
1485 { CSS_VAL_YELLOW, 0xFFFFFF00 },
1486 { CSS_VAL_INVERT, invertedColor },
1487 { CSS_VAL_TRANSPARENT, transparentColor },
1488 { CSS_VAL_GREY, 0xFF808080 },
1490 { CSS_VAL_ACTIVEBORDER, 0xFFE0E0E0 },
1491 { CSS_VAL_ACTIVECAPTION, 0xFF000000 },
1492 { CSS_VAL_APPWORKSPACE, 0xFF000000 },
1493 { CSS_VAL_BUTTONFACE, 0xFFC0C0C0 },
1494 { CSS_VAL_BUTTONHIGHLIGHT, 0xFFE0E0E0 },
1495 { CSS_VAL_BUTTONSHADOW, 0xFFFFFFFF },
1496 { CSS_VAL_BUTTONTEXT, 0xFF000000 },
1497 { CSS_VAL_CAPTIONTEXT, 0xFF000000 },
1498 { CSS_VAL_GRAYTEXT, 0xFF000000 },
1499 { CSS_VAL_HIGHLIGHT, 0xFFFFFFFF },
1500 { CSS_VAL_HIGHLIGHTTEXT, 0xFFFFFFFF },
1501 { CSS_VAL_INACTIVEBORDER, 0xFFFFFFFF },
1502 { CSS_VAL_INACTIVECAPTION, 0xFFFFFFFF },
1503 { CSS_VAL_INACTIVECAPTIONTEXT, 0xFF000000 },
1504 { CSS_VAL_INFOBACKGROUND, 0xFF000000 },
1505 { CSS_VAL_INFOTEXT, 0xFF000000 },
1506 { CSS_VAL_MENU, 0xFFFFFFFF },
1507 { CSS_VAL_MENUTEXT, 0xFFFFFFFF },
1508 { CSS_VAL_SCROLLBAR, 0xFFFFFFFF },
1509 { CSS_VAL_TEXT, 0xFF000000 },
1510 { CSS_VAL_THREEDDARKSHADOW, 0xFF404040 },
1511 { CSS_VAL_THREEDFACE, 0xFFC0C0C0 },
1512 { CSS_VAL_THREEDHIGHLIGHT, 0xFFE0E0E0 },
1513 { CSS_VAL_THREEDLIGHTSHADOW, 0xFFC0C0C0 },
1514 { CSS_VAL_THREEDSHADOW, 0xFFFFFFFF },
1515 { CSS_VAL_WINDOW, 0xFFFFFFFF },
1516 { CSS_VAL_WINDOWFRAME, 0xFFFFFFFF },
1517 { CSS_VAL_WINDOWTEXT, 0xFF000000 },
1526 const char * configGroup;
1527 const char * configEntry;
1528 QPalette::ColorGroup group;
1529 QColorGroup::ColorRole role;
1532 const char * const wmgroup = "WM";
1533 const char * const generalgroup = "General";
1535 /* Mapping system settings to CSS 2
1536 * Tried hard to get an appropriate mapping - schlpbch
1538 static const uiColors uimap[] = {
1539 // Active window border.
1540 { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light },
1541 // Active window caption.
1542 { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text },
1543 // Text in caption, size box, and scrollbar arrow box.
1544 { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text },
1545 // Face color for three-dimensional display elements.
1546 { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1547 // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
1548 { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1549 // Shadow color for three-dimensional display elements.
1550 { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1551 // Text on push buttons.
1552 { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText },
1553 // Dark shadow for three-dimensional display elements.
1554 { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark },
1555 // Face color for three-dimensional display elements.
1556 { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button },
1557 // Highlight color for three-dimensional display elements.
1558 { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light },
1559 // Light color for three-dimensional display elements (for edges facing the light source).
1560 { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight },
1561 // Dark shadow for three-dimensional display elements.
1562 { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow },
1564 // Inactive window border.
1565 { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background },
1566 // Inactive window caption.
1567 { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background },
1568 // Color of text in an inactive caption.
1569 { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text },
1570 { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text },
1573 { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1575 { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background },
1577 // Text of item(s) selected in a control.
1578 { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background },
1580 // Text of item(s) selected in a control.
1581 { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background },
1583 // Background color of multiple document interface.
1584 { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text },
1586 // Scroll bar gray area.
1587 { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background },
1589 // Window background.
1590 { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1592 { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background },
1594 { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text },
1595 { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text },
1596 { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles }
1599 #endif // !APPLE_CHANGES
1601 static QColor colorForCSSValue( int css_value )
1603 // try the regular ones first
1604 const colorMap *col = cmap;
1605 while ( col->css_value && col->css_value != css_value )
1607 if ( col->css_value )
1613 const uiColors *uicol = uimap;
1614 while ( uicol->css_value && uicol->css_value != css_value )
1616 if ( !uicol->css_value ) {
1617 if ( css_value == CSS_VAL_INFOBACKGROUND )
1618 return QToolTip::palette().inactive().background();
1619 else if ( css_value == CSS_VAL_INFOTEXT )
1620 return QToolTip::palette().inactive().foreground();
1621 else if ( css_value == CSS_VAL_BACKGROUND ) {
1622 KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
1623 bckgrConfig.setGroup("Desktop0");
1624 // Desktop background.
1625 return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background());
1627 return khtml::invalidColor;
1630 const QPalette &pal = qApp->palette();
1631 QColor c = pal.color( uicol->group, uicol->role );
1632 if ( uicol->configEntry ) {
1633 KConfig *globalConfig = KGlobal::config();
1634 globalConfig->setGroup( uicol->configGroup );
1635 c = globalConfig->readColorEntry( uicol->configEntry, &c );
1642 void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
1643 int startIndex, int endIndex)
1645 if (startIndex == -1) return;
1646 for (int i = startIndex; i <= endIndex; i++) {
1647 CSSStyleDeclarationImpl* decl = m_matchedDecls[i];
1648 QPtrList<CSSProperty>* props = decl->values();
1650 QPtrListIterator<CSSProperty> propertyIt(*props);
1651 CSSProperty* current;
1652 for (propertyIt.toFirst(); (current = propertyIt.current()); ++propertyIt) {
1653 // give special priority to font-xxx, color properties
1654 if (isImportant == current->isImportant()) {
1656 switch(current->id())
1658 case CSS_PROP_BACKGROUND:
1659 case CSS_PROP_BACKGROUND_IMAGE:
1660 case CSS_PROP_COLOR:
1661 case CSS_PROP_DISPLAY:
1663 case CSS_PROP_FONT_SIZE:
1664 case CSS_PROP_FONT_STYLE:
1665 case CSS_PROP_FONT_FAMILY:
1666 case CSS_PROP_FONT_WEIGHT:
1668 case CSS_PROP__APPLE_TEXT_SIZE_ADJUST:
1670 // these have to be applied first, because other properties use the computed
1671 // values of these porperties.
1679 if (first == applyFirst)
1680 applyProperty(current->id(), current->value());
1687 void CSSStyleSelector::applyProperty( int id, DOM::CSSValueImpl *value )
1689 //kdDebug( 6080 ) << "applying property " << prop->m_id << endl;
1691 CSSPrimitiveValueImpl *primitiveValue = 0;
1692 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
1697 bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1698 bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
1699 (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
1701 // What follows is a list that maps the CSS properties into their corresponding front-end
1702 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
1703 // are only hit when mapping "inherit" or "initial" into front-end values.
1706 // ident only properties
1707 case CSS_PROP_BACKGROUND_ATTACHMENT:
1708 HANDLE_INHERIT_AND_INITIAL(backgroundAttachment, BackgroundAttachment)
1709 if(!primitiveValue) break;
1710 switch(primitiveValue->getIdent())
1714 style->setBackgroundAttachment(false);
1715 // only use slow repaints if we actually have a background pixmap
1716 if( style->backgroundImage() && view )
1717 view->useSlowRepaints();
1720 case CSS_VAL_SCROLL:
1721 style->setBackgroundAttachment(true);
1726 case CSS_PROP_BACKGROUND_REPEAT:
1728 HANDLE_INHERIT_AND_INITIAL(backgroundRepeat, BackgroundRepeat)
1729 if(!primitiveValue) return;
1730 switch(primitiveValue->getIdent())
1732 case CSS_VAL_REPEAT:
1733 style->setBackgroundRepeat( REPEAT );
1735 case CSS_VAL_REPEAT_X:
1736 style->setBackgroundRepeat( REPEAT_X );
1738 case CSS_VAL_REPEAT_Y:
1739 style->setBackgroundRepeat( REPEAT_Y );
1741 case CSS_VAL_NO_REPEAT:
1742 style->setBackgroundRepeat( NO_REPEAT );
1748 case CSS_PROP_BORDER_COLLAPSE:
1749 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
1750 if(!primitiveValue) break;
1751 switch(primitiveValue->getIdent())
1753 case CSS_VAL_COLLAPSE:
1754 style->setBorderCollapse(true);
1756 case CSS_VAL_SEPARATE:
1757 style->setBorderCollapse(false);
1764 case CSS_PROP_BORDER_TOP_STYLE:
1765 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
1766 if (!primitiveValue) return;
1767 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1769 case CSS_PROP_BORDER_RIGHT_STYLE:
1770 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
1771 if (!primitiveValue) return;
1772 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1774 case CSS_PROP_BORDER_BOTTOM_STYLE:
1775 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
1776 if (!primitiveValue) return;
1777 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1779 case CSS_PROP_BORDER_LEFT_STYLE:
1780 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
1781 if (!primitiveValue) return;
1782 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1784 case CSS_PROP_OUTLINE_STYLE:
1785 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
1786 if (!primitiveValue) return;
1787 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
1788 style->setOutlineStyle(DOTTED, true);
1790 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE));
1792 case CSS_PROP_CAPTION_SIDE:
1794 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
1795 if(!primitiveValue) break;
1796 ECaptionSide c = RenderStyle::initialCaptionSide();
1797 switch(primitiveValue->getIdent())
1802 c = CAPRIGHT; break;
1805 case CSS_VAL_BOTTOM:
1806 c = CAPBOTTOM; break;
1810 style->setCaptionSide(c);
1813 case CSS_PROP_CLEAR:
1815 HANDLE_INHERIT_AND_INITIAL(clear, Clear)
1816 if(!primitiveValue) break;
1818 switch(primitiveValue->getIdent())
1834 case CSS_PROP_DIRECTION:
1836 HANDLE_INHERIT_AND_INITIAL(direction, Direction)
1837 if(!primitiveValue) break;
1838 style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
1841 case CSS_PROP_DISPLAY:
1843 HANDLE_INHERIT_AND_INITIAL(display, Display)
1844 if(!primitiveValue) break;
1845 int id = primitiveValue->getIdent();
1847 if (id == CSS_VAL_NONE)
1850 d = EDisplay(primitiveValue->getIdent() - CSS_VAL_INLINE);
1852 style->setDisplay(d);
1853 //kdDebug( 6080 ) << "setting display to " << d << endl;
1858 case CSS_PROP_EMPTY_CELLS:
1860 HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
1861 if (!primitiveValue) break;
1862 int id = primitiveValue->getIdent();
1863 if (id == CSS_VAL_SHOW)
1864 style->setEmptyCells(SHOW);
1865 else if (id == CSS_VAL_HIDE)
1866 style->setEmptyCells(HIDE);
1869 case CSS_PROP_FLOAT:
1871 HANDLE_INHERIT_AND_INITIAL(floating, Floating)
1872 if(!primitiveValue) return;
1874 switch(primitiveValue->getIdent())
1881 case CSS_VAL_CENTER: //Non standart CSS-Value
1887 style->setFloating(f);
1892 case CSS_PROP_FONT_STRETCH:
1893 break; /* Not supported. */
1895 case CSS_PROP_FONT_STYLE:
1897 FontDef fontDef = style->htmlFont().fontDef;
1899 fontDef.italic = parentStyle->htmlFont().fontDef.italic;
1901 fontDef.italic = false;
1903 if(!primitiveValue) return;
1904 switch(primitiveValue->getIdent()) {
1905 case CSS_VAL_OBLIQUE:
1906 // ### oblique is the same as italic for the moment...
1907 case CSS_VAL_ITALIC:
1908 fontDef.italic = true;
1910 case CSS_VAL_NORMAL:
1911 fontDef.italic = false;
1917 if (style->setFontDef( fontDef ))
1923 case CSS_PROP_FONT_VARIANT:
1925 FontDef fontDef = style->htmlFont().fontDef;
1927 fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps;
1929 fontDef.smallCaps = false;
1931 if(!primitiveValue) return;
1932 int id = primitiveValue->getIdent();
1933 if ( id == CSS_VAL_NORMAL )
1934 fontDef.smallCaps = false;
1935 else if ( id == CSS_VAL_SMALL_CAPS )
1936 fontDef.smallCaps = true;
1940 if (style->setFontDef( fontDef ))
1945 case CSS_PROP_FONT_WEIGHT:
1947 FontDef fontDef = style->htmlFont().fontDef;
1949 fontDef.weight = parentStyle->htmlFont().fontDef.weight;
1951 fontDef.weight = QFont::Normal;
1953 if(!primitiveValue) return;
1954 if(primitiveValue->getIdent())
1956 switch(primitiveValue->getIdent()) {
1957 // ### we just support normal and bold fonts at the moment...
1958 // setWeight can actually accept values between 0 and 99...
1960 case CSS_VAL_BOLDER:
1965 fontDef.weight = QFont::Bold;
1967 case CSS_VAL_NORMAL:
1968 case CSS_VAL_LIGHTER:
1974 fontDef.weight = QFont::Normal;
1982 // ### fix parsing of 100-900 values in parser, apply them here
1985 if (style->setFontDef( fontDef ))
1990 case CSS_PROP_LIST_STYLE_POSITION:
1992 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
1993 if (!primitiveValue) return;
1994 if (primitiveValue->getIdent())
1995 style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
1999 case CSS_PROP_LIST_STYLE_TYPE:
2001 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
2002 if (!primitiveValue) return;
2003 if (primitiveValue->getIdent())
2006 int id = primitiveValue->getIdent();
2007 if ( id == CSS_VAL_NONE) { // important!!
2010 t = EListStyleType(id - CSS_VAL_DISC);
2012 style->setListStyleType(t);
2017 case CSS_PROP_OVERFLOW:
2019 HANDLE_INHERIT_AND_INITIAL(overflow, Overflow)
2020 if (!primitiveValue) return;
2022 switch(primitiveValue->getIdent())
2024 case CSS_VAL_VISIBLE:
2025 o = OVISIBLE; break;
2026 case CSS_VAL_HIDDEN:
2028 case CSS_VAL_SCROLL:
2032 case CSS_VAL_MARQUEE:
2033 o = OMARQUEE; break;
2034 case CSS_VAL_OVERLAY:
2035 o = OOVERLAY; break;
2039 style->setOverflow(o);
2043 case CSS_PROP_PAGE_BREAK_BEFORE:
2045 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2046 if (!primitiveValue) return;
2047 switch (primitiveValue->getIdent()) {
2049 style->setPageBreakBefore(PBAUTO);
2053 case CSS_VAL_ALWAYS:
2054 style->setPageBreakBefore(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2057 style->setPageBreakBefore(PBAVOID);
2063 case CSS_PROP_PAGE_BREAK_AFTER:
2065 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2066 if (!primitiveValue) return;
2067 switch (primitiveValue->getIdent()) {
2069 style->setPageBreakAfter(PBAUTO);
2073 case CSS_VAL_ALWAYS:
2074 style->setPageBreakAfter(PBALWAYS); // CSS2.1: "Conforming user agents may map left/right to always."
2077 style->setPageBreakAfter(PBAVOID);
2083 case CSS_PROP_PAGE_BREAK_INSIDE: {
2084 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2085 if (!primitiveValue) return;
2086 if (primitiveValue->getIdent() == CSS_VAL_AUTO)
2087 style->setPageBreakInside(PBAUTO);
2088 else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
2089 style->setPageBreakInside(PBAVOID);
2094 break; /* FIXME: Not even sure what this is... -dwh */
2096 case CSS_PROP_POSITION:
2098 HANDLE_INHERIT_AND_INITIAL(position, Position)
2099 if(!primitiveValue) return;
2101 switch(primitiveValue->getIdent())
2103 case CSS_VAL_STATIC:
2105 case CSS_VAL_RELATIVE:
2106 p = RELATIVE; break;
2107 case CSS_VAL_ABSOLUTE:
2108 p = ABSOLUTE; break;
2112 view->useSlowRepaints();
2119 style->setPosition(p);
2123 case CSS_PROP_TABLE_LAYOUT: {
2124 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
2126 if ( !primitiveValue->getIdent() )
2129 ETableLayout l = RenderStyle::initialTableLayout();
2130 switch( primitiveValue->getIdent() ) {
2135 style->setTableLayout( l );
2142 case CSS_PROP_UNICODE_BIDI: {
2143 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
2144 switch (primitiveValue->getIdent()) {
2145 case CSS_VAL_NORMAL:
2146 style->setUnicodeBidi(UBNormal);
2149 style->setUnicodeBidi(Embed);
2151 case CSS_VAL_BIDI_OVERRIDE:
2152 style->setUnicodeBidi(Override);
2159 case CSS_PROP_TEXT_TRANSFORM: {
2160 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
2162 if(!primitiveValue->getIdent()) return;
2165 switch(primitiveValue->getIdent()) {
2166 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break;
2167 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break;
2168 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break;
2170 default: tt = TTNONE; break;
2172 style->setTextTransform(tt);
2176 case CSS_PROP_VISIBILITY:
2178 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
2180 switch( primitiveValue->getIdent() ) {
2181 case CSS_VAL_HIDDEN:
2182 style->setVisibility( HIDDEN );
2184 case CSS_VAL_VISIBLE:
2185 style->setVisibility( VISIBLE );
2187 case CSS_VAL_COLLAPSE:
2188 style->setVisibility( COLLAPSE );
2194 case CSS_PROP_WHITE_SPACE:
2195 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
2197 if(!primitiveValue->getIdent()) return;
2200 switch(primitiveValue->getIdent()) {
2201 case CSS_VAL__KHTML_NOWRAP:
2204 case CSS_VAL_NOWRAP:
2210 case CSS_VAL_NORMAL:
2215 style->setWhiteSpace(s);
2218 case CSS_PROP_BACKGROUND_POSITION:
2220 style->setBackgroundXPosition(parentStyle->backgroundXPosition());
2221 style->setBackgroundYPosition(parentStyle->backgroundYPosition());
2223 else if (isInitial) {
2224 style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
2225 style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
2228 case CSS_PROP_BACKGROUND_POSITION_X: {
2229 HANDLE_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition)
2230 if(!primitiveValue) break;
2232 int type = primitiveValue->primitiveType();
2233 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2234 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2235 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2236 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2239 style->setBackgroundXPosition(l);
2242 case CSS_PROP_BACKGROUND_POSITION_Y: {
2243 HANDLE_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition)
2244 if(!primitiveValue) break;
2246 int type = primitiveValue->primitiveType();
2247 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2248 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2249 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2250 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2253 style->setBackgroundYPosition(l);
2256 case CSS_PROP_BORDER_SPACING: {
2257 if(value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
2258 style->setHorizontalBorderSpacing(parentStyle->horizontalBorderSpacing());
2259 style->setVerticalBorderSpacing(parentStyle->verticalBorderSpacing());
2262 case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
2263 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
2264 if (!primitiveValue) break;
2265 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
2266 style->setHorizontalBorderSpacing(spacing);
2269 case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
2270 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
2271 if (!primitiveValue) break;
2272 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
2273 style->setVerticalBorderSpacing(spacing);
2276 case CSS_PROP_CURSOR:
2277 HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
2279 style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
2281 // colors || inherit
2282 case CSS_PROP_BACKGROUND_COLOR:
2283 case CSS_PROP_BORDER_TOP_COLOR:
2284 case CSS_PROP_BORDER_RIGHT_COLOR:
2285 case CSS_PROP_BORDER_BOTTOM_COLOR:
2286 case CSS_PROP_BORDER_LEFT_COLOR:
2287 case CSS_PROP_COLOR:
2288 case CSS_PROP_OUTLINE_COLOR:
2289 // this property is an extension used to get HTML4 <font> right.
2291 case CSS_PROP_SCROLLBAR_FACE_COLOR:
2292 case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2293 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2294 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2295 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2296 case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2297 case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2302 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
2303 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
2304 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
2305 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
2306 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
2307 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
2308 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
2311 else if (isInitial) {
2312 // The border/outline colors will just map to the invalid color |col| above. This will have the
2313 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
2314 // not painting the background since the color won't be valid).
2315 if (id == CSS_PROP_COLOR)
2316 col = RenderStyle::initialColor();
2321 col = getColorFromPrimitiveValue(primitiveValue);
2324 //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
2327 case CSS_PROP_BACKGROUND_COLOR:
2328 style->setBackgroundColor(col); break;
2329 case CSS_PROP_BORDER_TOP_COLOR:
2330 style->setBorderTopColor(col); break;
2331 case CSS_PROP_BORDER_RIGHT_COLOR:
2332 style->setBorderRightColor(col); break;
2333 case CSS_PROP_BORDER_BOTTOM_COLOR:
2334 style->setBorderBottomColor(col); break;
2335 case CSS_PROP_BORDER_LEFT_COLOR:
2336 style->setBorderLeftColor(col); break;
2337 case CSS_PROP_COLOR:
2338 style->setColor(col); break;
2339 case CSS_PROP_OUTLINE_COLOR:
2340 style->setOutlineColor(col); break;
2342 case CSS_PROP_SCROLLBAR_FACE_COLOR:
2343 style->setPaletteColor(QPalette::Active, QColorGroup::Button, col);
2344 style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col);
2346 case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
2347 style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col);
2348 style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col);
2350 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
2351 style->setPaletteColor(QPalette::Active, QColorGroup::Light, col);
2352 style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col);
2354 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
2356 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
2357 style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col);
2358 style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col);
2360 case CSS_PROP_SCROLLBAR_TRACK_COLOR:
2361 style->setPaletteColor(QPalette::Active, QColorGroup::Base, col);
2362 style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col);
2363 style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col);
2364 style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col);
2365 style->setPaletteColor(QPalette::Active, QColorGroup::Background, col);
2366 style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col);
2368 case CSS_PROP_SCROLLBAR_ARROW_COLOR:
2369 style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col);
2370 style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col);
2380 case CSS_PROP_BACKGROUND_IMAGE:
2382 HANDLE_INHERIT_AND_INITIAL(backgroundImage, BackgroundImage)
2383 if (!primitiveValue) return;
2384 style->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)
2385 ->image(element->getDocument()->docLoader()));
2386 //kdDebug( 6080 ) << "setting image in style to " << image->image() << endl;
2389 case CSS_PROP_LIST_STYLE_IMAGE:
2391 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
2392 if (!primitiveValue) return;
2393 style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)
2394 ->image(element->getDocument()->docLoader()));
2395 //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
2400 case CSS_PROP_BORDER_TOP_WIDTH:
2401 case CSS_PROP_BORDER_RIGHT_WIDTH:
2402 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2403 case CSS_PROP_BORDER_LEFT_WIDTH:
2404 case CSS_PROP_OUTLINE_WIDTH:
2407 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
2408 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
2409 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
2410 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
2411 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
2414 else if (isInitial) {
2415 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
2416 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
2417 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
2418 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
2419 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
2423 if(!primitiveValue) break;
2425 switch(primitiveValue->getIdent())
2430 case CSS_VAL_MEDIUM:
2436 case CSS_VAL_INVALID:
2437 width = primitiveValue->computeLength(style, paintDeviceMetrics);
2443 if(width < 0) return;
2446 case CSS_PROP_BORDER_TOP_WIDTH:
2447 style->setBorderTopWidth(width);
2449 case CSS_PROP_BORDER_RIGHT_WIDTH:
2450 style->setBorderRightWidth(width);
2452 case CSS_PROP_BORDER_BOTTOM_WIDTH:
2453 style->setBorderBottomWidth(width);
2455 case CSS_PROP_BORDER_LEFT_WIDTH:
2456 style->setBorderLeftWidth(width);
2458 case CSS_PROP_OUTLINE_WIDTH:
2459 style->setOutlineWidth(width);
2467 case CSS_PROP_LETTER_SPACING:
2468 case CSS_PROP_WORD_SPACING:
2472 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
2473 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
2476 else if (isInitial) {
2477 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
2478 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
2483 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){
2486 if(!primitiveValue) return;
2487 width = primitiveValue->computeLength(style, paintDeviceMetrics);
2491 case CSS_PROP_LETTER_SPACING:
2492 style->setLetterSpacing(width);
2494 case CSS_PROP_WORD_SPACING:
2495 style->setWordSpacing(width);
2497 // ### needs the definitions in renderstyle
2504 case CSS_PROP_MAX_WIDTH:
2506 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2510 case CSS_PROP_RIGHT:
2511 case CSS_PROP_BOTTOM:
2512 case CSS_PROP_WIDTH:
2513 case CSS_PROP_MIN_WIDTH:
2514 case CSS_PROP_MARGIN_TOP:
2515 case CSS_PROP_MARGIN_RIGHT:
2516 case CSS_PROP_MARGIN_BOTTOM:
2517 case CSS_PROP_MARGIN_LEFT:
2519 if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) {
2520 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2521 l = Length(Intrinsic);
2524 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2525 l = Length(MinIntrinsic);
2529 if (id != CSS_PROP_MAX_WIDTH && primitiveValue &&
2530 primitiveValue->getIdent() == CSS_VAL_AUTO)
2532 //kdDebug( 6080 ) << "found value=auto" << endl;
2535 case CSS_PROP_PADDING_TOP:
2536 case CSS_PROP_PADDING_RIGHT:
2537 case CSS_PROP_PADDING_BOTTOM:
2538 case CSS_PROP_PADDING_LEFT:
2539 case CSS_PROP_TEXT_INDENT:
2543 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
2544 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
2545 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
2546 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
2547 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
2548 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
2549 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
2550 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
2551 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
2552 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
2553 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
2554 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
2555 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
2556 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
2557 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
2558 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
2561 else if (isInitial) {
2562 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
2563 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
2564 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
2565 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
2566 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
2567 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
2568 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
2569 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
2570 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
2571 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
2572 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
2573 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
2574 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
2575 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
2576 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
2577 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
2581 if (primitiveValue && !apply) {
2582 int type = primitiveValue->primitiveType();
2583 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2584 // Handle our quirky margin units if we have them.
2585 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed,
2586 primitiveValue->isQuirkValue());
2587 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2588 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2589 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
2590 l = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
2593 if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT ||
2594 id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM)
2595 // Padding can't be negative
2596 apply = !((l.isFixed() || l.isPercent()) && l.width(100) < 0);
2603 case CSS_PROP_MAX_WIDTH:
2604 style->setMaxWidth(l); break;
2605 case CSS_PROP_BOTTOM:
2606 style->setBottom(l); break;
2608 style->setTop(l); break;
2610 style->setLeft(l); break;
2611 case CSS_PROP_RIGHT:
2612 style->setRight(l); break;
2613 case CSS_PROP_WIDTH:
2614 style->setWidth(l); break;
2615 case CSS_PROP_MIN_WIDTH:
2616 style->setMinWidth(l); break;
2617 case CSS_PROP_PADDING_TOP:
2618 style->setPaddingTop(l); break;
2619 case CSS_PROP_PADDING_RIGHT:
2620 style->setPaddingRight(l); break;
2621 case CSS_PROP_PADDING_BOTTOM:
2622 style->setPaddingBottom(l); break;
2623 case CSS_PROP_PADDING_LEFT:
2624 style->setPaddingLeft(l); break;
2625 case CSS_PROP_MARGIN_TOP:
2626 style->setMarginTop(l); break;
2627 case CSS_PROP_MARGIN_RIGHT:
2628 style->setMarginRight(l); break;
2629 case CSS_PROP_MARGIN_BOTTOM:
2630 style->setMarginBottom(l); break;
2631 case CSS_PROP_MARGIN_LEFT:
2632 style->setMarginLeft(l); break;
2633 case CSS_PROP_TEXT_INDENT:
2634 style->setTextIndent(l); break;
2640 case CSS_PROP_MAX_HEIGHT:
2641 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)
2643 case CSS_PROP_HEIGHT:
2644 case CSS_PROP_MIN_HEIGHT:
2645 if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) {
2646 l = Length(Intrinsic);
2649 else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) {
2650 l = Length(MinIntrinsic);
2653 if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
2654 primitiveValue->getIdent() == CSS_VAL_AUTO)
2657 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
2658 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
2659 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
2662 else if (isInitial) {
2663 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
2664 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
2665 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
2669 if (primitiveValue && !apply)
2671 int type = primitiveValue->primitiveType();
2672 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2673 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
2674 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2676 // ### compute from parents height!!!
2677 l = Length((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
2686 case CSS_PROP_MAX_HEIGHT:
2687 style->setMaxHeight(l); break;
2688 case CSS_PROP_HEIGHT:
2689 style->setHeight(l); break;
2690 case CSS_PROP_MIN_HEIGHT:
2691 style->setMinHeight(l); break;
2699 case CSS_PROP_VERTICAL_ALIGN:
2700 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2701 if (!primitiveValue) return;
2702 if (primitiveValue->getIdent()) {
2703 khtml::EVerticalAlign align;
2705 switch(primitiveValue->getIdent())
2709 case CSS_VAL_BOTTOM:
2710 align = BOTTOM; break;
2711 case CSS_VAL_MIDDLE:
2712 align = MIDDLE; break;
2713 case CSS_VAL_BASELINE:
2714 align = BASELINE; break;
2715 case CSS_VAL_TEXT_BOTTOM:
2716 align = TEXT_BOTTOM; break;
2717 case CSS_VAL_TEXT_TOP:
2718 align = TEXT_TOP; break;
2722 align = SUPER; break;
2723 case CSS_VAL__KHTML_BASELINE_MIDDLE:
2724 align = BASELINE_MIDDLE; break;
2728 style->setVerticalAlign(align);
2731 int type = primitiveValue->primitiveType();
2733 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2734 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
2735 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2736 l = Length( int( primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
2738 style->setVerticalAlign( LENGTH );
2739 style->setVerticalAlignLength( l );
2743 case CSS_PROP_FONT_SIZE:
2745 FontDef fontDef = style->htmlFont().fontDef;
2749 bool parentIsAbsoluteSize = false;
2751 oldSize = parentStyle->htmlFont().fontDef.specifiedSize;
2752 parentIsAbsoluteSize = parentStyle->htmlFont().fontDef.isAbsoluteSize;
2758 size = fontSizeForKeyword(CSS_VAL_MEDIUM, style->htmlHacks());
2759 else if (primitiveValue->getIdent()) {
2760 // Keywords are being used.
2761 switch (primitiveValue->getIdent()) {
2762 case CSS_VAL_XX_SMALL:
2763 case CSS_VAL_X_SMALL:
2765 case CSS_VAL_MEDIUM:
2767 case CSS_VAL_X_LARGE:
2768 case CSS_VAL_XX_LARGE:
2769 case CSS_VAL__KHTML_XXX_LARGE:
2770 size = fontSizeForKeyword(primitiveValue->getIdent(), style->htmlHacks());
2772 case CSS_VAL_LARGER:
2773 size = largerFontSize(oldSize, style->htmlHacks());
2775 case CSS_VAL_SMALLER:
2776 size = smallerFontSize(oldSize, style->htmlHacks());
2782 fontDef.isAbsoluteSize = parentIsAbsoluteSize &&
2783 (primitiveValue->getIdent() == CSS_VAL_LARGER ||
2784 primitiveValue->getIdent() == CSS_VAL_SMALLER);
2786 int type = primitiveValue->primitiveType();
2787 fontDef.isAbsoluteSize = parentIsAbsoluteSize ||
2788 (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
2789 type != CSSPrimitiveValue::CSS_EMS &&
2790 type != CSSPrimitiveValue::CSS_EXS);
2791 if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
2792 size = primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics, false);
2793 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
2794 size = (primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
2800 if (size <= 0) return;
2802 //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
2804 setFontSize(fontDef, size);
2805 if (style->setFontDef( fontDef ))
2810 case CSS_PROP_Z_INDEX:
2812 HANDLE_INHERIT(zIndex, ZIndex)
2813 else if (isInitial) {
2814 style->setHasAutoZIndex();
2818 if (!primitiveValue)
2821 if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
2822 style->setHasAutoZIndex();
2826 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2827 return; // Error case.
2829 style->setZIndex((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2834 case CSS_PROP_WIDOWS:
2836 HANDLE_INHERIT_AND_INITIAL(widows, Widows)
2837 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2839 style->setWidows((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2843 case CSS_PROP_ORPHANS:
2845 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
2846 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
2848 style->setOrphans((int)primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER));
2852 // length, percent, number
2853 case CSS_PROP_LINE_HEIGHT:
2855 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
2856 if(!primitiveValue) return;
2858 int type = primitiveValue->primitiveType();
2859 if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
2860 lineHeight = Length( -100, Percent );
2861 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
2862 double multiplier = 1.0;
2863 // Scale for the font zoom factor only for types other than "em" and "ex", since those are
2864 // already based on the font size.
2865 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) {
2866 multiplier = view->part()->zoomFactor() / 100.0;
2868 lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics, multiplier), Fixed);
2869 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2870 lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
2871 else if (type == CSSPrimitiveValue::CSS_NUMBER)
2872 lineHeight = Length(int(primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
2875 style->setLineHeight(lineHeight);
2880 case CSS_PROP_TEXT_ALIGN:
2882 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
2883 if (!primitiveValue) return;
2884 if (primitiveValue->getIdent())
2885 style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
2896 bool hasClip = true;
2898 if (parentStyle->hasClip()) {
2899 top = parentStyle->clipTop();
2900 right = parentStyle->clipRight();
2901 bottom = parentStyle->clipBottom();
2902 left = parentStyle->clipLeft();
2906 top = right = bottom = left = Length();
2908 } else if (isInitial) {
2910 top = right = bottom = left = Length();
2911 } else if ( !primitiveValue ) {
2913 } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT ) {
2914 RectImpl *rect = primitiveValue->getRectValue();
2917 top = convertToLength( rect->top(), style, paintDeviceMetrics );
2918 right = convertToLength( rect->right(), style, paintDeviceMetrics );
2919 bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
2920 left = convertToLength( rect->left(), style, paintDeviceMetrics );
2922 } else if ( primitiveValue->getIdent() != CSS_VAL_AUTO ) {
2925 // qDebug("setting clip top to %d", top.value );
2926 // qDebug("setting clip right to %d", right.value );
2927 // qDebug("setting clip bottom to %d", bottom.value );
2928 // qDebug("setting clip left to %d", left.value );
2929 style->setClip(top, right, bottom, left);
2930 style->setHasClip(hasClip);
2937 case CSS_PROP_CONTENT:
2938 // list of string, uri, counter, attr, i
2940 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2941 // note is a reminder that eventually "inherit" needs to be supported.
2942 if (!(style->styleType()==RenderStyle::BEFORE ||
2943 style->styleType()==RenderStyle::AFTER))
2947 if (style->contentData())
2948 style->contentData()->clearContent();
2952 if(!value->isValueList()) return;
2953 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
2954 int len = list->length();
2956 for(int i = 0; i < len; i++) {
2957 CSSValueImpl *item = list->item(i);
2958 if(!item->isPrimitiveValue()) continue;
2959 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
2960 if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
2962 style->setContent(val->getStringValue(), i != 0);
2964 else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
2966 // FIXME: Should work with generic XML attributes also, and not
2967 // just the hardcoded HTML set. Can a namespace be specified for
2969 int attrID = element->getDocument()->attrId(0, val->getStringValue(), false);
2971 style->setContent(element->getAttribute(attrID).implementation(), i != 0);
2973 else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
2975 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
2976 style->setContent(image->image(element->getDocument()->docLoader()), i != 0);
2983 case CSS_PROP_COUNTER_INCREMENT:
2984 // list of CSS2CounterIncrement
2985 case CSS_PROP_COUNTER_RESET:
2986 // list of CSS2CounterReset
2988 case CSS_PROP_FONT_FAMILY:
2989 // list of strings and ids
2992 FontDef parentFontDef = parentStyle->htmlFont().fontDef;
2993 FontDef fontDef = style->htmlFont().fontDef;
2994 fontDef.genericFamily = parentFontDef.genericFamily;
2995 fontDef.family = parentFontDef.family;
2996 if (style->setFontDef(fontDef))
3000 else if (isInitial) {
3001 FontDef fontDef = style->htmlFont().fontDef;
3002 FontDef initialDef = FontDef();
3003 fontDef.genericFamily = initialDef.genericFamily;
3004 fontDef.family = initialDef.firstFamily();
3005 if (style->setFontDef(fontDef))
3010 if (!value->isValueList()) return;
3011 FontDef fontDef = style->htmlFont().fontDef;
3012 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3013 int len = list->length();
3014 KWQFontFamily &firstFamily = fontDef.firstFamily();
3015 KWQFontFamily *currFamily = 0;
3017 for(int i = 0; i < len; i++) {
3018 CSSValueImpl *item = list->item(i);
3019 if(!item->isPrimitiveValue()) continue;
3020 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
3022 if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
3023 face = static_cast<FontFamilyValueImpl *>(val)->fontName();
3024 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
3025 switch (val->getIdent()) {
3026 case CSS_VAL__KHTML_BODY:
3027 face = settings->stdFontName();
3030 face = settings->serifFontName();
3031 fontDef.setGenericFamily(FontDef::eSerif);
3033 case CSS_VAL_SANS_SERIF:
3034 face = settings->sansSerifFontName();
3035 fontDef.setGenericFamily(FontDef::eSansSerif);
3037 case CSS_VAL_CURSIVE:
3038 face = settings->cursiveFontName();
3039 fontDef.setGenericFamily(FontDef::eCursive);
3041 case CSS_VAL_FANTASY:
3042 face = settings->fantasyFontName();
3043 fontDef.setGenericFamily(FontDef::eFantasy);
3045 case CSS_VAL_MONOSPACE:
3046 face = settings->fixedFontName();
3047 fontDef.setGenericFamily(FontDef::eMonospace);
3052 if ( !face.isEmpty() ) {
3054 // Filling in the first family.
3055 firstFamily.setFamily(face);
3056 currFamily = &firstFamily;
3059 KWQFontFamily *newFamily = new KWQFontFamily;
3060 newFamily->setFamily(face);
3061 currFamily->appendFamily(newFamily);
3062 currFamily = newFamily;
3065 if (style->setFontDef( fontDef )) {
3072 case CSS_PROP_QUOTES:
3073 // list of strings or i
3077 case CSS_PROP_TEXT_DECORATION: {
3079 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3080 int t = RenderStyle::initialTextDecoration();
3081 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
3084 if(!value->isValueList()) return;
3085 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
3086 int len = list->length();
3087 for(int i = 0; i < len; i++)
3089 CSSValueImpl *item = list->item(i);
3090 if(!item->isPrimitiveValue()) continue;
3091 primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
3092 switch(primitiveValue->getIdent())
3096 case CSS_VAL_UNDERLINE:
3097 t |= UNDERLINE; break;
3098 case CSS_VAL_OVERLINE:
3099 t |= OVERLINE; break;
3100 case CSS_VAL_LINE_THROUGH:
3101 t |= LINE_THROUGH; break;
3110 style->setTextDecoration(t);
3114 // shorthand properties
3115 case CSS_PROP_BACKGROUND:
3117 style->setBackgroundColor(parentStyle->backgroundColor());
3118 style->setBackgroundImage(parentStyle->backgroundImage());
3119 style->setBackgroundRepeat(parentStyle->backgroundRepeat());
3120 style->setBackgroundAttachment(parentStyle->backgroundAttachment());
3121 style->setBackgroundXPosition(parentStyle->backgroundXPosition());
3122 style->setBackgroundYPosition(parentStyle->backgroundYPosition());
3124 else if (isInitial) {
3125 style->setBackgroundColor(QColor());
3126 style->setBackgroundImage(RenderStyle::initialBackgroundImage());
3127 style->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
3128 style->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
3129 style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
3130 style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
3133 case CSS_PROP_BORDER:
3134 case CSS_PROP_BORDER_STYLE:
3135 case CSS_PROP_BORDER_WIDTH:
3136 case CSS_PROP_BORDER_COLOR:
3137 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
3140 style->setBorderTopColor(parentStyle->borderTopColor());
3141 style->setBorderBottomColor(parentStyle->borderBottomColor());
3142 style->setBorderLeftColor(parentStyle->borderLeftColor());
3143 style->setBorderRightColor(parentStyle->borderRightColor());
3145 else if (isInitial) {
3146 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead.
3147 style->setBorderBottomColor(QColor());
3148 style->setBorderLeftColor(QColor());
3149 style->setBorderRightColor(QColor());
3152 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
3155 style->setBorderTopStyle(parentStyle->borderTopStyle());
3156 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3157 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3158 style->setBorderRightStyle(parentStyle->borderRightStyle());
3160 else if (isInitial) {
3161 style->setBorderTopStyle(RenderStyle::initialBorderStyle());
3162 style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
3163 style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
3164 style->setBorderRightStyle(RenderStyle::initialBorderStyle());
3167 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
3170 style->setBorderTopWidth(parentStyle->borderTopWidth());
3171 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3172 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
3173 style->setBorderRightWidth(parentStyle->borderRightWidth());
3175 else if (isInitial) {
3176 style->setBorderTopWidth(RenderStyle::initialBorderWidth());
3177 style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
3178 style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
3179 style->setBorderRightWidth(RenderStyle::initialBorderWidth());
3183 case CSS_PROP_BORDER_TOP:
3185 style->setBorderTopColor(parentStyle->borderTopColor());
3186 style->setBorderTopStyle(parentStyle->borderTopStyle());
3187 style->setBorderTopWidth(parentStyle->borderTopWidth());
3190 style->resetBorderTop();
3192 case CSS_PROP_BORDER_RIGHT:
3194 style->setBorderRightColor(parentStyle->borderRightColor());
3195 style->setBorderRightStyle(parentStyle->borderRightStyle());
3196 style->setBorderRightWidth(parentStyle->borderRightWidth());
3199 style->resetBorderRight();
3201 case CSS_PROP_BORDER_BOTTOM:
3203 style->setBorderBottomColor(parentStyle->borderBottomColor());
3204 style->setBorderBottomStyle(parentStyle->borderBottomStyle());
3205 style->setBorderBottomWidth(parentStyle->borderBottomWidth());
3208 style->resetBorderBottom();
3210 case CSS_PROP_BORDER_LEFT:
3212 style->setBorderLeftColor(parentStyle->borderLeftColor());
3213 style->setBorderLeftStyle(parentStyle->borderLeftStyle());
3214 style->setBorderLeftWidth(parentStyle->borderLeftWidth());
3217 style->resetBorderLeft();
3219 case CSS_PROP_MARGIN:
3221 style->setMarginTop(parentStyle->marginTop());
3222 style->setMarginBottom(parentStyle->marginBottom());