2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
5 * (C) 2004-2007 Apple Computer, Inc.
6 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include "css_valueimpl.h"
25 #include "css_ruleimpl.h"
26 #include "css_stylesheetimpl.h"
27 #include "cssparser.h"
28 #include "cssproperties.h"
29 #include "cssvalues.h"
31 #include <dom/css_value.h>
32 #include <dom/dom_exception.h>
33 #include <dom/dom_string.h>
35 #include <xml/dom_stringimpl.h>
36 #include <xml/dom_docimpl.h>
38 #include <misc/loader.h>
40 #include <rendering/font.h>
41 #include <rendering/render_style.h>
43 #include <wtf/ASCIICType.h>
46 #include <QtCore/QRegExp>
47 #include <QtGui/QPaintDevice>
49 // Hack for debugging purposes
50 extern DOM::DOMString
getPropertyName(unsigned short id
);
57 static int propertyID(const DOMString
&s
)
59 char buffer
[maxCSSPropertyNameLength
];
61 unsigned len
= s
.length();
62 if (len
> maxCSSPropertyNameLength
)
65 for (unsigned i
= 0; i
!= len
; ++i
) {
66 unsigned short c
= s
[i
].unicode();
67 if (c
== 0 || c
>= 0x7F)
68 return 0; // illegal character
69 buffer
[i
] = s
[i
].toLower().unicode();
72 return getPropertyID(buffer
, len
);
75 // "ident" from the CSS tokenizer, minus backslash-escape sequences
76 static bool isCSSTokenizerIdentifier(const DOMString
& string
)
78 const QChar
* p
= string
.unicode();
79 const QChar
* end
= p
+ string
.length();
82 if (p
!= end
&& p
[0] == '-')
86 if (p
== end
|| !(p
[0] == '_' || p
[0] >= 128 || isASCIIAlpha(p
->unicode())))
91 for (; p
!= end
; ++p
) {
92 if (!(p
[0] == '_' || p
[0] == '-' || p
[0] >= 128 || isASCIIAlphanumeric(p
->unicode())))
99 static DOMString
quoteString(const DOMString
&string
)
101 // FIXME: Also need to transform control characters into \ sequences.
102 QString s
= string
.string();
103 s
.replace('\\', "\\\\");
104 s
.replace('\'', "\\'");
105 return '\'' + s
+ '\'';
108 // Quotes the string if it needs quoting.
109 static DOMString
quoteStringIfNeeded(const DOMString
&string
)
111 return isCSSTokenizerIdentifier(string
) ? string
: quoteString(string
);
114 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl
*parent
)
115 : StyleBaseImpl(parent
)
121 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl
*parent
, QList
<CSSProperty
*> *lstValues
)
122 : StyleBaseImpl(parent
)
124 m_lstValues
= lstValues
;
128 CSSStyleDeclarationImpl
& CSSStyleDeclarationImpl::operator= (const CSSStyleDeclarationImpl
& o
)
130 if (this == &o
) return *this;
132 // don't attach it to the same node, just leave the current m_node value
134 qDeleteAll(*m_lstValues
);
138 m_lstValues
= new QList
<CSSProperty
*>;
139 QListIterator
<CSSProperty
*> lstValuesIt(*o
.m_lstValues
);
140 while ( lstValuesIt
.hasNext() )
141 m_lstValues
->append(new CSSProperty(*lstValuesIt
.next()));
147 CSSStyleDeclarationImpl::~CSSStyleDeclarationImpl()
150 qDeleteAll( *m_lstValues
);
152 // we don't use refcounting for m_node, to avoid cyclic references (see ElementImpl)
155 CSSValueImpl
*CSSStyleDeclarationImpl::getPropertyCSSValue(const DOMString
&propertyName
) const
157 int propID
= propertyID(propertyName
);
160 return getPropertyCSSValue(propID
);
163 DOMString
CSSStyleDeclarationImpl::getPropertyValue(const DOMString
&propertyName
) const
165 int propID
= propertyID(propertyName
);
168 return getPropertyValue(propID
);
171 DOMString
CSSStyleDeclarationImpl::getPropertyPriority(const DOMString
&propertyName
) const
173 int propID
= propertyID(propertyName
);
176 return getPropertyPriority(propID
) ? "important" : "";
179 void CSSStyleDeclarationImpl::setProperty(const DOMString
&propertyName
, const DOMString
&value
, const DOMString
&priority
)
181 int propID
= propertyID(propertyName
);
182 if (!propID
) // set exception?
184 bool important
= priority
.string().indexOf("important", 0, Qt::CaseInsensitive
) != -1;
185 setProperty(propID
, value
, important
);
188 DOMString
CSSStyleDeclarationImpl::removeProperty(const DOMString
&propertyName
)
190 int propID
= propertyID(propertyName
);
194 removeProperty(propID
, &old
);
198 DOMString
CSSStyleDeclarationImpl::getPropertyValue( int propertyID
) const
200 if(!m_lstValues
) return DOMString();
201 CSSValueImpl
* value
= getPropertyCSSValue( propertyID
);
203 return value
->cssText();
205 // Shorthand and 4-values properties
206 switch ( propertyID
) {
207 case CSS_PROP_BACKGROUND_POSITION
:
209 // ## Is this correct? The code in cssparser.cpp is confusing
210 const int properties
[2] = { CSS_PROP_BACKGROUND_POSITION_X
,
211 CSS_PROP_BACKGROUND_POSITION_Y
};
212 return getLayeredShortHandValue( properties
, 2 );
214 case CSS_PROP_BACKGROUND
:
216 const int properties
[6] = { CSS_PROP_BACKGROUND_IMAGE
, CSS_PROP_BACKGROUND_REPEAT
,
217 CSS_PROP_BACKGROUND_ATTACHMENT
,CSS_PROP_BACKGROUND_POSITION_X
,
218 CSS_PROP_BACKGROUND_POSITION_Y
, CSS_PROP_BACKGROUND_COLOR
};
219 return getLayeredShortHandValue( properties
, 6 );
221 case CSS_PROP_BORDER
:
223 const int properties
[3][4] = {{ CSS_PROP_BORDER_TOP_WIDTH
,
224 CSS_PROP_BORDER_RIGHT_WIDTH
,
225 CSS_PROP_BORDER_BOTTOM_WIDTH
,
226 CSS_PROP_BORDER_LEFT_WIDTH
},
227 { CSS_PROP_BORDER_TOP_STYLE
,
228 CSS_PROP_BORDER_RIGHT_STYLE
,
229 CSS_PROP_BORDER_BOTTOM_STYLE
,
230 CSS_PROP_BORDER_LEFT_STYLE
},
231 { CSS_PROP_BORDER_TOP_COLOR
,
232 CSS_PROP_BORDER_RIGHT_COLOR
,
233 CSS_PROP_BORDER_LEFT_COLOR
,
234 CSS_PROP_BORDER_BOTTOM_COLOR
}};
236 const int nrprops
= sizeof(properties
) / sizeof(properties
[0]);
237 for (int i
= 0; i
< nrprops
; ++i
) {
238 DOMString value
= getCommonValue(properties
[i
], 4);
239 if (!value
.isNull()) {
248 case CSS_PROP_BORDER_TOP
:
250 const int properties
[3] = { CSS_PROP_BORDER_TOP_WIDTH
, CSS_PROP_BORDER_TOP_STYLE
,
251 CSS_PROP_BORDER_TOP_COLOR
};
252 return getShortHandValue( properties
, 3 );
254 case CSS_PROP_BORDER_RIGHT
:
256 const int properties
[3] = { CSS_PROP_BORDER_RIGHT_WIDTH
, CSS_PROP_BORDER_RIGHT_STYLE
,
257 CSS_PROP_BORDER_RIGHT_COLOR
};
258 return getShortHandValue( properties
, 3 );
260 case CSS_PROP_BORDER_BOTTOM
:
262 const int properties
[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH
, CSS_PROP_BORDER_BOTTOM_STYLE
,
263 CSS_PROP_BORDER_BOTTOM_COLOR
};
264 return getShortHandValue( properties
, 3 );
266 case CSS_PROP_BORDER_LEFT
:
268 const int properties
[3] = { CSS_PROP_BORDER_LEFT_WIDTH
, CSS_PROP_BORDER_LEFT_STYLE
,
269 CSS_PROP_BORDER_LEFT_COLOR
};
270 return getShortHandValue( properties
, 3 );
272 case CSS_PROP_OUTLINE
:
274 const int properties
[3] = { CSS_PROP_OUTLINE_WIDTH
, CSS_PROP_OUTLINE_STYLE
,
275 CSS_PROP_OUTLINE_COLOR
};
276 return getShortHandValue( properties
, 3 );
278 case CSS_PROP_BORDER_COLOR
:
280 const int properties
[4] = { CSS_PROP_BORDER_TOP_COLOR
, CSS_PROP_BORDER_RIGHT_COLOR
,
281 CSS_PROP_BORDER_BOTTOM_COLOR
, CSS_PROP_BORDER_LEFT_COLOR
};
282 return get4Values( properties
);
284 case CSS_PROP_BORDER_WIDTH
:
286 const int properties
[4] = { CSS_PROP_BORDER_TOP_WIDTH
, CSS_PROP_BORDER_RIGHT_WIDTH
,
287 CSS_PROP_BORDER_BOTTOM_WIDTH
, CSS_PROP_BORDER_LEFT_WIDTH
};
288 return get4Values( properties
);
290 case CSS_PROP_BORDER_STYLE
:
292 const int properties
[4] = { CSS_PROP_BORDER_TOP_STYLE
, CSS_PROP_BORDER_RIGHT_STYLE
,
293 CSS_PROP_BORDER_BOTTOM_STYLE
, CSS_PROP_BORDER_LEFT_STYLE
};
294 return get4Values( properties
);
296 case CSS_PROP_MARGIN
:
298 const int properties
[4] = { CSS_PROP_MARGIN_TOP
, CSS_PROP_MARGIN_RIGHT
,
299 CSS_PROP_MARGIN_BOTTOM
, CSS_PROP_MARGIN_LEFT
};
300 return get4Values( properties
);
302 case CSS_PROP_PADDING
:
304 const int properties
[4] = { CSS_PROP_PADDING_TOP
, CSS_PROP_PADDING_RIGHT
,
305 CSS_PROP_PADDING_BOTTOM
, CSS_PROP_PADDING_LEFT
};
306 return get4Values( properties
);
308 case CSS_PROP_LIST_STYLE
:
310 const int properties
[3] = { CSS_PROP_LIST_STYLE_TYPE
, CSS_PROP_LIST_STYLE_POSITION
,
311 CSS_PROP_LIST_STYLE_IMAGE
};
312 return getShortHandValue( properties
, 3 );
315 //kDebug() << "property not found:" << propertyID;
319 // only returns a non-null value if all properties have the same, non-null value
320 DOMString
CSSStyleDeclarationImpl::getCommonValue(const int* properties
, int number
) const
323 for (int i
= 0; i
< number
; ++i
) {
324 CSSValueImpl
* value
= getPropertyCSSValue(properties
[i
]);
327 DOMString text
= value
->cssText();
332 else if (res
!= text
)
338 DOMString
CSSStyleDeclarationImpl::get4Values( const int* properties
) const
341 for ( int i
= 0 ; i
< 4 ; ++i
) {
342 if (!isPropertyImplicit(properties
[i
])) {
343 CSSValueImpl
* value
= getPropertyCSSValue( properties
[i
] );
344 if ( !value
) { // apparently all 4 properties must be specified.
349 res
+= value
->cssText();
355 DOMString
CSSStyleDeclarationImpl::getLayeredShortHandValue(const int* properties
, unsigned number
) const
361 // Begin by collecting the properties into an array.
362 QVector
<CSSValueImpl
*> values(number
);
363 unsigned numLayers
= 0;
365 for (i
= 0; i
< number
; ++i
) {
366 values
[i
] = getPropertyCSSValue(properties
[i
]);
368 if (values
[i
]->isValueList()) {
369 CSSValueListImpl
* valueList
= static_cast<CSSValueListImpl
*>(values
[i
]);
370 numLayers
= qMax(valueList
->length(), (unsigned long)numLayers
);
372 numLayers
= qMax(1U, numLayers
);
376 // Now stitch the properties together. Implicit initial values are flagged as such and
377 // can safely be omitted.
378 for (i
= 0; i
< numLayers
; i
++) {
380 for (j
= 0; j
< number
; j
++) {
381 CSSValueImpl
* value
= 0;
383 if (values
[j
]->isValueList())
384 value
= static_cast<CSSValueListImpl
*>(values
[j
])->item(i
);
388 // Color only belongs in the last layer.
389 if (properties
[j
] == CSS_PROP_BACKGROUND_COLOR
) {
390 if (i
!= numLayers
- 1)
392 } else if (i
!= 0) // Other singletons only belong in the first layer.
397 if (value
&& !value
->isImplicitInitialValue()) {
398 if (!layerRes
.isNull())
400 layerRes
+= value
->cssText();
404 if (!layerRes
.isNull()) {
414 DOMString
CSSStyleDeclarationImpl::getShortHandValue( const int* properties
, int number
) const
417 for ( int i
= 0 ; i
< number
; ++i
) {
418 CSSValueImpl
* value
= getPropertyCSSValue( properties
[i
] );
419 if ( value
) { // TODO provide default value if !value
422 res
+= value
->cssText();
428 CSSValueImpl
*CSSStyleDeclarationImpl::getPropertyCSSValue( int propertyID
) const
430 if(!m_lstValues
) return 0;
432 QListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
433 CSSProperty
*current
;
434 while ( lstValuesIt
.hasNext() ) {
435 current
= lstValuesIt
.next();
436 if (current
->m_id
== propertyID
)
437 return current
->value();
442 bool CSSStyleDeclarationImpl::isPropertyImplicit(int propertyID
) const
444 QListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
445 CSSProperty
const *current
;
446 while ( lstValuesIt
.hasNext() ) {
447 current
= lstValuesIt
.next();
448 if (current
->m_id
== propertyID
)
449 return current
->isImplicit();;
454 // --------------- Shorthands mapping ----------------
456 // In order top be able to remove a shorthand property,
457 // we need a reverse mapping from the shorthands to their composing properties.
459 // ### Warning: keep in sync when introducing new shorthands.
461 struct PropertyLonghand
{
468 PropertyLonghand(const int* firstProperty
, unsigned numProperties
)
469 : m_properties(firstProperty
)
470 , m_length(numProperties
)
474 const int* properties() const { return m_properties
; }
475 unsigned length() const { return m_length
; }
478 const int* m_properties
;
482 static void initShorthandMap(QHash
<int, PropertyLonghand
>& shorthandMap
)
484 #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \
485 map.insert(propID, PropertyLonghand(array, sizeof(array) / sizeof(array[0])))
487 // FIXME: The 'font' property has "shorthand nature" but is not parsed as a shorthand.
489 // Do not change the order of the following four shorthands, and keep them together.
490 static const int borderProperties
[4][3] = {
491 { CSS_PROP_BORDER_TOP_COLOR
, CSS_PROP_BORDER_TOP_STYLE
, CSS_PROP_BORDER_TOP_WIDTH
},
492 { CSS_PROP_BORDER_RIGHT_COLOR
, CSS_PROP_BORDER_RIGHT_STYLE
, CSS_PROP_BORDER_RIGHT_WIDTH
},
493 { CSS_PROP_BORDER_BOTTOM_COLOR
, CSS_PROP_BORDER_BOTTOM_STYLE
, CSS_PROP_BORDER_BOTTOM_WIDTH
},
494 { CSS_PROP_BORDER_LEFT_COLOR
, CSS_PROP_BORDER_LEFT_STYLE
, CSS_PROP_BORDER_LEFT_WIDTH
}
496 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_TOP
, borderProperties
[0]);
497 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_RIGHT
, borderProperties
[1]);
498 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_BOTTOM
, borderProperties
[2]);
499 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_LEFT
, borderProperties
[3]);
501 shorthandMap
.insert(CSS_PROP_BORDER
, PropertyLonghand(borderProperties
[0], sizeof(borderProperties
) / sizeof(borderProperties
[0][0])));
503 static const int borderColorProperties
[] = {
504 CSS_PROP_BORDER_TOP_COLOR
,
505 CSS_PROP_BORDER_RIGHT_COLOR
,
506 CSS_PROP_BORDER_BOTTOM_COLOR
,
507 CSS_PROP_BORDER_LEFT_COLOR
509 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_COLOR
, borderColorProperties
);
511 static const int borderStyleProperties
[] = {
512 CSS_PROP_BORDER_TOP_STYLE
,
513 CSS_PROP_BORDER_RIGHT_STYLE
,
514 CSS_PROP_BORDER_BOTTOM_STYLE
,
515 CSS_PROP_BORDER_LEFT_STYLE
517 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_STYLE
, borderStyleProperties
);
519 static const int borderWidthProperties
[] = {
520 CSS_PROP_BORDER_TOP_WIDTH
,
521 CSS_PROP_BORDER_RIGHT_WIDTH
,
522 CSS_PROP_BORDER_BOTTOM_WIDTH
,
523 CSS_PROP_BORDER_LEFT_WIDTH
525 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_WIDTH
, borderWidthProperties
);
527 static const int backgroundPositionProperties
[] = { CSS_PROP_BACKGROUND_POSITION_X
, CSS_PROP_BACKGROUND_POSITION_Y
};
528 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BACKGROUND_POSITION
, backgroundPositionProperties
);
530 static const int borderSpacingProperties
[] = { CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING
, CSS_PROP__KHTML_BORDER_VERTICAL_SPACING
};
531 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BORDER_SPACING
, borderSpacingProperties
);
533 static const int listStyleProperties
[] = {
534 CSS_PROP_LIST_STYLE_IMAGE
,
535 CSS_PROP_LIST_STYLE_POSITION
,
536 CSS_PROP_LIST_STYLE_TYPE
538 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_LIST_STYLE
, listStyleProperties
);
540 static const int marginProperties
[] = {
542 CSS_PROP_MARGIN_RIGHT
,
543 CSS_PROP_MARGIN_BOTTOM
,
546 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_MARGIN
, marginProperties
);
549 static const int marginCollapseProperties
[] = { CSS_PROP__KHTML_MARGIN_TOP_COLLAPSE
, CSS_PROP__KHTML_MARGIN_BOTTOM_COLLAPSE
};
550 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_MARGIN_COLLAPSE
, marginCollapseProperties
);
553 static const int marqueeProperties
[] = {
554 CSS_PROP__KHTML_MARQUEE_DIRECTION
,
555 CSS_PROP__KHTML_MARQUEE_INCREMENT
,
556 CSS_PROP__KHTML_MARQUEE_REPETITION
,
557 CSS_PROP__KHTML_MARQUEE_STYLE
,
558 CSS_PROP__KHTML_MARQUEE_SPEED
560 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_MARQUEE
, marqueeProperties
);
562 static const int outlineProperties
[] = {
563 CSS_PROP_OUTLINE_COLOR
,
564 CSS_PROP_OUTLINE_OFFSET
,
565 CSS_PROP_OUTLINE_STYLE
,
566 CSS_PROP_OUTLINE_WIDTH
568 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_OUTLINE
, outlineProperties
);
570 static const int paddingProperties
[] = {
571 CSS_PROP_PADDING_TOP
,
572 CSS_PROP_PADDING_RIGHT
,
573 CSS_PROP_PADDING_BOTTOM
,
574 CSS_PROP_PADDING_LEFT
576 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_PADDING
, paddingProperties
);
579 static const int textStrokeProperties
[] = { CSS_PROP__KHTML_TEXT_STROKE_COLOR
, CSS_PROP__KHTML_TEXT_STROKE_WIDTH
};
580 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_TEXT_STROKE
, textStrokeProperties
);
583 static const int backgroundProperties
[] = {
584 CSS_PROP_BACKGROUND_ATTACHMENT
,
585 CSS_PROP_BACKGROUND_COLOR
,
586 CSS_PROP_BACKGROUND_IMAGE
,
587 CSS_PROP_BACKGROUND_POSITION_X
,
588 CSS_PROP_BACKGROUND_POSITION_Y
,
589 CSS_PROP_BACKGROUND_REPEAT
,
590 CSS_PROP__KHTML_BACKGROUND_SIZE
592 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_BACKGROUND
, backgroundProperties
);
595 static const int columnsProperties
[] = { CSS_PROP__KHTML_COLUMN_WIDTH
, CSS_PROP__KHTML_COLUMN_COUNT
};
596 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_COLUMNS
, columnsProperties
);
598 static const int columnRuleProperties
[] = {
599 CSS_PROP__KHTML_COLUMN_RULE_COLOR
,
600 CSS_PROP__KHTML_COLUMN_RULE_STYLE
,
601 CSS_PROP__KHTML_COLUMN_RULE_WIDTH
603 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_COLUMN_RULE
, columnRuleProperties
);
606 static const int overflowProperties
[] = { CSS_PROP_OVERFLOW_X
, CSS_PROP_OVERFLOW_Y
};
607 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP_OVERFLOW
, overflowProperties
);
609 static const int borderRadiusProperties
[] = {
610 CSS_PROP__KHTML_BORDER_TOP_RIGHT_RADIUS
,
611 CSS_PROP__KHTML_BORDER_TOP_LEFT_RADIUS
,
612 CSS_PROP__KHTML_BORDER_BOTTOM_LEFT_RADIUS
,
613 CSS_PROP__KHTML_BORDER_BOTTOM_RIGHT_RADIUS
615 SET_SHORTHAND_MAP_ENTRY(shorthandMap
, CSS_PROP__KHTML_BORDER_RADIUS
, borderRadiusProperties
);
617 #undef SET_SHORTHAND_MAP_ENTRY
620 // -------------------------------------------
622 void CSSStyleDeclarationImpl::removeProperty(int propertyID
,
628 static QHash
<int, PropertyLonghand
> shorthandMap
;
629 if (shorthandMap
.isEmpty())
630 initShorthandMap(shorthandMap
);
632 PropertyLonghand longhand
= shorthandMap
.value(propertyID
);
633 if (longhand
.length()) {
634 removePropertiesInSet(longhand
.properties(), longhand
.length());
635 // FIXME: Return an equivalent shorthand when possible.
639 QMutableListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
640 CSSProperty
*current
;
641 lstValuesIt
.toBack();
642 while ( lstValuesIt
.hasPrevious() ) {
643 current
= lstValuesIt
.previous();
644 if (current
->m_id
== propertyID
) {
646 *old
= current
->value()->cssText();
647 delete lstValuesIt
.value();
648 lstValuesIt
.remove();
655 void CSSStyleDeclarationImpl::removePropertiesInSet(const int* set
, unsigned length
)
657 bool changed
= false;
658 for (unsigned i
= 0; i
< length
; i
++) {
659 QMutableListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
660 CSSProperty
*current
;
661 lstValuesIt
.toBack();
662 while ( lstValuesIt
.hasPrevious() ) {
663 current
= lstValuesIt
.previous();
664 if (current
->m_id
== set
[i
]) {
665 delete lstValuesIt
.value();
666 lstValuesIt
.remove();
676 void CSSStyleDeclarationImpl::setChanged()
679 m_node
->setChanged();
683 // ### quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk)
684 for (StyleBaseImpl
* stylesheet
= this; stylesheet
; stylesheet
= stylesheet
->parent())
685 if (stylesheet
->isCSSStyleSheet()) {
686 static_cast<CSSStyleSheetImpl
*>(stylesheet
)->doc()->updateStyleSelector();
691 void CSSStyleDeclarationImpl::clear()
696 QMutableListIterator
<CSSProperty
*> it(*m_lstValues
);
697 while (it
.hasNext()) {
703 bool CSSStyleDeclarationImpl::getPropertyPriority( int propertyID
) const
706 QListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
707 CSSProperty
*current
;
708 while (lstValuesIt
.hasNext()) {
709 current
= lstValuesIt
.next();
710 if( propertyID
== current
->m_id
)
711 return current
->m_important
;
717 bool CSSStyleDeclarationImpl::setProperty(int id
, const DOMString
&value
, bool important
, int &ec
)
721 // Setting the value to an empty string just removes the property in both IE and Gecko.
722 // Setting it to null seems to produce less consistent results, but we treat it just the same.
723 if (value
.isEmpty()) {
728 bool success
= setProperty(id
, value
, important
);
731 // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
732 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
738 bool CSSStyleDeclarationImpl::setProperty(int id
, const DOMString
&value
, bool important
)
741 m_lstValues
= new QList
<CSSProperty
*>;
744 CSSParser
parser( strictParsing
);
745 bool success
= parser
.parseValue( this, id
, value
, important
);
747 kDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id
).string()
748 << "] value: [" << value
.string() << "]"<< endl
;
754 void CSSStyleDeclarationImpl::setProperty(int id
, int value
, bool important
)
757 m_lstValues
= new QList
<CSSProperty
*>;
761 CSSValueImpl
* cssValue
= new CSSPrimitiveValueImpl(value
);
762 setParsedValue(id
, cssValue
, important
, m_lstValues
);
766 void CSSStyleDeclarationImpl::setLengthProperty(int id
, const DOM::DOMString
&value
, bool important
, bool _multiLength
)
768 bool parseMode
= strictParsing
;
769 strictParsing
= false;
770 multiLength
= _multiLength
;
771 setProperty( id
, value
, important
);
772 strictParsing
= parseMode
;
776 void CSSStyleDeclarationImpl::setProperty ( const DOMString
&propertyString
)
779 m_lstValues
= new QList
<CSSProperty
*>;
782 CSSParser
parser( strictParsing
);
783 parser
.parseDeclaration( this, propertyString
);
787 unsigned long CSSStyleDeclarationImpl::length() const
789 return m_lstValues
? m_lstValues
->count() : 0;
792 DOMString
CSSStyleDeclarationImpl::item( unsigned long index
) const
794 if(m_lstValues
&& index
< (unsigned)m_lstValues
->count() && m_lstValues
->at(index
))
795 return getPropertyName(m_lstValues
->at(index
)->m_id
);
799 CSSRuleImpl
*CSSStyleDeclarationImpl::parentRule() const
801 return (m_parent
&& m_parent
->isRule() ) ?
802 static_cast<CSSRuleImpl
*>(m_parent
) : 0;
805 DOM::DOMString
CSSStyleDeclarationImpl::cssText() const
809 const CSSProperty
* positionXProp
= 0;
810 const CSSProperty
* positionYProp
= 0;
813 QListIterator
<CSSProperty
*> lstValuesIt(*m_lstValues
);
814 while (lstValuesIt
.hasNext()) {
815 const CSSProperty
* cur
= lstValuesIt
.next();
816 if (cur
->id() == CSS_PROP_BACKGROUND_POSITION_X
)
818 else if (cur
->id() == CSS_PROP_BACKGROUND_POSITION_Y
)
821 result
+= cur
->cssText();
825 // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output.
826 // It is required because background-position-x/y are non-standard properties and generated output
827 // would not work in Firefox
828 // It would be a better solution if background-position was CSS_PAIR.
829 if (positionXProp
&& positionYProp
&& positionXProp
->isImportant() == positionYProp
->isImportant()) {
830 DOMString positionValue
;
831 const int properties
[2] = { CSS_PROP_BACKGROUND_POSITION_X
, CSS_PROP_BACKGROUND_POSITION_Y
};
832 if (positionXProp
->value()->isValueList() || positionYProp
->value()->isValueList())
833 positionValue
= getLayeredShortHandValue(properties
, 2);
835 positionValue
= positionXProp
->value()->cssText() + " " + positionYProp
->value()->cssText();
836 result
+= DOMString("background-position: ") + positionValue
837 + DOMString((positionXProp
->isImportant() ? " !important" : ""))
841 result
+= positionXProp
->cssText();
843 result
+= positionYProp
->cssText();
848 void CSSStyleDeclarationImpl::setCssText(const DOM::DOMString
& text
)
851 qDeleteAll(*m_lstValues
);
852 m_lstValues
->clear();
854 m_lstValues
= new QList
<CSSProperty
*>;
857 CSSParser
parser( strictParsing
);
858 parser
.parseDeclaration( this, text
);
862 bool CSSStyleDeclarationImpl::parseString( const DOMString
&/*string*/, bool )
864 kDebug() << "WARNING: CSSStyleDeclarationImpl::parseString, unimplemented, was called";
870 // --------------------------------------------------------------------------------------
872 unsigned short CSSInheritedValueImpl::cssValueType() const
874 return CSSValue::CSS_INHERIT
;
877 DOM::DOMString
CSSInheritedValueImpl::cssText() const
879 return DOMString("inherit");
882 unsigned short CSSInitialValueImpl::cssValueType() const
884 return CSSValue::CSS_INITIAL
;
887 DOM::DOMString
CSSInitialValueImpl::cssText() const
889 return DOMString("initial");
892 // ----------------------------------------------------------------------------------------
894 CSSValueListImpl::~CSSValueListImpl()
896 for (QListIterator
<CSSValueImpl
*> iterator(m_values
); iterator
.hasNext();)
897 iterator
.next()->deref();
900 unsigned short CSSValueListImpl::cssValueType() const
902 return CSSValue::CSS_VALUE_LIST
;
905 void CSSValueListImpl::append(CSSValueImpl
*val
)
907 m_values
.append(val
);
911 DOM::DOMString
CSSValueListImpl::cssText() const
913 DOMString result
= "";
915 for (QListIterator
<CSSValueImpl
*> iterator(m_values
); iterator
.hasNext();) {
916 result
+= iterator
.next()->cssText();
922 // -------------------------------------------------------------------------------------
924 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl()
930 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(int ident
)
933 m_value
.ident
= ident
;
934 m_type
= CSSPrimitiveValue::CSS_IDENT
;
937 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(double num
, CSSPrimitiveValue::UnitTypes type
)
943 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(const DOMString
&str
, CSSPrimitiveValue::UnitTypes type
)
945 m_value
.string
= str
.implementation();
946 if(m_value
.string
) m_value
.string
->ref();
950 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(CounterImpl
*c
)
954 m_value
.counter
->ref();
955 m_type
= CSSPrimitiveValue::CSS_COUNTER
;
958 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl( RectImpl
*r
)
963 m_type
= CSSPrimitiveValue::CSS_RECT
;
966 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color
)
968 m_value
.rgbcolor
= color
;
969 m_type
= CSSPrimitiveValue::CSS_RGBCOLOR
;
972 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(PairImpl
*p
)
977 m_type
= CSSPrimitiveValue::CSS_PAIR
;
981 CSSPrimitiveValueImpl::~CSSPrimitiveValueImpl()
986 void CSSPrimitiveValueImpl::cleanup()
989 case CSSPrimitiveValue::CSS_STRING
:
990 case CSSPrimitiveValue::CSS_URI
:
991 case CSSPrimitiveValue::CSS_ATTR
:
992 if(m_value
.string
) m_value
.string
->deref();
994 case CSSPrimitiveValue::CSS_COUNTER
:
995 m_value
.counter
->deref();
997 case CSSPrimitiveValue::CSS_RECT
:
998 m_value
.rect
->deref();
1000 case CSSPrimitiveValue::CSS_PAIR
:
1001 m_value
.pair
->deref();
1010 int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle
*style
, int logicalDpiY
)
1012 double result
= computeLengthFloat( style
, logicalDpiY
);
1013 // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
1014 // need to go ahead and round if we're really close to the next integer value.
1015 int intResult
= (int)(result
+ (result
< 0 ? -0.01 : +0.01));
1019 double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle
*style
, int logicalDpiY
)
1021 unsigned short type
= primitiveType();
1023 double dpiY
= 72.; // fallback
1026 if ( !khtml::printpainter
&& dpiY
< 96 )
1032 case CSSPrimitiveValue::CSS_EMS
:
1033 factor
= style
->font().pixelSize();
1035 case CSSPrimitiveValue::CSS_EXS
:
1037 QFontMetrics fm
= style
->fontMetrics();
1038 factor
= fm
.xHeight();
1041 case CSSPrimitiveValue::CSS_PX
:
1043 case CSSPrimitiveValue::CSS_CM
:
1044 factor
= dpiY
/2.54; //72dpi/(2.54 cm/in)
1046 case CSSPrimitiveValue::CSS_MM
:
1049 case CSSPrimitiveValue::CSS_IN
:
1052 case CSSPrimitiveValue::CSS_PT
:
1055 case CSSPrimitiveValue::CSS_PC
:
1057 factor
= dpiY
*12./72.;
1063 return floatValue(type
)*factor
;
1066 int CSSPrimitiveValueImpl::getDPIResolution() const
1068 unsigned short type
= primitiveType();
1072 case CSSPrimitiveValue::CSS_DPI
:
1074 case CSSPrimitiveValue::CSS_DPCM
:
1081 return (int)(0.01+floatValue(type
)*factor
);
1084 void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType
, double floatValue
, int &exceptioncode
)
1088 // ### check if property supports this type
1089 if(m_type
> CSSPrimitiveValue::CSS_DIMENSION
) {
1090 exceptioncode
= CSSException::SYNTAX_ERR
+ CSSException::_EXCEPTION_OFFSET
;
1093 //if(m_type > CSSPrimitiveValue::CSS_DIMENSION) throw DOMException(DOMException::INVALID_ACCESS_ERR);
1094 m_value
.num
= floatValue
;
1098 void CSSPrimitiveValueImpl::setStringValue( unsigned short stringType
, const DOMString
&stringValue
, int &exceptioncode
)
1102 //if(m_type < CSSPrimitiveValue::CSS_STRING) throw DOMException(DOMException::INVALID_ACCESS_ERR);
1103 //if(m_type > CSSPrimitiveValue::CSS_ATTR) throw DOMException(DOMException::INVALID_ACCESS_ERR);
1104 if(m_type
< CSSPrimitiveValue::CSS_STRING
|| m_type
> CSSPrimitiveValue::CSS_ATTR
) {
1105 exceptioncode
= CSSException::SYNTAX_ERR
+ CSSException::_EXCEPTION_OFFSET
;
1108 if(stringType
!= CSSPrimitiveValue::CSS_IDENT
)
1110 m_value
.string
= stringValue
.implementation();
1111 m_value
.string
->ref();
1112 m_type
= stringType
;
1117 unsigned short CSSPrimitiveValueImpl::cssValueType() const
1119 return CSSValue::CSS_PRIMITIVE_VALUE
;
1122 bool CSSPrimitiveValueImpl::parseString( const DOMString
&/*string*/, bool )
1125 kDebug() << "WARNING: CSSPrimitiveValueImpl::parseString, unimplemented, was called";
1129 int CSSPrimitiveValueImpl::getIdent()
1131 if(m_type
!= CSSPrimitiveValue::CSS_IDENT
) return 0;
1132 return m_value
.ident
;
1135 DOM::DOMString
CSSPrimitiveValueImpl::cssText() const
1137 // ### return the original value instead of a generated one (e.g. color
1138 // name if it was specified) - check what spec says about this
1141 case CSSPrimitiveValue::CSS_UNKNOWN
:
1144 case CSSPrimitiveValue::CSS_NUMBER
:
1145 // We want to output integral values w/o a period, but others as-is
1146 if ( m_value
.num
== (int)m_value
.num
)
1147 text
= DOMString(QString::number( (int)m_value
.num
));
1149 text
= DOMString(QString::number( m_value
.num
));
1151 case CSSPrimitiveValue::CSS_PERCENTAGE
:
1152 text
= DOMString(QString::number( m_value
.num
) + "%");
1154 case CSSPrimitiveValue::CSS_EMS
:
1155 text
= DOMString(QString::number( m_value
.num
) + "em");
1157 case CSSPrimitiveValue::CSS_EXS
:
1158 text
= DOMString(QString::number( m_value
.num
) + "ex");
1160 case CSSPrimitiveValue::CSS_PX
:
1161 text
= DOMString(QString::number( m_value
.num
) + "px");
1163 case CSSPrimitiveValue::CSS_CM
:
1164 text
= DOMString(QString::number( m_value
.num
) + "cm");
1166 case CSSPrimitiveValue::CSS_MM
:
1167 text
= DOMString(QString::number( m_value
.num
) + "mm");
1169 case CSSPrimitiveValue::CSS_IN
:
1170 text
= DOMString(QString::number( m_value
.num
) + "in");
1172 case CSSPrimitiveValue::CSS_PT
:
1173 text
= DOMString(QString::number( m_value
.num
) + "pt");
1175 case CSSPrimitiveValue::CSS_PC
:
1176 text
= DOMString(QString::number( m_value
.num
) + "pc");
1178 case CSSPrimitiveValue::CSS_DEG
:
1179 text
= DOMString(QString::number( m_value
.num
) + "deg");
1181 case CSSPrimitiveValue::CSS_RAD
:
1182 text
= DOMString(QString::number( m_value
.num
) + "rad");
1184 case CSSPrimitiveValue::CSS_GRAD
:
1185 text
= DOMString(QString::number( m_value
.num
) + "grad");
1187 case CSSPrimitiveValue::CSS_MS
:
1188 text
= DOMString(QString::number( m_value
.num
) + "ms");
1190 case CSSPrimitiveValue::CSS_S
:
1191 text
= DOMString(QString::number( m_value
.num
) + "s");
1193 case CSSPrimitiveValue::CSS_HZ
:
1194 text
= DOMString(QString::number( m_value
.num
) + "hz");
1196 case CSSPrimitiveValue::CSS_KHZ
:
1197 text
= DOMString(QString::number( m_value
.num
) + "khz");
1199 case CSSPrimitiveValue::CSS_DIMENSION
:
1202 case CSSPrimitiveValue::CSS_STRING
:
1203 text
= quoteStringIfNeeded(m_value
.string
);
1205 case CSSPrimitiveValue::CSS_URI
:
1207 text
+= DOMString( m_value
.string
);
1210 case CSSPrimitiveValue::CSS_IDENT
:
1211 text
= getValueName(m_value
.ident
);
1213 case CSSPrimitiveValue::CSS_ATTR
:
1216 case CSSPrimitiveValue::CSS_COUNTER
:
1218 text
+= m_value
.counter
->m_identifier
;
1220 // ### add list-style and separator
1222 case CSSPrimitiveValue::CSS_RECT
:
1224 RectImpl
* rectVal
= getRectValue();
1226 text
+= rectVal
->top()->cssText() + " ";
1227 text
+= rectVal
->right()->cssText() + " ";
1228 text
+= rectVal
->bottom()->cssText() + " ";
1229 text
+= rectVal
->left()->cssText() + ")";
1232 case CSSPrimitiveValue::CSS_RGBCOLOR
:
1233 if (qAlpha(m_value
.rgbcolor
) != 0xFF) {
1234 if (m_value
.rgbcolor
== khtml::transparentColor
)
1235 text
= "transparent";
1237 text
= "rgba(" + QString::number(qRed (m_value
.rgbcolor
)) + ", "
1238 + QString::number(qGreen(m_value
.rgbcolor
)) + ", "
1239 + QString::number(qBlue (m_value
.rgbcolor
)) + ", "
1240 + QString::number(qAlpha(m_value
.rgbcolor
)/255.0) + ")";
1242 text
= "rgb(" + QString::number(qRed (m_value
.rgbcolor
)) + ", "
1243 + QString::number(qGreen(m_value
.rgbcolor
)) + ", "
1244 + QString::number(qBlue (m_value
.rgbcolor
)) + ")";
1247 case CSSPrimitiveValue::CSS_PAIR
:
1248 text
= m_value
.pair
->first()->cssText();
1250 text
+= m_value
.pair
->second()->cssText();
1258 // -----------------------------------------------------------------
1260 RectImpl::RectImpl()
1268 RectImpl::~RectImpl()
1270 if (m_top
) m_top
->deref();
1271 if (m_right
) m_right
->deref();
1272 if (m_bottom
) m_bottom
->deref();
1273 if (m_left
) m_left
->deref();
1276 void RectImpl::setTop( CSSPrimitiveValueImpl
*top
)
1278 if( top
) top
->ref();
1279 if ( m_top
) m_top
->deref();
1283 void RectImpl::setRight( CSSPrimitiveValueImpl
*right
)
1285 if( right
) right
->ref();
1286 if ( m_right
) m_right
->deref();
1290 void RectImpl::setBottom( CSSPrimitiveValueImpl
*bottom
)
1292 if( bottom
) bottom
->ref();
1293 if ( m_bottom
) m_bottom
->deref();
1297 void RectImpl::setLeft( CSSPrimitiveValueImpl
*left
)
1299 if( left
) left
->ref();
1300 if ( m_left
) m_left
->deref();
1304 // -----------------------------------------------------------------
1306 PairImpl::~PairImpl()
1308 if (m_first
) m_first
->deref(); if (m_second
) m_second
->deref();
1311 void PairImpl::setFirst(CSSPrimitiveValueImpl
* first
)
1313 if (first
== m_first
) return;
1314 if (m_first
) m_first
->deref();
1316 if (m_first
) m_first
->ref();
1319 void PairImpl::setSecond(CSSPrimitiveValueImpl
* second
)
1321 if (second
== m_second
) return;
1322 if (m_second
) m_second
->deref();
1324 if (m_second
) m_second
->ref();
1327 // -----------------------------------------------------------------
1329 CSSImageValueImpl::CSSImageValueImpl(const DOMString
&url
, const StyleBaseImpl
* style
)
1330 : CSSPrimitiveValueImpl(url
, CSSPrimitiveValue::CSS_URI
)
1332 khtml::DocLoader
*docLoader
= 0;
1333 const StyleBaseImpl
*root
= style
;
1334 while (root
->parent())
1335 root
= root
->parent();
1336 if (root
->isCSSStyleSheet())
1337 docLoader
= static_cast<const CSSStyleSheetImpl
*>(root
)->docLoader();
1339 m_image
= docLoader
->requestImage(url
);
1340 if(m_image
) m_image
->ref(this);
1343 CSSImageValueImpl::CSSImageValueImpl()
1344 : CSSPrimitiveValueImpl(CSS_VAL_NONE
)
1349 CSSImageValueImpl::~CSSImageValueImpl()
1351 if(m_image
) m_image
->deref(this);
1354 // ------------------------------------------------------------------------
1356 FontFamilyValueImpl::FontFamilyValueImpl( const QString
&string
)
1357 : CSSPrimitiveValueImpl( DOMString(string
), CSSPrimitiveValue::CSS_STRING
)
1359 static const QRegExp
parenReg(" \\(.*\\)$");
1360 static const QRegExp
braceReg(" \\[.*\\]$");
1362 parsedFontName
= string
;
1363 // a language tag is often added in braces at the end. Remove it.
1364 parsedFontName
.replace(parenReg
, QString());
1365 // remove [Xft] qualifiers
1366 parsedFontName
.replace(braceReg
, QString());
1368 #ifndef APPLE_CHANGES
1369 const QString
&available
= KHTMLSettings::availableFamilies();
1371 parsedFontName
= parsedFontName
.toLower();
1372 // kDebug(0) << "searching for face '" << parsedFontName << "'";
1374 int pos
= available
.indexOf( ',' + parsedFontName
+ ',', 0, Qt::CaseInsensitive
);
1376 // many pages add extra MSs to make sure it's windows only ;(
1377 if ( parsedFontName
.startsWith( "ms " ) )
1378 parsedFontName
= parsedFontName
.mid( 3 );
1379 if ( parsedFontName
.endsWith( " ms" ) )
1380 parsedFontName
.truncate( parsedFontName
.length() - 3 );
1381 pos
= available
.indexOf( ",ms " + parsedFontName
+ ',', 0, Qt::CaseInsensitive
);
1383 pos
= available
.indexOf( ',' + parsedFontName
+ " ms,", 0, Qt::CaseInsensitive
);
1388 int p
= available
.indexOf(',', pos
);
1389 assert( p
!= -1 ); // available is supposed to start and end with ,
1390 parsedFontName
= available
.mid( pos
, p
- pos
);
1391 // kDebug(0) << "going for '" << parsedFontName << "'";
1393 parsedFontName
.clear();
1395 #endif // !APPLE_CHANGES
1398 FontValueImpl::FontValueImpl()
1399 : style(0), variant(0), weight(0), size(0), lineHeight(0), family(0)
1403 FontValueImpl::~FontValueImpl()
1413 DOMString
FontValueImpl::cssText() const
1415 // font variant weight size / line-height family
1417 DOMString
result("");
1420 result
+= style
->cssText();
1423 if (result
.length() > 0) {
1426 result
+= variant
->cssText();
1429 if (result
.length() > 0) {
1432 result
+= weight
->cssText();
1435 if (result
.length() > 0) {
1438 result
+= size
->cssText();
1445 result
+= lineHeight
->cssText();
1448 if (result
.length() > 0) {
1451 result
+= family
->cssText();
1457 QuotesValueImpl::QuotesValueImpl()
1462 DOMString
QuotesValueImpl::cssText() const
1464 return "\"" + data
.join("\" \"") + "\"";
1467 void QuotesValueImpl::addLevel(const QString
& open
, const QString
& close
)
1474 QString
QuotesValueImpl::openQuote(int level
) const
1476 if (levels
== 0) return "";
1477 level
--; // increments are calculated before openQuote is called
1478 // kDebug( 6080 ) << "Open quote level:" << level;
1479 if (level
< 0) level
= 0;
1481 if (level
>= (int) levels
) level
= (int) (levels
-1);
1482 return data
[level
*2];
1485 QString
QuotesValueImpl::closeQuote(int level
) const
1487 if (levels
== 0) return "";
1488 // kDebug( 6080 ) << "Close quote level:" << level;
1489 if (level
< 0) level
= 0;
1491 if (level
>= (int) levels
) level
= (int) (levels
-1);
1492 return data
[level
*2+1];
1495 // Used for text-shadow and box-shadow
1496 ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl
* _x
, CSSPrimitiveValueImpl
* _y
,
1497 CSSPrimitiveValueImpl
* _blur
, CSSPrimitiveValueImpl
* _color
)
1498 :x(_x
), y(_y
), blur(_blur
), color(_color
)
1501 ShadowValueImpl::~ShadowValueImpl()
1509 DOMString
ShadowValueImpl::cssText() const
1513 text
+= color
->cssText();
1516 if (text
.length() > 0) {
1519 text
+= x
->cssText();
1522 if (text
.length() > 0) {
1525 text
+= y
->cssText();
1528 if (text
.length() > 0) {
1531 text
+= blur
->cssText();
1537 DOMString
CounterActImpl::cssText() const
1539 DOMString
text(m_counter
);
1540 text
+= DOMString(QString::number(m_value
));
1545 DOMString
CSSProperty::cssText() const
1547 return getPropertyName(m_id
) + DOMString(": ") + m_value
->cssText() + (m_important
? DOMString(" !important") : DOMString()) + DOMString("; ");