1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Daniel Glazman <glazman@netscape.com>
24 * Mats Palmgren <mats.palmgren@bredband.net>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * representation of a declaration block (or style attribute) in a CSS
47 #include "nsCSSDeclaration.h"
50 #include "nsUnicharUtils.h"
51 #include "nsReadableUtils.h"
53 #include "nsCSSProps.h"
55 #include "nsReadableUtils.h"
56 #include "nsStyleUtil.h"
58 #include "nsStyleConsts.h"
62 #define B_BORDER_TOP_STYLE 0x001
63 #define B_BORDER_LEFT_STYLE 0x002
64 #define B_BORDER_RIGHT_STYLE 0x004
65 #define B_BORDER_BOTTOM_STYLE 0x008
66 #define B_BORDER_TOP_COLOR 0x010
67 #define B_BORDER_LEFT_COLOR 0x020
68 #define B_BORDER_RIGHT_COLOR 0x040
69 #define B_BORDER_BOTTOM_COLOR 0x080
70 #define B_BORDER_TOP_WIDTH 0x100
71 #define B_BORDER_LEFT_WIDTH 0x200
72 #define B_BORDER_RIGHT_WIDTH 0x400
73 #define B_BORDER_BOTTOM_WIDTH 0x800
75 #define B_BORDER_STYLE 0x00f
76 #define B_BORDER_COLOR 0x0f0
77 #define B_BORDER_WIDTH 0xf00
79 #define B_BORDER_TOP 0x111
80 #define B_BORDER_LEFT 0x222
81 #define B_BORDER_RIGHT 0x444
82 #define B_BORDER_BOTTOM 0x888
84 #define B_BORDER 0xfff
86 nsCSSDeclaration::nsCSSDeclaration()
88 mImportantData(nsnull
)
90 // check that we can fit all the CSS properties into a PRUint8
91 // for the mOrder array - if not, might need to use PRUint16!
92 PR_STATIC_ASSERT(eCSSProperty_COUNT_no_shorthands
- 1 <= PR_UINT8_MAX
);
94 MOZ_COUNT_CTOR(nsCSSDeclaration
);
97 nsCSSDeclaration::nsCSSDeclaration(const nsCSSDeclaration
& aCopy
)
98 : mOrder(aCopy
.mOrder
),
99 mData(aCopy
.mData
? aCopy
.mData
->Clone() : nsnull
),
100 mImportantData(aCopy
.mImportantData
? aCopy
.mImportantData
->Clone()
103 MOZ_COUNT_CTOR(nsCSSDeclaration
);
106 nsCSSDeclaration::~nsCSSDeclaration(void)
111 if (mImportantData
) {
112 mImportantData
->Destroy();
115 MOZ_COUNT_DTOR(nsCSSDeclaration
);
119 nsCSSDeclaration::ValueAppended(nsCSSProperty aProperty
)
121 // order IS important for CSS, so remove and add to the end
122 if (nsCSSProps::IsShorthand(aProperty
)) {
123 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p
, aProperty
) {
124 mOrder
.RemoveElement(*p
);
125 mOrder
.AppendElement(*p
);
128 mOrder
.RemoveElement(aProperty
);
129 mOrder
.AppendElement(aProperty
);
135 nsCSSDeclaration::RemoveProperty(nsCSSProperty aProperty
)
137 nsCSSExpandedDataBlock data
;
138 data
.Expand(&mData
, &mImportantData
);
139 NS_ASSERTION(!mData
&& !mImportantData
, "Expand didn't null things out");
141 if (nsCSSProps::IsShorthand(aProperty
)) {
142 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p
, aProperty
) {
143 data
.ClearProperty(*p
);
144 mOrder
.RemoveElement(*p
);
147 data
.ClearProperty(aProperty
);
148 mOrder
.RemoveElement(aProperty
);
151 data
.Compress(&mData
, &mImportantData
);
156 nsCSSDeclaration::AppendComment(const nsAString
& aComment
)
158 return /* NS_ERROR_NOT_IMPLEMENTED, or not any longer that is */ NS_OK
;
162 nsCSSDeclaration::GetValueOrImportantValue(nsCSSProperty aProperty
, nsCSSValue
& aValue
) const
166 NS_ASSERTION(aProperty
>= 0, "out of range");
167 if (aProperty
>= eCSSProperty_COUNT_no_shorthands
||
168 nsCSSProps::kTypeTable
[aProperty
] != eCSSType_Value
) {
169 NS_ERROR("can't query for shorthand properties");
170 return NS_ERROR_ILLEGAL_VALUE
;
173 nsCSSCompressedDataBlock
*data
= GetValueIsImportant(aProperty
)
174 ? mImportantData
: mData
;
175 const void *storage
= data
->StorageFor(aProperty
);
178 aValue
= *static_cast<const nsCSSValue
*>(storage
);
182 PRBool
nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty
, nsAString
& aResult
) const
184 nsCSSCompressedDataBlock
*data
= GetValueIsImportant(aProperty
)
185 ? mImportantData
: mData
;
186 const void *storage
= data
->StorageFor(aProperty
);
188 switch (nsCSSProps::kTypeTable
[aProperty
]) {
189 case eCSSType_Value
: {
190 const nsCSSValue
*val
= static_cast<const nsCSSValue
*>(storage
);
191 AppendCSSValueToString(aProperty
, *val
, aResult
);
193 case eCSSType_Rect
: {
194 const nsCSSRect
*rect
= static_cast<const nsCSSRect
*>(storage
);
195 if (rect
->mTop
.GetUnit() == eCSSUnit_Inherit
||
196 rect
->mTop
.GetUnit() == eCSSUnit_Initial
) {
197 NS_ASSERTION(rect
->mRight
.GetUnit() == rect
->mTop
.GetUnit(),
198 "Top inherit or initial, right isn't. Fix the parser!");
199 NS_ASSERTION(rect
->mBottom
.GetUnit() == rect
->mTop
.GetUnit(),
200 "Top inherit or initial, bottom isn't. Fix the parser!");
201 NS_ASSERTION(rect
->mLeft
.GetUnit() == rect
->mTop
.GetUnit(),
202 "Top inherit or initial, left isn't. Fix the parser!");
203 AppendCSSValueToString(aProperty
, rect
->mTop
, aResult
);
205 aResult
.AppendLiteral("rect(");
206 AppendCSSValueToString(aProperty
, rect
->mTop
, aResult
);
207 NS_NAMED_LITERAL_STRING(comma
, ", ");
208 aResult
.Append(comma
);
209 AppendCSSValueToString(aProperty
, rect
->mRight
, aResult
);
210 aResult
.Append(comma
);
211 AppendCSSValueToString(aProperty
, rect
->mBottom
, aResult
);
212 aResult
.Append(comma
);
213 AppendCSSValueToString(aProperty
, rect
->mLeft
, aResult
);
214 aResult
.Append(PRUnichar(')'));
217 case eCSSType_ValuePair
: {
218 const nsCSSValuePair
*pair
= static_cast<const nsCSSValuePair
*>(storage
);
219 AppendCSSValueToString(aProperty
, pair
->mXValue
, aResult
);
220 if (pair
->mYValue
!= pair
->mXValue
||
221 ((aProperty
== eCSSProperty_background_position
||
222 aProperty
== eCSSProperty__moz_transform_origin
) &&
223 pair
->mXValue
.GetUnit() != eCSSUnit_Inherit
&&
224 pair
->mXValue
.GetUnit() != eCSSUnit_Initial
)) {
225 // Only output a Y value if it's different from the X value
226 // or if it's a background-position value other than 'initial'
227 // or 'inherit' or if it's a -moz-transform-origin value other
228 // than 'initial' or 'inherit'.
229 aResult
.Append(PRUnichar(' '));
230 AppendCSSValueToString(aProperty
, pair
->mYValue
, aResult
);
233 case eCSSType_ValueList
: {
234 const nsCSSValueList
* val
=
235 *static_cast<nsCSSValueList
*const*>(storage
);
237 AppendCSSValueToString(aProperty
, val
->mValue
, aResult
);
240 if (nsCSSProps::PropHasFlags(aProperty
,
241 CSS_PROPERTY_VALUE_LIST_USES_COMMAS
))
242 aResult
.Append(PRUnichar(','));
243 aResult
.Append(PRUnichar(' '));
247 case eCSSType_ValuePairList
: {
248 const nsCSSValuePairList
* item
=
249 *static_cast<nsCSSValuePairList
*const*>(storage
);
251 NS_ASSERTION(item
->mXValue
.GetUnit() != eCSSUnit_Null
,
252 "unexpected null unit");
253 AppendCSSValueToString(aProperty
, item
->mXValue
, aResult
);
254 if (item
->mYValue
.GetUnit() != eCSSUnit_Null
) {
255 aResult
.Append(PRUnichar(' '));
256 AppendCSSValueToString(aProperty
, item
->mYValue
, aResult
);
260 aResult
.Append(PRUnichar(' '));
266 return storage
!= nsnull
;
270 nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty
,
271 const nsCSSValue
& aValue
,
274 nsCSSUnit unit
= aValue
.GetUnit();
276 if (eCSSUnit_Null
== unit
) {
280 if (eCSSUnit_String
<= unit
&& unit
<= eCSSUnit_Attr
) {
281 if (unit
== eCSSUnit_Attr
) {
282 aResult
.AppendLiteral("attr(");
285 aValue
.GetStringValue(buffer
);
286 aResult
.Append(buffer
);
288 else if (eCSSUnit_Array
<= unit
&& unit
<= eCSSUnit_Counters
) {
290 case eCSSUnit_Counter
: aResult
.AppendLiteral("counter("); break;
291 case eCSSUnit_Counters
: aResult
.AppendLiteral("counters("); break;
295 nsCSSValue::Array
*array
= aValue
.GetArrayValue();
296 PRBool mark
= PR_FALSE
;
297 for (PRUint16 i
= 0, i_end
= array
->Count(); i
< i_end
; ++i
) {
298 if (aProperty
== eCSSProperty_border_image
&& i
>= 5) {
299 if (array
->Item(i
).GetUnit() == eCSSUnit_Null
) {
303 aResult
.AppendLiteral(" /");
306 if (mark
&& array
->Item(i
).GetUnit() != eCSSUnit_Null
) {
307 if (unit
== eCSSUnit_Array
)
308 aResult
.AppendLiteral(" ");
310 aResult
.AppendLiteral(", ");
313 ((eCSSUnit_Counter
<= unit
&& unit
<= eCSSUnit_Counters
) &&
314 i
== array
->Count() - 1)
315 ? eCSSProperty_list_style_type
: aProperty
;
316 if (AppendCSSValueToString(prop
, array
->Item(i
), aResult
)) {
321 /* Although Function is backed by an Array, we'll handle it separately
322 * because it's a bit quirky.
324 else if (eCSSUnit_Function
== unit
) {
325 const nsCSSValue::Array
* array
= aValue
.GetArrayValue();
326 NS_ASSERTION(array
->Count() >= 1, "Functions must have at least one element for the name.");
328 /* Append the function name. */
329 AppendCSSValueToString(aProperty
, array
->Item(0), aResult
);
330 aResult
.AppendLiteral("(");
332 /* Now, step through the function contents, writing each of them as we go. */
333 for (PRUint16 index
= 1; index
< array
->Count(); ++index
) {
334 AppendCSSValueToString(aProperty
, array
->Item(index
), aResult
);
336 /* If we're not at the final element, append a comma. */
337 if (index
+ 1 != array
->Count())
338 aResult
.AppendLiteral(", ");
341 /* Finally, append the closing parenthesis. */
342 aResult
.AppendLiteral(")");
344 else if (eCSSUnit_Integer
== unit
) {
346 tmpStr
.AppendInt(aValue
.GetIntValue(), 10);
347 aResult
.Append(tmpStr
);
349 else if (eCSSUnit_Enumerated
== unit
) {
350 if (eCSSProperty_text_decoration
== aProperty
) {
351 PRInt32 intValue
= aValue
.GetIntValue();
352 if (NS_STYLE_TEXT_DECORATION_NONE
!= intValue
) {
354 for (mask
= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
355 mask
<= NS_STYLE_TEXT_DECORATION_BLINK
;
357 if ((mask
& intValue
) == mask
) {
358 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, mask
), aResult
);
360 if (0 != intValue
) { // more left
361 aResult
.Append(PRUnichar(' '));
367 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, NS_STYLE_TEXT_DECORATION_NONE
), aResult
);
370 else if (eCSSProperty_azimuth
== aProperty
) {
371 PRInt32 intValue
= aValue
.GetIntValue();
372 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, (intValue
& ~NS_STYLE_AZIMUTH_BEHIND
)), aResult
);
373 if ((NS_STYLE_AZIMUTH_BEHIND
& intValue
) != 0) {
374 aResult
.Append(PRUnichar(' '));
375 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, NS_STYLE_AZIMUTH_BEHIND
), aResult
);
378 else if (eCSSProperty_marks
== aProperty
) {
379 PRInt32 intValue
= aValue
.GetIntValue();
380 if ((NS_STYLE_PAGE_MARKS_CROP
& intValue
) != 0) {
381 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, NS_STYLE_PAGE_MARKS_CROP
), aResult
);
383 if ((NS_STYLE_PAGE_MARKS_REGISTER
& intValue
) != 0) {
384 if ((NS_STYLE_PAGE_MARKS_CROP
& intValue
) != 0) {
385 aResult
.Append(PRUnichar(' '));
387 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty
, NS_STYLE_PAGE_MARKS_REGISTER
), aResult
);
391 const nsAFlatCString
& name
= nsCSSProps::LookupPropertyValue(aProperty
, aValue
.GetIntValue());
392 AppendASCIItoUTF16(name
, aResult
);
395 else if (eCSSUnit_EnumColor
== unit
) {
396 // we can lookup the property in the ColorTable and then
397 // get a string mapping the name
399 if (nsCSSProps::GetColorName(aValue
.GetIntValue(), str
)){
400 AppendASCIItoUTF16(str
, aResult
);
402 NS_NOTREACHED("bad color value");
405 else if (eCSSUnit_Color
== unit
) {
406 nscolor color
= aValue
.GetColorValue();
407 if (color
== NS_RGBA(0, 0, 0, 0)) {
408 // Use the strictest match for 'transparent' so we do correct
409 // round-tripping of all other rgba() values.
410 aResult
.AppendLiteral("transparent");
413 PRUint8 a
= NS_GET_A(color
);
415 tmpStr
.AppendLiteral("rgba(");
417 tmpStr
.AppendLiteral("rgb(");
420 NS_NAMED_LITERAL_STRING(comma
, ", ");
422 tmpStr
.AppendInt(NS_GET_R(color
), 10);
423 tmpStr
.Append(comma
);
424 tmpStr
.AppendInt(NS_GET_G(color
), 10);
425 tmpStr
.Append(comma
);
426 tmpStr
.AppendInt(NS_GET_B(color
), 10);
428 tmpStr
.Append(comma
);
429 tmpStr
.AppendFloat(nsStyleUtil::ColorComponentToFloat(a
));
431 tmpStr
.Append(PRUnichar(')'));
433 aResult
.Append(tmpStr
);
436 else if (eCSSUnit_URL
== unit
|| eCSSUnit_Image
== unit
) {
437 aResult
.Append(NS_LITERAL_STRING("url(") +
438 nsDependentString(aValue
.GetOriginalURLValue()) +
439 NS_LITERAL_STRING(")"));
441 else if (eCSSUnit_Percent
== unit
) {
443 tmpStr
.AppendFloat(aValue
.GetPercentValue() * 100.0f
);
444 aResult
.Append(tmpStr
);
446 else if (eCSSUnit_Percent
< unit
) { // length unit
448 tmpStr
.AppendFloat(aValue
.GetFloatValue());
449 aResult
.Append(tmpStr
);
453 case eCSSUnit_Null
: break;
454 case eCSSUnit_Auto
: aResult
.AppendLiteral("auto"); break;
455 case eCSSUnit_Inherit
: aResult
.AppendLiteral("inherit"); break;
456 case eCSSUnit_Initial
: aResult
.AppendLiteral("-moz-initial"); break;
457 case eCSSUnit_None
: aResult
.AppendLiteral("none"); break;
458 case eCSSUnit_Normal
: aResult
.AppendLiteral("normal"); break;
459 case eCSSUnit_System_Font
: aResult
.AppendLiteral("-moz-use-system-font"); break;
460 case eCSSUnit_Dummy
: break;
462 case eCSSUnit_String
: break;
463 case eCSSUnit_URL
: break;
464 case eCSSUnit_Image
: break;
465 case eCSSUnit_Array
: break;
467 case eCSSUnit_Counter
:
468 case eCSSUnit_Counters
: aResult
.Append(PRUnichar(')')); break;
469 case eCSSUnit_Local_Font
: break;
470 case eCSSUnit_Font_Format
: break;
471 case eCSSUnit_Function
: break;
472 case eCSSUnit_Integer
: break;
473 case eCSSUnit_Enumerated
: break;
474 case eCSSUnit_EnumColor
: break;
475 case eCSSUnit_Color
: break;
476 case eCSSUnit_Percent
: aResult
.Append(PRUnichar('%')); break;
477 case eCSSUnit_Number
: break;
479 case eCSSUnit_Inch
: aResult
.AppendLiteral("in"); break;
480 case eCSSUnit_Foot
: aResult
.AppendLiteral("ft"); break;
481 case eCSSUnit_Mile
: aResult
.AppendLiteral("mi"); break;
482 case eCSSUnit_Millimeter
: aResult
.AppendLiteral("mm"); break;
483 case eCSSUnit_Centimeter
: aResult
.AppendLiteral("cm"); break;
484 case eCSSUnit_Meter
: aResult
.AppendLiteral("m"); break;
485 case eCSSUnit_Kilometer
: aResult
.AppendLiteral("km"); break;
486 case eCSSUnit_Point
: aResult
.AppendLiteral("pt"); break;
487 case eCSSUnit_Pica
: aResult
.AppendLiteral("pc"); break;
488 case eCSSUnit_Didot
: aResult
.AppendLiteral("dt"); break;
489 case eCSSUnit_Cicero
: aResult
.AppendLiteral("cc"); break;
491 case eCSSUnit_EM
: aResult
.AppendLiteral("em"); break;
492 case eCSSUnit_XHeight
: aResult
.AppendLiteral("ex"); break;
493 case eCSSUnit_Char
: aResult
.AppendLiteral("ch"); break;
495 case eCSSUnit_Pixel
: aResult
.AppendLiteral("px"); break;
497 case eCSSUnit_Degree
: aResult
.AppendLiteral("deg"); break;
498 case eCSSUnit_Grad
: aResult
.AppendLiteral("grad"); break;
499 case eCSSUnit_Radian
: aResult
.AppendLiteral("rad"); break;
501 case eCSSUnit_Hertz
: aResult
.AppendLiteral("Hz"); break;
502 case eCSSUnit_Kilohertz
: aResult
.AppendLiteral("kHz"); break;
504 case eCSSUnit_Seconds
: aResult
.Append(PRUnichar('s')); break;
505 case eCSSUnit_Milliseconds
: aResult
.AppendLiteral("ms"); break;
512 nsCSSDeclaration::GetValue(nsCSSProperty aProperty
,
513 nsAString
& aValue
) const
517 // simple properties are easy.
518 if (!nsCSSProps::IsShorthand(aProperty
)) {
519 AppendValueToString(aProperty
, aValue
);
523 // DOM Level 2 Style says (when describing CSS2Properties, although
524 // not CSSStyleDeclaration.getPropertyValue):
525 // However, if there is no shorthand declaration that could be added
526 // to the ruleset without changing in any way the rules already
527 // declared in the ruleset (i.e., by adding longhand rules that were
528 // previously not declared in the ruleset), then the empty string
529 // should be returned for the shorthand property.
530 // This means we need to check a number of cases:
531 // (1) Since a shorthand sets all sub-properties, if some of its
532 // subproperties were not specified, we must return the empty
534 // (2) Since 'inherit' and 'initial' can only be specified as the
535 // values for entire properties, we need to return the empty
536 // string if some but not all of the subproperties have one of
538 // (3) Since a single value only makes sense with or without
539 // !important, we return the empty string if some values are
540 // !important and some are not.
541 // Since we're doing this check for 'inherit' and 'initial' up front,
542 // we can also simplify the property serialization code by serializing
543 // those values up front as well.
544 PRUint32 totalCount
= 0, importantCount
= 0,
545 initialCount
= 0, inheritCount
= 0;
546 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p
, aProperty
) {
547 if (*p
== eCSSProperty__x_system_font
||
548 nsCSSProps::PropHasFlags(*p
, CSS_PROPERTY_DIRECTIONAL_SOURCE
)) {
549 // The system-font subproperty and the *-source properties don't count.
553 const void *storage
= mData
->StorageFor(*p
);
554 NS_ASSERTION(!storage
|| !mImportantData
|| !mImportantData
->StorageFor(*p
),
555 "can't be in both blocks");
556 if (!storage
&& mImportantData
) {
558 storage
= mImportantData
->StorageFor(*p
);
561 // Case (1) above: some subproperties not specified.
565 switch (nsCSSProps::kTypeTable
[*p
]) {
566 case eCSSType_Value
: {
567 const nsCSSValue
*val
= static_cast<const nsCSSValue
*>(storage
);
568 unit
= val
->GetUnit();
570 case eCSSType_Rect
: {
571 const nsCSSRect
*rect
= static_cast<const nsCSSRect
*>(storage
);
572 unit
= rect
->mTop
.GetUnit();
574 case eCSSType_ValuePair
: {
575 const nsCSSValuePair
*pair
= static_cast<const nsCSSValuePair
*>(storage
);
576 unit
= pair
->mXValue
.GetUnit();
578 case eCSSType_ValueList
: {
579 const nsCSSValueList
* item
=
580 *static_cast<nsCSSValueList
*const*>(storage
);
582 unit
= item
->mValue
.GetUnit();
584 unit
= eCSSUnit_Null
;
587 case eCSSType_ValuePairList
: {
588 const nsCSSValuePairList
* item
=
589 *static_cast<nsCSSValuePairList
*const*>(storage
);
591 unit
= item
->mXValue
.GetUnit();
593 unit
= eCSSUnit_Null
;
597 if (unit
== eCSSUnit_Inherit
) {
599 } else if (unit
== eCSSUnit_Initial
) {
603 if (importantCount
!= 0 && importantCount
!= totalCount
) {
604 // Case (3), no consistent importance.
607 if (initialCount
== totalCount
) {
608 // Simplify serialization below by serializing initial up-front.
609 AppendCSSValueToString(eCSSProperty_UNKNOWN
, nsCSSValue(eCSSUnit_Initial
),
613 if (inheritCount
== totalCount
) {
614 // Simplify serialization below by serializing inherit up-front.
615 AppendCSSValueToString(eCSSProperty_UNKNOWN
, nsCSSValue(eCSSUnit_Inherit
),
619 if (initialCount
!= 0 || inheritCount
!= 0) {
620 // Case (2): partially initial or inherit.
625 // XXX What about checking the consistency of '!important'?
626 // XXX What about checking that we don't serialize inherit,
627 // -moz-initial, or other illegal values?
628 // XXXldb Can we share shorthand logic with ToString?
630 case eCSSProperty_margin
:
631 case eCSSProperty_padding
:
632 case eCSSProperty_border_color
:
633 case eCSSProperty_border_style
:
634 case eCSSProperty_border_width
: {
635 const nsCSSProperty
* subprops
=
636 nsCSSProps::SubpropertyEntryFor(aProperty
);
637 NS_ASSERTION(nsCSSProps::kTypeTable
[subprops
[0]] == eCSSType_Value
&&
638 nsCSSProps::kTypeTable
[subprops
[1]] == eCSSType_Value
&&
639 nsCSSProps::kTypeTable
[subprops
[2]] == eCSSType_Value
&&
640 nsCSSProps::kTypeTable
[subprops
[3]] == eCSSType_Value
,
642 if (!AppendValueToString(subprops
[0], aValue
) ||
643 !(aValue
.Append(PRUnichar(' ')),
644 AppendValueToString(subprops
[1], aValue
)) ||
645 !(aValue
.Append(PRUnichar(' ')),
646 AppendValueToString(subprops
[2], aValue
)) ||
647 !(aValue
.Append(PRUnichar(' ')),
648 AppendValueToString(subprops
[3], aValue
))) {
653 case eCSSProperty__moz_border_radius
:
654 case eCSSProperty__moz_outline_radius
: {
655 const nsCSSProperty
* subprops
=
656 nsCSSProps::SubpropertyEntryFor(aProperty
);
657 NS_ASSERTION(nsCSSProps::kTypeTable
[subprops
[0]] == eCSSType_ValuePair
&&
658 nsCSSProps::kTypeTable
[subprops
[1]] == eCSSType_ValuePair
&&
659 nsCSSProps::kTypeTable
[subprops
[2]] == eCSSType_ValuePair
&&
660 nsCSSProps::kTypeTable
[subprops
[3]] == eCSSType_ValuePair
,
662 nsCSSCompressedDataBlock
*data
= GetValueIsImportant(aProperty
)
663 ? mImportantData
: mData
;
664 const nsCSSValuePair
* vals
[4] = {
665 static_cast<const nsCSSValuePair
*>(data
->StorageFor(subprops
[0])),
666 static_cast<const nsCSSValuePair
*>(data
->StorageFor(subprops
[1])),
667 static_cast<const nsCSSValuePair
*>(data
->StorageFor(subprops
[2])),
668 static_cast<const nsCSSValuePair
*>(data
->StorageFor(subprops
[3]))
671 AppendCSSValueToString(aProperty
, vals
[0]->mXValue
, aValue
);
672 aValue
.Append(PRUnichar(' '));
673 AppendCSSValueToString(aProperty
, vals
[1]->mXValue
, aValue
);
674 aValue
.Append(PRUnichar(' '));
675 AppendCSSValueToString(aProperty
, vals
[2]->mXValue
, aValue
);
676 aValue
.Append(PRUnichar(' '));
677 AppendCSSValueToString(aProperty
, vals
[3]->mXValue
, aValue
);
679 // For compatibility, only write a slash and the y-values
680 // if they're not identical to the x-values.
681 if (vals
[0]->mXValue
!= vals
[0]->mYValue
||
682 vals
[1]->mXValue
!= vals
[1]->mYValue
||
683 vals
[2]->mXValue
!= vals
[2]->mYValue
||
684 vals
[3]->mXValue
!= vals
[3]->mYValue
) {
685 aValue
.AppendLiteral(" / ");
686 AppendCSSValueToString(aProperty
, vals
[0]->mYValue
, aValue
);
687 aValue
.Append(PRUnichar(' '));
688 AppendCSSValueToString(aProperty
, vals
[1]->mYValue
, aValue
);
689 aValue
.Append(PRUnichar(' '));
690 AppendCSSValueToString(aProperty
, vals
[2]->mYValue
, aValue
);
691 aValue
.Append(PRUnichar(' '));
692 AppendCSSValueToString(aProperty
, vals
[3]->mYValue
, aValue
);
696 case eCSSProperty_border
:
697 // XXX More consistency checking needed before falling through.
698 aProperty
= eCSSProperty_border_top
;
699 case eCSSProperty_border_top
:
700 case eCSSProperty_border_right
:
701 case eCSSProperty_border_bottom
:
702 case eCSSProperty_border_left
:
703 case eCSSProperty_border_start
:
704 case eCSSProperty_border_end
:
705 case eCSSProperty__moz_column_rule
:
706 case eCSSProperty_outline
: {
707 const nsCSSProperty
* subprops
=
708 nsCSSProps::SubpropertyEntryFor(aProperty
);
709 NS_ASSERTION(nsCSSProps::kTypeTable
[subprops
[0]] == eCSSType_Value
&&
710 nsCSSProps::kTypeTable
[subprops
[1]] == eCSSType_Value
&&
711 nsCSSProps::kTypeTable
[subprops
[2]] == eCSSType_Value
,
713 if (!AppendValueToString(subprops
[0], aValue
) ||
714 !(aValue
.Append(PRUnichar(' ')),
715 AppendValueToString(subprops
[1], aValue
)) ||
716 !(aValue
.Append(PRUnichar(' ')),
717 AppendValueToString(subprops
[2], aValue
))) {
722 case eCSSProperty_margin_left
:
723 case eCSSProperty_margin_right
:
724 case eCSSProperty_margin_start
:
725 case eCSSProperty_margin_end
:
726 case eCSSProperty_padding_left
:
727 case eCSSProperty_padding_right
:
728 case eCSSProperty_padding_start
:
729 case eCSSProperty_padding_end
:
730 case eCSSProperty_border_left_color
:
731 case eCSSProperty_border_left_style
:
732 case eCSSProperty_border_left_width
:
733 case eCSSProperty_border_right_color
:
734 case eCSSProperty_border_right_style
:
735 case eCSSProperty_border_right_width
:
736 case eCSSProperty_border_start_color
:
737 case eCSSProperty_border_start_style
:
738 case eCSSProperty_border_start_width
:
739 case eCSSProperty_border_end_color
:
740 case eCSSProperty_border_end_style
:
741 case eCSSProperty_border_end_width
: {
742 const nsCSSProperty
* subprops
=
743 nsCSSProps::SubpropertyEntryFor(aProperty
);
744 NS_ASSERTION(subprops
[3] == eCSSProperty_UNKNOWN
,
745 "not box property with physical vs. logical cascading");
746 AppendValueToString(subprops
[0], aValue
);
749 case eCSSProperty_background
: {
750 PRBool appendedSomething
= PR_FALSE
;
751 if (AppendValueToString(eCSSProperty_background_color
, aValue
)) {
752 appendedSomething
= PR_TRUE
;
753 aValue
.Append(PRUnichar(' '));
755 if (AppendValueToString(eCSSProperty_background_image
, aValue
)) {
756 aValue
.Append(PRUnichar(' '));
757 appendedSomething
= PR_TRUE
;
759 if (AppendValueToString(eCSSProperty_background_repeat
, aValue
)) {
760 aValue
.Append(PRUnichar(' '));
761 appendedSomething
= PR_TRUE
;
763 if (AppendValueToString(eCSSProperty_background_attachment
, aValue
)) {
764 aValue
.Append(PRUnichar(' '));
765 appendedSomething
= PR_TRUE
;
767 if (!AppendValueToString(eCSSProperty_background_position
, aValue
) &&
769 NS_ASSERTION(!aValue
.IsEmpty() && aValue
.Last() == PRUnichar(' '),
770 "We appended a space before!");
771 // We appended an extra space. Let's get rid of it
772 aValue
.Truncate(aValue
.Length() - 1);
776 case eCSSProperty_cue
: {
777 if (AppendValueToString(eCSSProperty_cue_before
, aValue
)) {
778 aValue
.Append(PRUnichar(' '));
779 if (!AppendValueToString(eCSSProperty_cue_after
, aValue
))
784 case eCSSProperty_font
: {
785 nsCSSValue style
, variant
, weight
, size
, lh
, family
, systemFont
;
786 GetValueOrImportantValue(eCSSProperty__x_system_font
, systemFont
);
787 GetValueOrImportantValue(eCSSProperty_font_style
, style
);
788 GetValueOrImportantValue(eCSSProperty_font_variant
, variant
);
789 GetValueOrImportantValue(eCSSProperty_font_weight
, weight
);
790 GetValueOrImportantValue(eCSSProperty_font_size
, size
);
791 GetValueOrImportantValue(eCSSProperty_line_height
, lh
);
792 GetValueOrImportantValue(eCSSProperty_font_family
, family
);
794 if (systemFont
.GetUnit() != eCSSUnit_None
&&
795 systemFont
.GetUnit() != eCSSUnit_Null
) {
796 AppendCSSValueToString(eCSSProperty__x_system_font
, systemFont
, aValue
);
798 if (style
.GetUnit() != eCSSUnit_Normal
) {
799 AppendCSSValueToString(eCSSProperty_font_style
, style
, aValue
);
800 aValue
.Append(PRUnichar(' '));
802 if (variant
.GetUnit() != eCSSUnit_Normal
) {
803 AppendCSSValueToString(eCSSProperty_font_variant
, variant
, aValue
);
804 aValue
.Append(PRUnichar(' '));
806 if (weight
.GetUnit() != eCSSUnit_Normal
) {
807 AppendCSSValueToString(eCSSProperty_font_weight
, weight
, aValue
);
808 aValue
.Append(PRUnichar(' '));
810 AppendCSSValueToString(eCSSProperty_font_size
, size
, aValue
);
811 if (lh
.GetUnit() != eCSSUnit_Normal
) {
812 aValue
.Append(PRUnichar('/'));
813 AppendCSSValueToString(eCSSProperty_line_height
, lh
, aValue
);
815 aValue
.Append(PRUnichar(' '));
816 AppendCSSValueToString(eCSSProperty_font_family
, family
, aValue
);
820 case eCSSProperty_list_style
:
821 if (AppendValueToString(eCSSProperty_list_style_type
, aValue
))
822 aValue
.Append(PRUnichar(' '));
823 if (AppendValueToString(eCSSProperty_list_style_position
, aValue
))
824 aValue
.Append(PRUnichar(' '));
825 AppendValueToString(eCSSProperty_list_style_image
, aValue
);
827 case eCSSProperty_overflow
: {
828 nsCSSValue xValue
, yValue
;
829 GetValueOrImportantValue(eCSSProperty_overflow_x
, xValue
);
830 GetValueOrImportantValue(eCSSProperty_overflow_y
, yValue
);
831 if (xValue
== yValue
)
832 AppendValueToString(eCSSProperty_overflow_x
, aValue
);
835 case eCSSProperty_pause
: {
836 if (AppendValueToString(eCSSProperty_pause_before
, aValue
)) {
837 aValue
.Append(PRUnichar(' '));
838 if (!AppendValueToString(eCSSProperty_pause_after
, aValue
))
844 case eCSSProperty_marker
: {
845 nsCSSValue endValue
, midValue
, startValue
;
846 GetValueOrImportantValue(eCSSProperty_marker_end
, endValue
);
847 GetValueOrImportantValue(eCSSProperty_marker_mid
, midValue
);
848 GetValueOrImportantValue(eCSSProperty_marker_start
, startValue
);
849 if (endValue
== midValue
&& midValue
== startValue
)
850 AppendValueToString(eCSSProperty_marker_end
, aValue
);
855 NS_NOTREACHED("no other shorthands");
862 nsCSSDeclaration::GetValueIsImportant(const nsAString
& aProperty
) const
864 nsCSSProperty propID
= nsCSSProps::LookupProperty(aProperty
);
865 return GetValueIsImportant(propID
);
869 nsCSSDeclaration::GetValueIsImportant(nsCSSProperty aProperty
) const
874 // Calling StorageFor is inefficient, but we can assume '!important'
877 if (nsCSSProps::IsShorthand(aProperty
)) {
878 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p
, aProperty
) {
879 if (*p
== eCSSProperty__x_system_font
) {
880 // The system_font subproperty doesn't count.
883 if (!mImportantData
->StorageFor(*p
)) {
890 return mImportantData
->StorageFor(aProperty
) != nsnull
;
893 // XXXldb Bug 376075 All callers of AllPropertiesSameImportance also
894 // need to check for 'inherit' and 'initial' values, since you can't
895 // output a mix of either mixed with other values in the same shorthand!
897 nsCSSDeclaration::AllPropertiesSameImportance(PRInt32 aFirst
, PRInt32 aSecond
,
898 PRInt32 aThird
, PRInt32 aFourth
,
900 PRBool
& aImportance
) const
902 aImportance
= GetValueIsImportant(OrderValueAt(aFirst
-1));
903 if ((aSecond
&& aImportance
!= GetValueIsImportant(OrderValueAt(aSecond
-1))) ||
904 (aThird
&& aImportance
!= GetValueIsImportant(OrderValueAt(aThird
-1))) ||
905 (aFourth
&& aImportance
!= GetValueIsImportant(OrderValueAt(aFourth
-1))) ||
906 (aFifth
&& aImportance
!= GetValueIsImportant(OrderValueAt(aFifth
-1)))) {
913 nsCSSDeclaration::AllPropertiesSameValue(PRInt32 aFirst
, PRInt32 aSecond
,
914 PRInt32 aThird
, PRInt32 aFourth
) const
916 nsCSSValue firstValue
, otherValue
;
917 // TryBorderShorthand does the bounds-checking for us; valid values there
918 // are > 0; 0 is a flag for "not set". We here are passed the actual
919 // index, which comes from finding the value in the mOrder property array.
920 // Of course, re-getting the mOrder value here is pretty silly.
921 GetValueOrImportantValue(OrderValueAt(aFirst
-1), firstValue
);
922 GetValueOrImportantValue(OrderValueAt(aSecond
-1), otherValue
);
923 if (firstValue
!= otherValue
) {
926 GetValueOrImportantValue(OrderValueAt(aThird
-1), otherValue
);
927 if (firstValue
!= otherValue
) {
930 GetValueOrImportantValue(OrderValueAt(aFourth
-1), otherValue
);
931 if (firstValue
!= otherValue
) {
938 nsCSSDeclaration::AppendImportanceToString(PRBool aIsImportant
,
942 aString
.AppendLiteral(" ! important");
947 nsCSSDeclaration::AppendPropertyAndValueToString(nsCSSProperty aProperty
,
948 nsCSSProperty aPropertyName
,
949 nsAString
& aResult
) const
951 NS_ASSERTION(0 <= aProperty
&& aProperty
< eCSSProperty_COUNT_no_shorthands
,
952 "property enum out of range");
953 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aPropertyName
), aResult
);
954 aResult
.AppendLiteral(": ");
955 AppendValueToString(aProperty
, aResult
);
956 PRBool isImportant
= GetValueIsImportant(aProperty
);
957 AppendImportanceToString(isImportant
, aResult
);
958 aResult
.AppendLiteral("; ");
962 nsCSSDeclaration::TryBorderShorthand(nsAString
& aString
, PRUint32 aPropertiesSet
,
963 PRInt32 aBorderTopWidth
,
964 PRInt32 aBorderTopStyle
,
965 PRInt32 aBorderTopColor
,
966 PRInt32 aBorderBottomWidth
,
967 PRInt32 aBorderBottomStyle
,
968 PRInt32 aBorderBottomColor
,
969 PRInt32 aBorderLeftWidth
,
970 PRInt32 aBorderLeftStyle
,
971 PRInt32 aBorderLeftColor
,
972 PRInt32 aBorderRightWidth
,
973 PRInt32 aBorderRightStyle
,
974 PRInt32 aBorderRightColor
) const
976 PRBool border
= PR_FALSE
, isImportant
= PR_FALSE
;
977 // 0 means not in the mOrder array; otherwise it's index+1
978 if (B_BORDER
== aPropertiesSet
979 && AllPropertiesSameValue(aBorderTopWidth
, aBorderBottomWidth
,
980 aBorderLeftWidth
, aBorderRightWidth
)
981 && AllPropertiesSameValue(aBorderTopStyle
, aBorderBottomStyle
,
982 aBorderLeftStyle
, aBorderRightStyle
)
983 && AllPropertiesSameValue(aBorderTopColor
, aBorderBottomColor
,
984 aBorderLeftColor
, aBorderRightColor
)) {
989 PRBool isWidthImportant
, isStyleImportant
, isColorImportant
;
990 if (AllPropertiesSameImportance(aBorderTopWidth
, aBorderBottomWidth
,
991 aBorderLeftWidth
, aBorderRightWidth
,
994 AllPropertiesSameImportance(aBorderTopStyle
, aBorderBottomStyle
,
995 aBorderLeftStyle
, aBorderRightStyle
,
998 AllPropertiesSameImportance(aBorderTopColor
, aBorderBottomColor
,
999 aBorderLeftColor
, aBorderRightColor
,
1001 isColorImportant
)) {
1002 if (isWidthImportant
== isStyleImportant
&& isWidthImportant
== isColorImportant
) {
1004 isImportant
= isWidthImportant
;
1009 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_border
), aString
);
1010 aString
.AppendLiteral(": ");
1012 AppendValueToString(eCSSProperty_border_top_width
, aString
);
1013 aString
.Append(PRUnichar(' '));
1015 AppendValueToString(eCSSProperty_border_top_style
, aString
);
1016 aString
.Append(PRUnichar(' '));
1018 nsAutoString valueString
;
1019 AppendValueToString(eCSSProperty_border_top_color
, valueString
);
1020 if (!valueString
.EqualsLiteral("-moz-use-text-color")) {
1021 /* don't output this value, it's proprietary Mozilla and */
1022 /* not intended to be exposed ; we can remove it from the */
1023 /* values of the shorthand since this value represents the */
1024 /* initial value of border-*-color */
1025 aString
.Append(valueString
);
1027 AppendImportanceToString(isImportant
, aString
);
1028 aString
.AppendLiteral("; ");
1034 nsCSSDeclaration::TryBorderSideShorthand(nsAString
& aString
,
1035 nsCSSProperty aShorthand
,
1036 PRInt32 aBorderWidth
,
1037 PRInt32 aBorderStyle
,
1038 PRInt32 aBorderColor
) const
1041 if (AllPropertiesSameImportance(aBorderWidth
, aBorderStyle
, aBorderColor
,
1044 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand
), aString
);
1045 aString
.AppendLiteral(": ");
1047 AppendValueToString(OrderValueAt(aBorderWidth
-1), aString
);
1049 aString
.Append(PRUnichar(' '));
1050 AppendValueToString(OrderValueAt(aBorderStyle
-1), aString
);
1052 nsAutoString valueString
;
1053 AppendValueToString(OrderValueAt(aBorderColor
-1), valueString
);
1054 if (!valueString
.EqualsLiteral("-moz-use-text-color")) {
1055 aString
.AppendLiteral(" ");
1056 aString
.Append(valueString
);
1058 AppendImportanceToString(isImportant
, aString
);
1059 aString
.AppendLiteral("; ");
1066 nsCSSDeclaration::TryFourSidesShorthand(nsAString
& aString
,
1067 nsCSSProperty aShorthand
,
1072 PRBool aClearIndexes
) const
1074 // 0 means not in the mOrder array; otherwise it's index+1
1076 if (aTop
&& aBottom
&& aLeft
&& aRight
&&
1077 AllPropertiesSameImportance(aTop
, aBottom
, aLeft
, aRight
,
1080 // all 4 properties are set, we can output a shorthand
1081 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand
), aString
);
1082 aString
.AppendLiteral(": ");
1083 nsCSSValue topValue
, bottomValue
, leftValue
, rightValue
;
1084 nsCSSProperty topProp
= OrderValueAt(aTop
-1);
1085 nsCSSProperty bottomProp
= OrderValueAt(aBottom
-1);
1086 nsCSSProperty leftProp
= OrderValueAt(aLeft
-1);
1087 nsCSSProperty rightProp
= OrderValueAt(aRight
-1);
1088 GetValueOrImportantValue(topProp
, topValue
);
1089 GetValueOrImportantValue(bottomProp
, bottomValue
);
1090 GetValueOrImportantValue(leftProp
, leftValue
);
1091 GetValueOrImportantValue(rightProp
, rightValue
);
1092 AppendCSSValueToString(topProp
, topValue
, aString
);
1093 if (topValue
!= rightValue
|| topValue
!= leftValue
|| topValue
!= bottomValue
) {
1094 aString
.Append(PRUnichar(' '));
1095 AppendCSSValueToString(rightProp
, rightValue
, aString
);
1096 if (topValue
!= bottomValue
|| rightValue
!= leftValue
) {
1097 aString
.Append(PRUnichar(' '));
1098 AppendCSSValueToString(bottomProp
, bottomValue
, aString
);
1099 if (rightValue
!= leftValue
) {
1100 aString
.Append(PRUnichar(' '));
1101 AppendCSSValueToString(leftProp
, leftValue
, aString
);
1105 if (aClearIndexes
) {
1106 aTop
= 0; aBottom
= 0; aLeft
= 0; aRight
= 0;
1108 AppendImportanceToString(isImportant
, aString
);
1109 aString
.AppendLiteral("; ");
1116 nsCSSDeclaration::TryBackgroundShorthand(nsAString
& aString
,
1119 PRInt32
& aBgRepeat
,
1120 PRInt32
& aBgAttachment
,
1121 PRInt32
& aBgPosition
) const
1123 // 0 means not in the mOrder array; otherwise it's index+1
1124 // check if we have at least two properties set; otherwise, no need to
1127 if (aBgColor
&& aBgImage
&& aBgRepeat
&& aBgAttachment
&& aBgPosition
&&
1128 AllPropertiesSameImportance(aBgColor
, aBgImage
, aBgRepeat
, aBgAttachment
,
1129 aBgPosition
, isImportant
)) {
1130 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_background
), aString
);
1131 aString
.AppendLiteral(": ");
1133 AppendValueToString(eCSSProperty_background_color
, aString
);
1136 aString
.Append(PRUnichar(' '));
1137 AppendValueToString(eCSSProperty_background_image
, aString
);
1140 aString
.Append(PRUnichar(' '));
1141 AppendValueToString(eCSSProperty_background_repeat
, aString
);
1144 aString
.Append(PRUnichar(' '));
1145 AppendValueToString(eCSSProperty_background_attachment
, aString
);
1148 aString
.Append(PRUnichar(' '));
1149 AppendValueToString(eCSSProperty_background_position
, aString
);
1152 AppendImportanceToString(isImportant
, aString
);
1153 aString
.AppendLiteral("; ");
1158 nsCSSDeclaration::TryOverflowShorthand(nsAString
& aString
,
1159 PRInt32
& aOverflowX
,
1160 PRInt32
& aOverflowY
) const
1163 if (aOverflowX
&& aOverflowY
&&
1164 AllPropertiesSameImportance(aOverflowX
, aOverflowY
,
1165 0, 0, 0, isImportant
)) {
1166 nsCSSValue xValue
, yValue
;
1167 GetValueOrImportantValue(eCSSProperty_overflow_x
, xValue
);
1168 GetValueOrImportantValue(eCSSProperty_overflow_y
, yValue
);
1169 if (xValue
== yValue
) {
1170 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_overflow
),
1172 aString
.AppendLiteral(": ");
1174 AppendCSSValueToString(eCSSProperty_overflow_x
, xValue
, aString
);
1175 AppendImportanceToString(isImportant
, aString
);
1176 aString
.AppendLiteral("; ");
1177 aOverflowX
= aOverflowY
= 0;
1184 nsCSSDeclaration::TryMarkerShorthand(nsAString
& aString
,
1185 PRInt32
& aMarkerEnd
,
1186 PRInt32
& aMarkerMid
,
1187 PRInt32
& aMarkerStart
) const
1190 if (aMarkerEnd
&& aMarkerMid
&& aMarkerEnd
&&
1191 AllPropertiesSameImportance(aMarkerEnd
, aMarkerMid
, aMarkerStart
,
1192 0, 0, isImportant
)) {
1193 nsCSSValue endValue
, midValue
, startValue
;
1194 GetValueOrImportantValue(eCSSProperty_marker_end
, endValue
);
1195 GetValueOrImportantValue(eCSSProperty_marker_mid
, midValue
);
1196 GetValueOrImportantValue(eCSSProperty_marker_start
, startValue
);
1197 if (endValue
== midValue
&& midValue
== startValue
) {
1198 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_marker
),
1200 aString
.AppendLiteral(": ");
1202 AppendCSSValueToString(eCSSProperty_marker_end
, endValue
, aString
);
1203 AppendImportanceToString(isImportant
, aString
);
1204 aString
.AppendLiteral("; ");
1205 aMarkerEnd
= aMarkerMid
= aMarkerStart
= 0;
1211 #define NS_CASE_OUTPUT_PROPERTY_VALUE(_prop, _index) \
1214 AppendPropertyAndValueToString(property, aString); \
1219 #define NS_CASE_OUTPUT_PROPERTY_VALUE_AS(_prop, _propas, _index) \
1222 AppendPropertyAndValueToString(property, _propas, aString); \
1227 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(_condition, _prop, _index) \
1229 if ((_condition) && _index) { \
1230 AppendPropertyAndValueToString(property, aString); \
1235 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(_condition, _prop, _propas, _index) \
1237 if ((_condition) && _index) { \
1238 AppendPropertyAndValueToString(property, _propas, aString); \
1243 void nsCSSDeclaration::PropertyIsSet(PRInt32
& aPropertyIndex
, PRInt32 aIndex
, PRUint32
& aSet
, PRUint32 aValue
) const
1245 aPropertyIndex
= aIndex
+ 1;
1250 nsCSSDeclaration::ToString(nsAString
& aString
) const
1252 PRInt32 count
= mOrder
.Length();
1254 // 0 means not in the mOrder array; otherwise it's index+1
1255 PRInt32 borderTopWidth
= 0, borderTopStyle
= 0, borderTopColor
= 0;
1256 PRInt32 borderBottomWidth
= 0, borderBottomStyle
= 0, borderBottomColor
= 0;
1257 PRInt32 borderLeftWidth
= 0, borderLeftStyle
= 0, borderLeftColor
= 0;
1258 PRInt32 borderRightWidth
= 0, borderRightStyle
= 0, borderRightColor
= 0;
1259 PRInt32 borderStartWidth
= 0, borderStartStyle
= 0, borderStartColor
= 0;
1260 PRInt32 borderEndWidth
= 0, borderEndStyle
= 0, borderEndColor
= 0;
1261 PRInt32 marginTop
= 0, marginBottom
= 0, marginLeft
= 0, marginRight
= 0;
1262 PRInt32 paddingTop
= 0, paddingBottom
= 0, paddingLeft
= 0, paddingRight
= 0;
1263 PRInt32 bgColor
= 0, bgImage
= 0, bgRepeat
= 0, bgAttachment
= 0;
1264 PRInt32 bgPosition
= 0;
1265 PRInt32 overflowX
= 0, overflowY
= 0;
1266 PRInt32 columnRuleWidth
= 0, columnRuleStyle
= 0, columnRuleColor
= 0;
1267 PRUint32 borderPropertiesSet
= 0, finalBorderPropertiesToSet
= 0;
1269 PRInt32 markerEnd
= 0, markerMid
= 0, markerStart
= 0;
1272 for (index
= 0; index
< count
; index
++) {
1273 nsCSSProperty property
= OrderValueAt(index
);
1275 case eCSSProperty_border_top_width
:
1276 PropertyIsSet(borderTopWidth
, index
, borderPropertiesSet
, B_BORDER_TOP_WIDTH
);
1278 case eCSSProperty_border_bottom_width
:
1279 PropertyIsSet(borderBottomWidth
, index
, borderPropertiesSet
, B_BORDER_BOTTOM_WIDTH
);
1281 case eCSSProperty_border_left_width_value
:
1282 PropertyIsSet(borderLeftWidth
, index
, borderPropertiesSet
, B_BORDER_LEFT_WIDTH
);
1284 case eCSSProperty_border_right_width_value
:
1285 PropertyIsSet(borderRightWidth
, index
, borderPropertiesSet
, B_BORDER_RIGHT_WIDTH
);
1287 case eCSSProperty_border_start_width_value
:
1288 borderStartWidth
= index
+1;
1290 case eCSSProperty_border_end_width_value
:
1291 borderEndWidth
= index
+1;
1294 case eCSSProperty_border_top_style
:
1295 PropertyIsSet(borderTopStyle
, index
, borderPropertiesSet
, B_BORDER_TOP_STYLE
);
1297 case eCSSProperty_border_bottom_style
:
1298 PropertyIsSet(borderBottomStyle
, index
, borderPropertiesSet
, B_BORDER_BOTTOM_STYLE
);
1300 case eCSSProperty_border_left_style_value
:
1301 PropertyIsSet(borderLeftStyle
, index
, borderPropertiesSet
, B_BORDER_LEFT_STYLE
);
1303 case eCSSProperty_border_right_style_value
:
1304 PropertyIsSet(borderRightStyle
, index
, borderPropertiesSet
, B_BORDER_RIGHT_STYLE
);
1306 case eCSSProperty_border_start_style_value
:
1307 borderStartStyle
= index
+1;
1309 case eCSSProperty_border_end_style_value
:
1310 borderEndStyle
= index
+1;
1313 case eCSSProperty_border_top_color
:
1314 PropertyIsSet(borderTopColor
, index
, borderPropertiesSet
, B_BORDER_TOP_COLOR
);
1316 case eCSSProperty_border_bottom_color
:
1317 PropertyIsSet(borderBottomColor
, index
, borderPropertiesSet
, B_BORDER_BOTTOM_COLOR
);
1319 case eCSSProperty_border_left_color_value
:
1320 PropertyIsSet(borderLeftColor
, index
, borderPropertiesSet
, B_BORDER_LEFT_COLOR
);
1322 case eCSSProperty_border_right_color_value
:
1323 PropertyIsSet(borderRightColor
, index
, borderPropertiesSet
, B_BORDER_RIGHT_COLOR
);
1325 case eCSSProperty_border_start_color_value
:
1326 borderStartColor
= index
+1;
1328 case eCSSProperty_border_end_color_value
:
1329 borderEndColor
= index
+1;
1332 case eCSSProperty_margin_top
: marginTop
= index
+1; break;
1333 case eCSSProperty_margin_bottom
: marginBottom
= index
+1; break;
1334 case eCSSProperty_margin_left_value
: marginLeft
= index
+1; break;
1335 case eCSSProperty_margin_right_value
: marginRight
= index
+1; break;
1337 case eCSSProperty_padding_top
: paddingTop
= index
+1; break;
1338 case eCSSProperty_padding_bottom
: paddingBottom
= index
+1; break;
1339 case eCSSProperty_padding_left_value
: paddingLeft
= index
+1; break;
1340 case eCSSProperty_padding_right_value
: paddingRight
= index
+1; break;
1342 case eCSSProperty_background_color
: bgColor
= index
+1; break;
1343 case eCSSProperty_background_image
: bgImage
= index
+1; break;
1344 case eCSSProperty_background_repeat
: bgRepeat
= index
+1; break;
1345 case eCSSProperty_background_attachment
: bgAttachment
= index
+1; break;
1346 case eCSSProperty_background_position
: bgPosition
= index
+1; break;
1348 case eCSSProperty_overflow_x
: overflowX
= index
+1; break;
1349 case eCSSProperty_overflow_y
: overflowY
= index
+1; break;
1351 case eCSSProperty__moz_column_rule_width
: columnRuleWidth
= index
+1; break;
1352 case eCSSProperty__moz_column_rule_style
: columnRuleStyle
= index
+1; break;
1353 case eCSSProperty__moz_column_rule_color
: columnRuleColor
= index
+1; break;
1356 case eCSSProperty_marker_end
: markerEnd
= index
+1; break;
1357 case eCSSProperty_marker_mid
: markerMid
= index
+1; break;
1358 case eCSSProperty_marker_start
: markerStart
= index
+1; break;
1365 if (!TryBorderShorthand(aString
, borderPropertiesSet
,
1366 borderTopWidth
, borderTopStyle
, borderTopColor
,
1367 borderBottomWidth
, borderBottomStyle
, borderBottomColor
,
1368 borderLeftWidth
, borderLeftStyle
, borderLeftColor
,
1369 borderRightWidth
, borderRightStyle
, borderRightColor
)) {
1370 PRUint32 borderPropertiesToSet
= 0;
1371 if ((borderPropertiesSet
& B_BORDER_STYLE
) != B_BORDER_STYLE
||
1372 !TryFourSidesShorthand(aString
, eCSSProperty_border_style
,
1373 borderTopStyle
, borderBottomStyle
,
1374 borderLeftStyle
, borderRightStyle
,
1376 borderPropertiesToSet
|= B_BORDER_STYLE
;
1378 if ((borderPropertiesSet
& B_BORDER_COLOR
) != B_BORDER_COLOR
||
1379 !TryFourSidesShorthand(aString
, eCSSProperty_border_color
,
1380 borderTopColor
, borderBottomColor
,
1381 borderLeftColor
, borderRightColor
,
1383 borderPropertiesToSet
|= B_BORDER_COLOR
;
1385 if ((borderPropertiesSet
& B_BORDER_WIDTH
) != B_BORDER_WIDTH
||
1386 !TryFourSidesShorthand(aString
, eCSSProperty_border_width
,
1387 borderTopWidth
, borderBottomWidth
,
1388 borderLeftWidth
, borderRightWidth
,
1390 borderPropertiesToSet
|= B_BORDER_WIDTH
;
1392 borderPropertiesToSet
&= borderPropertiesSet
;
1393 if (borderPropertiesToSet
) {
1394 if ((borderPropertiesSet
& B_BORDER_TOP
) != B_BORDER_TOP
||
1395 !TryBorderSideShorthand(aString
, eCSSProperty_border_top
,
1396 borderTopWidth
, borderTopStyle
, borderTopColor
)) {
1397 finalBorderPropertiesToSet
|= B_BORDER_TOP
;
1399 if ((borderPropertiesSet
& B_BORDER_LEFT
) != B_BORDER_LEFT
||
1400 !TryBorderSideShorthand(aString
, eCSSProperty_border_left
,
1401 borderLeftWidth
, borderLeftStyle
, borderLeftColor
)) {
1402 finalBorderPropertiesToSet
|= B_BORDER_LEFT
;
1404 if ((borderPropertiesSet
& B_BORDER_RIGHT
) != B_BORDER_RIGHT
||
1405 !TryBorderSideShorthand(aString
, eCSSProperty_border_right
,
1406 borderRightWidth
, borderRightStyle
, borderRightColor
)) {
1407 finalBorderPropertiesToSet
|= B_BORDER_RIGHT
;
1409 if ((borderPropertiesSet
& B_BORDER_BOTTOM
) != B_BORDER_BOTTOM
||
1410 !TryBorderSideShorthand(aString
, eCSSProperty_border_bottom
,
1411 borderBottomWidth
, borderBottomStyle
, borderBottomColor
)) {
1412 finalBorderPropertiesToSet
|= B_BORDER_BOTTOM
;
1414 finalBorderPropertiesToSet
&= borderPropertiesToSet
;
1418 TryFourSidesShorthand(aString
, eCSSProperty_margin
,
1419 marginTop
, marginBottom
,
1420 marginLeft
, marginRight
,
1422 TryFourSidesShorthand(aString
, eCSSProperty_padding
,
1423 paddingTop
, paddingBottom
,
1424 paddingLeft
, paddingRight
,
1426 TryBackgroundShorthand(aString
,
1427 bgColor
, bgImage
, bgRepeat
, bgAttachment
,
1429 TryOverflowShorthand(aString
, overflowX
, overflowY
);
1431 TryMarkerShorthand(aString
, markerEnd
, markerMid
, markerStart
);
1434 if (columnRuleColor
&& columnRuleStyle
&& columnRuleWidth
) {
1435 TryBorderSideShorthand(aString
, eCSSProperty__moz_column_rule
,
1436 columnRuleWidth
, columnRuleStyle
, columnRuleColor
);
1437 columnRuleWidth
= columnRuleStyle
= columnRuleColor
= 0;
1440 // FIXME The order of the declarations should depend on the *-source
1442 if (borderStartWidth
&& borderStartStyle
&& borderStartColor
&&
1443 TryBorderSideShorthand(aString
, eCSSProperty_border_start
,
1444 borderStartWidth
, borderStartStyle
, borderStartColor
))
1445 borderStartWidth
= borderStartStyle
= borderStartColor
= 0;
1446 if (borderEndWidth
&& borderEndStyle
&& borderEndColor
&&
1447 TryBorderSideShorthand(aString
, eCSSProperty_border_end
,
1448 borderEndWidth
, borderEndStyle
, borderEndColor
))
1449 borderEndWidth
= borderEndStyle
= borderEndColor
= 0;
1451 for (index
= 0; index
< count
; index
++) {
1452 nsCSSProperty property
= OrderValueAt(index
);
1455 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_TOP_STYLE
,
1456 eCSSProperty_border_top_style
, borderTopStyle
)
1457 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_LEFT_STYLE
,
1458 eCSSProperty_border_left_style_value
,
1459 eCSSProperty_border_left_style
, borderLeftStyle
)
1460 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_RIGHT_STYLE
,
1461 eCSSProperty_border_right_style_value
,
1462 eCSSProperty_border_right_style
, borderRightStyle
)
1463 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_BOTTOM_STYLE
,
1464 eCSSProperty_border_bottom_style
, borderBottomStyle
)
1465 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_style_value
,
1466 eCSSProperty_border_start_style
, borderStartStyle
)
1467 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_style_value
,
1468 eCSSProperty_border_end_style
, borderEndStyle
)
1470 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_TOP_COLOR
,
1471 eCSSProperty_border_top_color
, borderTopColor
)
1472 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_LEFT_COLOR
,
1473 eCSSProperty_border_left_color_value
,
1474 eCSSProperty_border_left_color
, borderLeftColor
)
1475 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_RIGHT_COLOR
,
1476 eCSSProperty_border_right_color_value
,
1477 eCSSProperty_border_right_color
, borderRightColor
)
1478 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_BOTTOM_COLOR
,
1479 eCSSProperty_border_bottom_color
, borderBottomColor
)
1480 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_color_value
,
1481 eCSSProperty_border_start_color
, borderStartColor
)
1482 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_color_value
,
1483 eCSSProperty_border_end_color
, borderEndColor
)
1485 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_TOP_WIDTH
,
1486 eCSSProperty_border_top_width
, borderTopWidth
)
1487 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_LEFT_WIDTH
,
1488 eCSSProperty_border_left_width_value
,
1489 eCSSProperty_border_left_width
, borderLeftWidth
)
1490 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet
& B_BORDER_RIGHT_WIDTH
,
1491 eCSSProperty_border_right_width_value
,
1492 eCSSProperty_border_right_width
, borderRightWidth
)
1493 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet
& B_BORDER_BOTTOM_WIDTH
,
1494 eCSSProperty_border_bottom_width
, borderBottomWidth
)
1495 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_width_value
,
1496 eCSSProperty_border_start_width
, borderStartWidth
)
1497 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_width_value
,
1498 eCSSProperty_border_end_width
, borderEndWidth
)
1500 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_top
, marginTop
)
1501 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_bottom
, marginBottom
)
1502 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_left_value
,
1503 eCSSProperty_margin_left
, marginLeft
)
1504 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_right_value
,
1505 eCSSProperty_margin_right
, marginRight
)
1507 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_top
, paddingTop
)
1508 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_bottom
, paddingBottom
)
1509 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_left_value
,
1510 eCSSProperty_padding_left
, paddingLeft
)
1511 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_right_value
,
1512 eCSSProperty_padding_right
, paddingRight
)
1514 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_color
, bgColor
)
1515 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_image
, bgImage
)
1516 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_repeat
, bgRepeat
)
1517 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_attachment
, bgAttachment
)
1518 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_position
, bgPosition
)
1520 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_x
, overflowX
)
1521 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_y
, overflowY
)
1524 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_end
, markerEnd
)
1525 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_mid
, markerMid
)
1526 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_start
, markerStart
)
1529 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_width
, columnRuleWidth
)
1530 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_style
, columnRuleStyle
)
1531 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_color
, columnRuleColor
)
1533 case eCSSProperty_margin_left_ltr_source
:
1534 case eCSSProperty_margin_left_rtl_source
:
1535 case eCSSProperty_margin_right_ltr_source
:
1536 case eCSSProperty_margin_right_rtl_source
:
1537 case eCSSProperty_padding_left_ltr_source
:
1538 case eCSSProperty_padding_left_rtl_source
:
1539 case eCSSProperty_padding_right_ltr_source
:
1540 case eCSSProperty_padding_right_rtl_source
:
1541 case eCSSProperty_border_left_color_ltr_source
:
1542 case eCSSProperty_border_left_color_rtl_source
:
1543 case eCSSProperty_border_left_style_ltr_source
:
1544 case eCSSProperty_border_left_style_rtl_source
:
1545 case eCSSProperty_border_left_width_ltr_source
:
1546 case eCSSProperty_border_left_width_rtl_source
:
1547 case eCSSProperty_border_right_color_ltr_source
:
1548 case eCSSProperty_border_right_color_rtl_source
:
1549 case eCSSProperty_border_right_style_ltr_source
:
1550 case eCSSProperty_border_right_style_rtl_source
:
1551 case eCSSProperty_border_right_width_ltr_source
:
1552 case eCSSProperty_border_right_width_rtl_source
:
1555 case eCSSProperty_margin_start_value
:
1556 AppendPropertyAndValueToString(property
, eCSSProperty_margin_start
,
1559 case eCSSProperty_margin_end_value
:
1560 AppendPropertyAndValueToString(property
, eCSSProperty_margin_end
,
1563 case eCSSProperty_padding_start_value
:
1564 AppendPropertyAndValueToString(property
, eCSSProperty_padding_start
,
1567 case eCSSProperty_padding_end_value
:
1568 AppendPropertyAndValueToString(property
, eCSSProperty_padding_end
,
1573 if (0 <= property
) {
1574 AppendPropertyAndValueToString(property
, aString
);
1579 if (! aString
.IsEmpty()) {
1580 // if the string is not empty, we have a trailing whitespace we should remove
1581 aString
.Truncate(aString
.Length() - 1);
1587 void nsCSSDeclaration::List(FILE* out
, PRInt32 aIndent
) const
1589 for (PRInt32 index
= aIndent
; --index
>= 0; ) fputs(" ", out
);
1594 fputs(NS_ConvertUTF16toUTF8(s
).get(), out
);
1600 nsCSSDeclaration::GetNthProperty(PRUint32 aIndex
, nsAString
& aReturn
) const
1603 if (aIndex
< mOrder
.Length()) {
1604 nsCSSProperty property
= OrderValueAt(aIndex
);
1605 if (0 <= property
) {
1606 AppendASCIItoUTF16(nsCSSProps::GetStringValue(property
), aReturn
);
1614 nsCSSDeclaration::Clone() const
1616 return new nsCSSDeclaration(*this);
1620 nsCSSDeclaration::InitializeEmpty()
1622 NS_ASSERTION(!mData
&& !mImportantData
, "already initialized");
1623 mData
= nsCSSCompressedDataBlock::CreateEmptyBlock();
1624 return mData
!= nsnull
;