Bug 458861. Validate TrueType headers before activating downloaded font. r=roc, sr...
[wine-gecko.git] / layout / style / nsCSSDeclaration.cpp
blob1fa34fbb42cf0ff6970fda198c0459c21c0643e1
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
13 * License.
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.
22 * Contributor(s):
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
42 * stylesheet
45 #include "nscore.h"
46 #include "prlog.h"
47 #include "nsCSSDeclaration.h"
48 #include "nsString.h"
49 #include "nsIAtom.h"
50 #include "nsUnicharUtils.h"
51 #include "nsReadableUtils.h"
52 #include "nsCRT.h"
53 #include "nsCSSProps.h"
54 #include "nsFont.h"
55 #include "nsReadableUtils.h"
56 #include "nsStyleUtil.h"
58 #include "nsStyleConsts.h"
60 #include "nsCOMPtr.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()
87 : mData(nsnull),
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()
101 : nsnull)
103 MOZ_COUNT_CTOR(nsCSSDeclaration);
106 nsCSSDeclaration::~nsCSSDeclaration(void)
108 if (mData) {
109 mData->Destroy();
111 if (mImportantData) {
112 mImportantData->Destroy();
115 MOZ_COUNT_DTOR(nsCSSDeclaration);
118 nsresult
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);
127 } else {
128 mOrder.RemoveElement(aProperty);
129 mOrder.AppendElement(aProperty);
131 return NS_OK;
134 nsresult
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);
146 } else {
147 data.ClearProperty(aProperty);
148 mOrder.RemoveElement(aProperty);
151 data.Compress(&mData, &mImportantData);
152 return NS_OK;
155 nsresult
156 nsCSSDeclaration::AppendComment(const nsAString& aComment)
158 return /* NS_ERROR_NOT_IMPLEMENTED, or not any longer that is */ NS_OK;
161 nsresult
162 nsCSSDeclaration::GetValueOrImportantValue(nsCSSProperty aProperty, nsCSSValue& aValue) const
164 aValue.Reset();
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);
176 if (!storage)
177 return NS_OK;
178 aValue = *static_cast<const nsCSSValue*>(storage);
179 return NS_OK;
182 PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const
184 nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
185 ? mImportantData : mData;
186 const void *storage = data->StorageFor(aProperty);
187 if (storage) {
188 switch (nsCSSProps::kTypeTable[aProperty]) {
189 case eCSSType_Value: {
190 const nsCSSValue *val = static_cast<const nsCSSValue*>(storage);
191 AppendCSSValueToString(aProperty, *val, aResult);
192 } break;
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);
204 } else {
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(')'));
216 } break;
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);
232 } break;
233 case eCSSType_ValueList: {
234 const nsCSSValueList* val =
235 *static_cast<nsCSSValueList*const*>(storage);
236 do {
237 AppendCSSValueToString(aProperty, val->mValue, aResult);
238 val = val->mNext;
239 if (val) {
240 if (nsCSSProps::PropHasFlags(aProperty,
241 CSS_PROPERTY_VALUE_LIST_USES_COMMAS))
242 aResult.Append(PRUnichar(','));
243 aResult.Append(PRUnichar(' '));
245 } while (val);
246 } break;
247 case eCSSType_ValuePairList: {
248 const nsCSSValuePairList* item =
249 *static_cast<nsCSSValuePairList*const*>(storage);
250 do {
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);
258 item = item->mNext;
259 if (item) {
260 aResult.Append(PRUnichar(' '));
262 } while (item);
263 } break;
266 return storage != nsnull;
269 /* static */ PRBool
270 nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty,
271 const nsCSSValue& aValue,
272 nsAString& aResult)
274 nsCSSUnit unit = aValue.GetUnit();
276 if (eCSSUnit_Null == unit) {
277 return PR_FALSE;
280 if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) {
281 if (unit == eCSSUnit_Attr) {
282 aResult.AppendLiteral("attr(");
284 nsAutoString buffer;
285 aValue.GetStringValue(buffer);
286 aResult.Append(buffer);
288 else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Counters) {
289 switch (unit) {
290 case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break;
291 case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
292 default: 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) {
300 continue;
302 if (i == 5) {
303 aResult.AppendLiteral(" /");
306 if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
307 if (unit == eCSSUnit_Array)
308 aResult.AppendLiteral(" ");
309 else
310 aResult.AppendLiteral(", ");
312 nsCSSProperty prop =
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)) {
317 mark = PR_TRUE;
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) {
345 nsAutoString tmpStr;
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) {
353 PRInt32 mask;
354 for (mask = NS_STYLE_TEXT_DECORATION_UNDERLINE;
355 mask <= NS_STYLE_TEXT_DECORATION_BLINK;
356 mask <<= 1) {
357 if ((mask & intValue) == mask) {
358 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, mask), aResult);
359 intValue &= ~mask;
360 if (0 != intValue) { // more left
361 aResult.Append(PRUnichar(' '));
366 else {
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);
390 else {
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
398 nsCAutoString str;
399 if (nsCSSProps::GetColorName(aValue.GetIntValue(), str)){
400 AppendASCIItoUTF16(str, aResult);
401 } else {
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");
411 } else {
412 nsAutoString tmpStr;
413 PRUint8 a = NS_GET_A(color);
414 if (a < 255) {
415 tmpStr.AppendLiteral("rgba(");
416 } else {
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);
427 if (a < 255) {
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) {
442 nsAutoString tmpStr;
443 tmpStr.AppendFloat(aValue.GetPercentValue() * 100.0f);
444 aResult.Append(tmpStr);
446 else if (eCSSUnit_Percent < unit) { // length unit
447 nsAutoString tmpStr;
448 tmpStr.AppendFloat(aValue.GetFloatValue());
449 aResult.Append(tmpStr);
452 switch (unit) {
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;
466 case eCSSUnit_Attr:
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_EN: aResult.AppendLiteral("en"); break;
493 case eCSSUnit_XHeight: aResult.AppendLiteral("ex"); break;
494 case eCSSUnit_CapHeight: aResult.AppendLiteral("cap"); break;
495 case eCSSUnit_Char: aResult.AppendLiteral("ch"); break;
497 case eCSSUnit_Pixel: aResult.AppendLiteral("px"); break;
499 case eCSSUnit_Degree: aResult.AppendLiteral("deg"); break;
500 case eCSSUnit_Grad: aResult.AppendLiteral("grad"); break;
501 case eCSSUnit_Radian: aResult.AppendLiteral("rad"); break;
503 case eCSSUnit_Hertz: aResult.AppendLiteral("Hz"); break;
504 case eCSSUnit_Kilohertz: aResult.AppendLiteral("kHz"); break;
506 case eCSSUnit_Seconds: aResult.Append(PRUnichar('s')); break;
507 case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break;
510 return PR_TRUE;
513 nsresult
514 nsCSSDeclaration::GetValue(nsCSSProperty aProperty,
515 nsAString& aValue) const
517 aValue.Truncate(0);
519 // simple properties are easy.
520 if (!nsCSSProps::IsShorthand(aProperty)) {
521 AppendValueToString(aProperty, aValue);
522 return NS_OK;
525 // DOM Level 2 Style says (when describing CSS2Properties, although
526 // not CSSStyleDeclaration.getPropertyValue):
527 // However, if there is no shorthand declaration that could be added
528 // to the ruleset without changing in any way the rules already
529 // declared in the ruleset (i.e., by adding longhand rules that were
530 // previously not declared in the ruleset), then the empty string
531 // should be returned for the shorthand property.
532 // This means we need to check a number of cases:
533 // (1) Since a shorthand sets all sub-properties, if some of its
534 // subproperties were not specified, we must return the empty
535 // string.
536 // (2) Since 'inherit' and 'initial' can only be specified as the
537 // values for entire properties, we need to return the empty
538 // string if some but not all of the subproperties have one of
539 // those values.
540 // (3) Since a single value only makes sense with or without
541 // !important, we return the empty string if some values are
542 // !important and some are not.
543 // Since we're doing this check for 'inherit' and 'initial' up front,
544 // we can also simplify the property serialization code by serializing
545 // those values up front as well.
546 PRUint32 totalCount = 0, importantCount = 0,
547 initialCount = 0, inheritCount = 0;
548 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
549 if (*p == eCSSProperty__x_system_font ||
550 nsCSSProps::PropHasFlags(*p, CSS_PROPERTY_DIRECTIONAL_SOURCE)) {
551 // The system-font subproperty and the *-source properties don't count.
552 continue;
554 ++totalCount;
555 const void *storage = mData->StorageFor(*p);
556 NS_ASSERTION(!storage || !mImportantData || !mImportantData->StorageFor(*p),
557 "can't be in both blocks");
558 if (!storage && mImportantData) {
559 ++importantCount;
560 storage = mImportantData->StorageFor(*p);
562 if (!storage) {
563 // Case (1) above: some subproperties not specified.
564 return NS_OK;
566 nsCSSUnit unit;
567 switch (nsCSSProps::kTypeTable[*p]) {
568 case eCSSType_Value: {
569 const nsCSSValue *val = static_cast<const nsCSSValue*>(storage);
570 unit = val->GetUnit();
571 } break;
572 case eCSSType_Rect: {
573 const nsCSSRect *rect = static_cast<const nsCSSRect*>(storage);
574 unit = rect->mTop.GetUnit();
575 } break;
576 case eCSSType_ValuePair: {
577 const nsCSSValuePair *pair = static_cast<const nsCSSValuePair*>(storage);
578 unit = pair->mXValue.GetUnit();
579 } break;
580 case eCSSType_ValueList: {
581 const nsCSSValueList* item =
582 *static_cast<nsCSSValueList*const*>(storage);
583 if (item) {
584 unit = item->mValue.GetUnit();
585 } else {
586 unit = eCSSUnit_Null;
588 } break;
589 case eCSSType_ValuePairList: {
590 const nsCSSValuePairList* item =
591 *static_cast<nsCSSValuePairList*const*>(storage);
592 if (item) {
593 unit = item->mXValue.GetUnit();
594 } else {
595 unit = eCSSUnit_Null;
597 } break;
599 if (unit == eCSSUnit_Inherit) {
600 ++inheritCount;
601 } else if (unit == eCSSUnit_Initial) {
602 ++initialCount;
605 if (importantCount != 0 && importantCount != totalCount) {
606 // Case (3), no consistent importance.
607 return NS_OK;
609 if (initialCount == totalCount) {
610 // Simplify serialization below by serializing initial up-front.
611 AppendCSSValueToString(eCSSProperty_UNKNOWN, nsCSSValue(eCSSUnit_Initial),
612 aValue);
613 return NS_OK;
615 if (inheritCount == totalCount) {
616 // Simplify serialization below by serializing inherit up-front.
617 AppendCSSValueToString(eCSSProperty_UNKNOWN, nsCSSValue(eCSSUnit_Inherit),
618 aValue);
619 return NS_OK;
621 if (initialCount != 0 || inheritCount != 0) {
622 // Case (2): partially initial or inherit.
623 return NS_OK;
627 // XXX What about checking the consistency of '!important'?
628 // XXX What about checking that we don't serialize inherit,
629 // -moz-initial, or other illegal values?
630 // XXXldb Can we share shorthand logic with ToString?
631 switch (aProperty) {
632 case eCSSProperty_margin:
633 case eCSSProperty_padding:
634 case eCSSProperty_border_color:
635 case eCSSProperty_border_style:
636 case eCSSProperty_border_width: {
637 const nsCSSProperty* subprops =
638 nsCSSProps::SubpropertyEntryFor(aProperty);
639 NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
640 nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
641 nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value &&
642 nsCSSProps::kTypeTable[subprops[3]] == eCSSType_Value,
643 "type mismatch");
644 if (!AppendValueToString(subprops[0], aValue) ||
645 !(aValue.Append(PRUnichar(' ')),
646 AppendValueToString(subprops[1], aValue)) ||
647 !(aValue.Append(PRUnichar(' ')),
648 AppendValueToString(subprops[2], aValue)) ||
649 !(aValue.Append(PRUnichar(' ')),
650 AppendValueToString(subprops[3], aValue))) {
651 aValue.Truncate();
653 break;
655 case eCSSProperty__moz_border_radius:
656 case eCSSProperty__moz_outline_radius: {
657 const nsCSSProperty* subprops =
658 nsCSSProps::SubpropertyEntryFor(aProperty);
659 NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_ValuePair &&
660 nsCSSProps::kTypeTable[subprops[1]] == eCSSType_ValuePair &&
661 nsCSSProps::kTypeTable[subprops[2]] == eCSSType_ValuePair &&
662 nsCSSProps::kTypeTable[subprops[3]] == eCSSType_ValuePair,
663 "type mismatch");
664 nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
665 ? mImportantData : mData;
666 const nsCSSValuePair* vals[4] = {
667 static_cast<const nsCSSValuePair*>(data->StorageFor(subprops[0])),
668 static_cast<const nsCSSValuePair*>(data->StorageFor(subprops[1])),
669 static_cast<const nsCSSValuePair*>(data->StorageFor(subprops[2])),
670 static_cast<const nsCSSValuePair*>(data->StorageFor(subprops[3]))
673 AppendCSSValueToString(aProperty, vals[0]->mXValue, aValue);
674 aValue.Append(PRUnichar(' '));
675 AppendCSSValueToString(aProperty, vals[1]->mXValue, aValue);
676 aValue.Append(PRUnichar(' '));
677 AppendCSSValueToString(aProperty, vals[2]->mXValue, aValue);
678 aValue.Append(PRUnichar(' '));
679 AppendCSSValueToString(aProperty, vals[3]->mXValue, aValue);
681 // For compatibility, only write a slash and the y-values
682 // if they're not identical to the x-values.
683 if (vals[0]->mXValue != vals[0]->mYValue ||
684 vals[1]->mXValue != vals[1]->mYValue ||
685 vals[2]->mXValue != vals[2]->mYValue ||
686 vals[3]->mXValue != vals[3]->mYValue) {
687 aValue.AppendLiteral(" / ");
688 AppendCSSValueToString(aProperty, vals[0]->mYValue, aValue);
689 aValue.Append(PRUnichar(' '));
690 AppendCSSValueToString(aProperty, vals[1]->mYValue, aValue);
691 aValue.Append(PRUnichar(' '));
692 AppendCSSValueToString(aProperty, vals[2]->mYValue, aValue);
693 aValue.Append(PRUnichar(' '));
694 AppendCSSValueToString(aProperty, vals[3]->mYValue, aValue);
696 break;
698 case eCSSProperty_border:
699 // XXX More consistency checking needed before falling through.
700 aProperty = eCSSProperty_border_top;
701 case eCSSProperty_border_top:
702 case eCSSProperty_border_right:
703 case eCSSProperty_border_bottom:
704 case eCSSProperty_border_left:
705 case eCSSProperty_border_start:
706 case eCSSProperty_border_end:
707 case eCSSProperty__moz_column_rule:
708 case eCSSProperty_outline: {
709 const nsCSSProperty* subprops =
710 nsCSSProps::SubpropertyEntryFor(aProperty);
711 NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
712 nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
713 nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value,
714 "type mismatch");
715 if (!AppendValueToString(subprops[0], aValue) ||
716 !(aValue.Append(PRUnichar(' ')),
717 AppendValueToString(subprops[1], aValue)) ||
718 !(aValue.Append(PRUnichar(' ')),
719 AppendValueToString(subprops[2], aValue))) {
720 aValue.Truncate();
722 break;
724 case eCSSProperty_margin_left:
725 case eCSSProperty_margin_right:
726 case eCSSProperty_margin_start:
727 case eCSSProperty_margin_end:
728 case eCSSProperty_padding_left:
729 case eCSSProperty_padding_right:
730 case eCSSProperty_padding_start:
731 case eCSSProperty_padding_end:
732 case eCSSProperty_border_left_color:
733 case eCSSProperty_border_left_style:
734 case eCSSProperty_border_left_width:
735 case eCSSProperty_border_right_color:
736 case eCSSProperty_border_right_style:
737 case eCSSProperty_border_right_width:
738 case eCSSProperty_border_start_color:
739 case eCSSProperty_border_start_style:
740 case eCSSProperty_border_start_width:
741 case eCSSProperty_border_end_color:
742 case eCSSProperty_border_end_style:
743 case eCSSProperty_border_end_width: {
744 const nsCSSProperty* subprops =
745 nsCSSProps::SubpropertyEntryFor(aProperty);
746 NS_ASSERTION(subprops[3] == eCSSProperty_UNKNOWN,
747 "not box property with physical vs. logical cascading");
748 AppendValueToString(subprops[0], aValue);
749 break;
751 case eCSSProperty_background: {
752 PRBool appendedSomething = PR_FALSE;
753 if (AppendValueToString(eCSSProperty_background_color, aValue)) {
754 appendedSomething = PR_TRUE;
755 aValue.Append(PRUnichar(' '));
757 if (AppendValueToString(eCSSProperty_background_image, aValue)) {
758 aValue.Append(PRUnichar(' '));
759 appendedSomething = PR_TRUE;
761 if (AppendValueToString(eCSSProperty_background_repeat, aValue)) {
762 aValue.Append(PRUnichar(' '));
763 appendedSomething = PR_TRUE;
765 if (AppendValueToString(eCSSProperty_background_attachment, aValue)) {
766 aValue.Append(PRUnichar(' '));
767 appendedSomething = PR_TRUE;
769 if (!AppendValueToString(eCSSProperty_background_position, aValue) &&
770 appendedSomething) {
771 NS_ASSERTION(!aValue.IsEmpty() && aValue.Last() == PRUnichar(' '),
772 "We appended a space before!");
773 // We appended an extra space. Let's get rid of it
774 aValue.Truncate(aValue.Length() - 1);
776 break;
778 case eCSSProperty_cue: {
779 if (AppendValueToString(eCSSProperty_cue_before, aValue)) {
780 aValue.Append(PRUnichar(' '));
781 if (!AppendValueToString(eCSSProperty_cue_after, aValue))
782 aValue.Truncate();
784 break;
786 case eCSSProperty_font: {
787 nsCSSValue style, variant, weight, size, lh, family, systemFont;
788 GetValueOrImportantValue(eCSSProperty__x_system_font, systemFont);
789 GetValueOrImportantValue(eCSSProperty_font_style, style);
790 GetValueOrImportantValue(eCSSProperty_font_variant, variant);
791 GetValueOrImportantValue(eCSSProperty_font_weight, weight);
792 GetValueOrImportantValue(eCSSProperty_font_size, size);
793 GetValueOrImportantValue(eCSSProperty_line_height, lh);
794 GetValueOrImportantValue(eCSSProperty_font_family, family);
796 if (systemFont.GetUnit() != eCSSUnit_None &&
797 systemFont.GetUnit() != eCSSUnit_Null) {
798 AppendCSSValueToString(eCSSProperty__x_system_font, systemFont, aValue);
799 } else {
800 if (style.GetUnit() != eCSSUnit_Normal) {
801 AppendCSSValueToString(eCSSProperty_font_style, style, aValue);
802 aValue.Append(PRUnichar(' '));
804 if (variant.GetUnit() != eCSSUnit_Normal) {
805 AppendCSSValueToString(eCSSProperty_font_variant, variant, aValue);
806 aValue.Append(PRUnichar(' '));
808 if (weight.GetUnit() != eCSSUnit_Normal) {
809 AppendCSSValueToString(eCSSProperty_font_weight, weight, aValue);
810 aValue.Append(PRUnichar(' '));
812 AppendCSSValueToString(eCSSProperty_font_size, size, aValue);
813 if (lh.GetUnit() != eCSSUnit_Normal) {
814 aValue.Append(PRUnichar('/'));
815 AppendCSSValueToString(eCSSProperty_line_height, lh, aValue);
817 aValue.Append(PRUnichar(' '));
818 AppendCSSValueToString(eCSSProperty_font_family, family, aValue);
820 break;
822 case eCSSProperty_list_style:
823 if (AppendValueToString(eCSSProperty_list_style_type, aValue))
824 aValue.Append(PRUnichar(' '));
825 if (AppendValueToString(eCSSProperty_list_style_position, aValue))
826 aValue.Append(PRUnichar(' '));
827 AppendValueToString(eCSSProperty_list_style_image, aValue);
828 break;
829 case eCSSProperty_overflow: {
830 nsCSSValue xValue, yValue;
831 GetValueOrImportantValue(eCSSProperty_overflow_x, xValue);
832 GetValueOrImportantValue(eCSSProperty_overflow_y, yValue);
833 if (xValue == yValue)
834 AppendValueToString(eCSSProperty_overflow_x, aValue);
835 break;
837 case eCSSProperty_pause: {
838 if (AppendValueToString(eCSSProperty_pause_before, aValue)) {
839 aValue.Append(PRUnichar(' '));
840 if (!AppendValueToString(eCSSProperty_pause_after, aValue))
841 aValue.Truncate();
843 break;
845 #ifdef MOZ_SVG
846 case eCSSProperty_marker: {
847 nsCSSValue endValue, midValue, startValue;
848 GetValueOrImportantValue(eCSSProperty_marker_end, endValue);
849 GetValueOrImportantValue(eCSSProperty_marker_mid, midValue);
850 GetValueOrImportantValue(eCSSProperty_marker_start, startValue);
851 if (endValue == midValue && midValue == startValue)
852 AppendValueToString(eCSSProperty_marker_end, aValue);
853 break;
855 #endif
856 default:
857 NS_NOTREACHED("no other shorthands");
858 break;
860 return NS_OK;
863 PRBool
864 nsCSSDeclaration::GetValueIsImportant(const nsAString& aProperty) const
866 nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
867 return GetValueIsImportant(propID);
870 PRBool
871 nsCSSDeclaration::GetValueIsImportant(nsCSSProperty aProperty) const
873 if (!mImportantData)
874 return PR_FALSE;
876 // Calling StorageFor is inefficient, but we can assume '!important'
877 // is rare.
879 if (nsCSSProps::IsShorthand(aProperty)) {
880 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
881 if (*p == eCSSProperty__x_system_font) {
882 // The system_font subproperty doesn't count.
883 continue;
885 if (!mImportantData->StorageFor(*p)) {
886 return PR_FALSE;
889 return PR_TRUE;
892 return mImportantData->StorageFor(aProperty) != nsnull;
895 // XXXldb Bug 376075 All callers of AllPropertiesSameImportance also
896 // need to check for 'inherit' and 'initial' values, since you can't
897 // output a mix of either mixed with other values in the same shorthand!
898 PRBool
899 nsCSSDeclaration::AllPropertiesSameImportance(PRInt32 aFirst, PRInt32 aSecond,
900 PRInt32 aThird, PRInt32 aFourth,
901 PRInt32 aFifth,
902 PRBool & aImportance) const
904 aImportance = GetValueIsImportant(OrderValueAt(aFirst-1));
905 if ((aSecond && aImportance != GetValueIsImportant(OrderValueAt(aSecond-1))) ||
906 (aThird && aImportance != GetValueIsImportant(OrderValueAt(aThird-1))) ||
907 (aFourth && aImportance != GetValueIsImportant(OrderValueAt(aFourth-1))) ||
908 (aFifth && aImportance != GetValueIsImportant(OrderValueAt(aFifth-1)))) {
909 return PR_FALSE;
911 return PR_TRUE;
914 PRBool
915 nsCSSDeclaration::AllPropertiesSameValue(PRInt32 aFirst, PRInt32 aSecond,
916 PRInt32 aThird, PRInt32 aFourth) const
918 nsCSSValue firstValue, otherValue;
919 // TryBorderShorthand does the bounds-checking for us; valid values there
920 // are > 0; 0 is a flag for "not set". We here are passed the actual
921 // index, which comes from finding the value in the mOrder property array.
922 // Of course, re-getting the mOrder value here is pretty silly.
923 GetValueOrImportantValue(OrderValueAt(aFirst-1), firstValue);
924 GetValueOrImportantValue(OrderValueAt(aSecond-1), otherValue);
925 if (firstValue != otherValue) {
926 return PR_FALSE;
928 GetValueOrImportantValue(OrderValueAt(aThird-1), otherValue);
929 if (firstValue != otherValue) {
930 return PR_FALSE;
932 GetValueOrImportantValue(OrderValueAt(aFourth-1), otherValue);
933 if (firstValue != otherValue) {
934 return PR_FALSE;
936 return PR_TRUE;
939 /* static */ void
940 nsCSSDeclaration::AppendImportanceToString(PRBool aIsImportant,
941 nsAString& aString)
943 if (aIsImportant) {
944 aString.AppendLiteral(" ! important");
948 void
949 nsCSSDeclaration::AppendPropertyAndValueToString(nsCSSProperty aProperty,
950 nsCSSProperty aPropertyName,
951 nsAString& aResult) const
953 NS_ASSERTION(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
954 "property enum out of range");
955 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aPropertyName), aResult);
956 aResult.AppendLiteral(": ");
957 AppendValueToString(aProperty, aResult);
958 PRBool isImportant = GetValueIsImportant(aProperty);
959 AppendImportanceToString(isImportant, aResult);
960 aResult.AppendLiteral("; ");
963 PRBool
964 nsCSSDeclaration::TryBorderShorthand(nsAString & aString, PRUint32 aPropertiesSet,
965 PRInt32 aBorderTopWidth,
966 PRInt32 aBorderTopStyle,
967 PRInt32 aBorderTopColor,
968 PRInt32 aBorderBottomWidth,
969 PRInt32 aBorderBottomStyle,
970 PRInt32 aBorderBottomColor,
971 PRInt32 aBorderLeftWidth,
972 PRInt32 aBorderLeftStyle,
973 PRInt32 aBorderLeftColor,
974 PRInt32 aBorderRightWidth,
975 PRInt32 aBorderRightStyle,
976 PRInt32 aBorderRightColor) const
978 PRBool border = PR_FALSE, isImportant = PR_FALSE;
979 // 0 means not in the mOrder array; otherwise it's index+1
980 if (B_BORDER == aPropertiesSet
981 && AllPropertiesSameValue(aBorderTopWidth, aBorderBottomWidth,
982 aBorderLeftWidth, aBorderRightWidth)
983 && AllPropertiesSameValue(aBorderTopStyle, aBorderBottomStyle,
984 aBorderLeftStyle, aBorderRightStyle)
985 && AllPropertiesSameValue(aBorderTopColor, aBorderBottomColor,
986 aBorderLeftColor, aBorderRightColor)) {
987 border = PR_TRUE;
989 if (border) {
990 border = PR_FALSE;
991 PRBool isWidthImportant, isStyleImportant, isColorImportant;
992 if (AllPropertiesSameImportance(aBorderTopWidth, aBorderBottomWidth,
993 aBorderLeftWidth, aBorderRightWidth,
995 isWidthImportant) &&
996 AllPropertiesSameImportance(aBorderTopStyle, aBorderBottomStyle,
997 aBorderLeftStyle, aBorderRightStyle,
999 isStyleImportant) &&
1000 AllPropertiesSameImportance(aBorderTopColor, aBorderBottomColor,
1001 aBorderLeftColor, aBorderRightColor,
1003 isColorImportant)) {
1004 if (isWidthImportant == isStyleImportant && isWidthImportant == isColorImportant) {
1005 border = PR_TRUE;
1006 isImportant = isWidthImportant;
1010 if (border) {
1011 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_border), aString);
1012 aString.AppendLiteral(": ");
1014 AppendValueToString(eCSSProperty_border_top_width, aString);
1015 aString.Append(PRUnichar(' '));
1017 AppendValueToString(eCSSProperty_border_top_style, aString);
1018 aString.Append(PRUnichar(' '));
1020 nsAutoString valueString;
1021 AppendValueToString(eCSSProperty_border_top_color, valueString);
1022 if (!valueString.EqualsLiteral("-moz-use-text-color")) {
1023 /* don't output this value, it's proprietary Mozilla and */
1024 /* not intended to be exposed ; we can remove it from the */
1025 /* values of the shorthand since this value represents the */
1026 /* initial value of border-*-color */
1027 aString.Append(valueString);
1029 AppendImportanceToString(isImportant, aString);
1030 aString.AppendLiteral("; ");
1032 return border;
1035 PRBool
1036 nsCSSDeclaration::TryBorderSideShorthand(nsAString & aString,
1037 nsCSSProperty aShorthand,
1038 PRInt32 aBorderWidth,
1039 PRInt32 aBorderStyle,
1040 PRInt32 aBorderColor) const
1042 PRBool isImportant;
1043 if (AllPropertiesSameImportance(aBorderWidth, aBorderStyle, aBorderColor,
1044 0, 0,
1045 isImportant)) {
1046 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand), aString);
1047 aString.AppendLiteral(": ");
1049 AppendValueToString(OrderValueAt(aBorderWidth-1), aString);
1051 aString.Append(PRUnichar(' '));
1052 AppendValueToString(OrderValueAt(aBorderStyle-1), aString);
1054 nsAutoString valueString;
1055 AppendValueToString(OrderValueAt(aBorderColor-1), valueString);
1056 if (!valueString.EqualsLiteral("-moz-use-text-color")) {
1057 aString.AppendLiteral(" ");
1058 aString.Append(valueString);
1060 AppendImportanceToString(isImportant, aString);
1061 aString.AppendLiteral("; ");
1062 return PR_TRUE;
1064 return PR_FALSE;
1067 PRBool
1068 nsCSSDeclaration::TryFourSidesShorthand(nsAString & aString,
1069 nsCSSProperty aShorthand,
1070 PRInt32 & aTop,
1071 PRInt32 & aBottom,
1072 PRInt32 & aLeft,
1073 PRInt32 & aRight,
1074 PRBool aClearIndexes) const
1076 // 0 means not in the mOrder array; otherwise it's index+1
1077 PRBool isImportant;
1078 if (aTop && aBottom && aLeft && aRight &&
1079 AllPropertiesSameImportance(aTop, aBottom, aLeft, aRight,
1081 isImportant)) {
1082 // all 4 properties are set, we can output a shorthand
1083 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand), aString);
1084 aString.AppendLiteral(": ");
1085 nsCSSValue topValue, bottomValue, leftValue, rightValue;
1086 nsCSSProperty topProp = OrderValueAt(aTop-1);
1087 nsCSSProperty bottomProp = OrderValueAt(aBottom-1);
1088 nsCSSProperty leftProp = OrderValueAt(aLeft-1);
1089 nsCSSProperty rightProp = OrderValueAt(aRight-1);
1090 GetValueOrImportantValue(topProp, topValue);
1091 GetValueOrImportantValue(bottomProp, bottomValue);
1092 GetValueOrImportantValue(leftProp, leftValue);
1093 GetValueOrImportantValue(rightProp, rightValue);
1094 AppendCSSValueToString(topProp, topValue, aString);
1095 if (topValue != rightValue || topValue != leftValue || topValue != bottomValue) {
1096 aString.Append(PRUnichar(' '));
1097 AppendCSSValueToString(rightProp, rightValue, aString);
1098 if (topValue != bottomValue || rightValue != leftValue) {
1099 aString.Append(PRUnichar(' '));
1100 AppendCSSValueToString(bottomProp, bottomValue, aString);
1101 if (rightValue != leftValue) {
1102 aString.Append(PRUnichar(' '));
1103 AppendCSSValueToString(leftProp, leftValue, aString);
1107 if (aClearIndexes) {
1108 aTop = 0; aBottom = 0; aLeft = 0; aRight = 0;
1110 AppendImportanceToString(isImportant, aString);
1111 aString.AppendLiteral("; ");
1112 return PR_TRUE;
1114 return PR_FALSE;
1117 void
1118 nsCSSDeclaration::TryBackgroundShorthand(nsAString & aString,
1119 PRInt32 & aBgColor,
1120 PRInt32 & aBgImage,
1121 PRInt32 & aBgRepeat,
1122 PRInt32 & aBgAttachment,
1123 PRInt32 & aBgPosition) const
1125 // 0 means not in the mOrder array; otherwise it's index+1
1126 // check if we have at least two properties set; otherwise, no need to
1127 // use a shorthand
1128 PRBool isImportant;
1129 if (aBgColor && aBgImage && aBgRepeat && aBgAttachment && aBgPosition &&
1130 AllPropertiesSameImportance(aBgColor, aBgImage, aBgRepeat, aBgAttachment,
1131 aBgPosition, isImportant)) {
1132 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_background), aString);
1133 aString.AppendLiteral(": ");
1135 AppendValueToString(eCSSProperty_background_color, aString);
1136 aBgColor = 0;
1138 aString.Append(PRUnichar(' '));
1139 AppendValueToString(eCSSProperty_background_image, aString);
1140 aBgImage = 0;
1142 aString.Append(PRUnichar(' '));
1143 AppendValueToString(eCSSProperty_background_repeat, aString);
1144 aBgRepeat = 0;
1146 aString.Append(PRUnichar(' '));
1147 AppendValueToString(eCSSProperty_background_attachment, aString);
1148 aBgAttachment = 0;
1150 aString.Append(PRUnichar(' '));
1151 AppendValueToString(eCSSProperty_background_position, aString);
1152 aBgPosition = 0;
1154 AppendImportanceToString(isImportant, aString);
1155 aString.AppendLiteral("; ");
1159 void
1160 nsCSSDeclaration::TryOverflowShorthand(nsAString & aString,
1161 PRInt32 & aOverflowX,
1162 PRInt32 & aOverflowY) const
1164 PRBool isImportant;
1165 if (aOverflowX && aOverflowY &&
1166 AllPropertiesSameImportance(aOverflowX, aOverflowY,
1167 0, 0, 0, isImportant)) {
1168 nsCSSValue xValue, yValue;
1169 GetValueOrImportantValue(eCSSProperty_overflow_x, xValue);
1170 GetValueOrImportantValue(eCSSProperty_overflow_y, yValue);
1171 if (xValue == yValue) {
1172 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_overflow),
1173 aString);
1174 aString.AppendLiteral(": ");
1176 AppendCSSValueToString(eCSSProperty_overflow_x, xValue, aString);
1177 AppendImportanceToString(isImportant, aString);
1178 aString.AppendLiteral("; ");
1179 aOverflowX = aOverflowY = 0;
1184 #ifdef MOZ_SVG
1185 void
1186 nsCSSDeclaration::TryMarkerShorthand(nsAString & aString,
1187 PRInt32 & aMarkerEnd,
1188 PRInt32 & aMarkerMid,
1189 PRInt32 & aMarkerStart) const
1191 PRBool isImportant;
1192 if (aMarkerEnd && aMarkerMid && aMarkerEnd &&
1193 AllPropertiesSameImportance(aMarkerEnd, aMarkerMid, aMarkerStart,
1194 0, 0, isImportant)) {
1195 nsCSSValue endValue, midValue, startValue;
1196 GetValueOrImportantValue(eCSSProperty_marker_end, endValue);
1197 GetValueOrImportantValue(eCSSProperty_marker_mid, midValue);
1198 GetValueOrImportantValue(eCSSProperty_marker_start, startValue);
1199 if (endValue == midValue && midValue == startValue) {
1200 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_marker),
1201 aString);
1202 aString.AppendLiteral(": ");
1204 AppendCSSValueToString(eCSSProperty_marker_end, endValue, aString);
1205 AppendImportanceToString(isImportant, aString);
1206 aString.AppendLiteral("; ");
1207 aMarkerEnd = aMarkerMid = aMarkerStart = 0;
1211 #endif
1213 #define NS_CASE_OUTPUT_PROPERTY_VALUE(_prop, _index) \
1214 case _prop: \
1215 if (_index) { \
1216 AppendPropertyAndValueToString(property, aString); \
1217 _index = 0; \
1219 break;
1221 #define NS_CASE_OUTPUT_PROPERTY_VALUE_AS(_prop, _propas, _index) \
1222 case _prop: \
1223 if (_index) { \
1224 AppendPropertyAndValueToString(property, _propas, aString); \
1225 _index = 0; \
1227 break;
1229 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(_condition, _prop, _index) \
1230 case _prop: \
1231 if ((_condition) && _index) { \
1232 AppendPropertyAndValueToString(property, aString); \
1233 _index = 0; \
1235 break;
1237 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(_condition, _prop, _propas, _index) \
1238 case _prop: \
1239 if ((_condition) && _index) { \
1240 AppendPropertyAndValueToString(property, _propas, aString); \
1241 _index = 0; \
1243 break;
1245 void nsCSSDeclaration::PropertyIsSet(PRInt32 & aPropertyIndex, PRInt32 aIndex, PRUint32 & aSet, PRUint32 aValue) const
1247 aPropertyIndex = aIndex + 1;
1248 aSet |= aValue;
1251 nsresult
1252 nsCSSDeclaration::ToString(nsAString& aString) const
1254 PRInt32 count = mOrder.Length();
1255 PRInt32 index;
1256 // 0 means not in the mOrder array; otherwise it's index+1
1257 PRInt32 borderTopWidth = 0, borderTopStyle = 0, borderTopColor = 0;
1258 PRInt32 borderBottomWidth = 0, borderBottomStyle = 0, borderBottomColor = 0;
1259 PRInt32 borderLeftWidth = 0, borderLeftStyle = 0, borderLeftColor = 0;
1260 PRInt32 borderRightWidth = 0, borderRightStyle = 0, borderRightColor = 0;
1261 PRInt32 borderStartWidth = 0, borderStartStyle = 0, borderStartColor = 0;
1262 PRInt32 borderEndWidth = 0, borderEndStyle = 0, borderEndColor = 0;
1263 PRInt32 marginTop = 0, marginBottom = 0, marginLeft = 0, marginRight = 0;
1264 PRInt32 paddingTop = 0, paddingBottom = 0, paddingLeft = 0, paddingRight = 0;
1265 PRInt32 bgColor = 0, bgImage = 0, bgRepeat = 0, bgAttachment = 0;
1266 PRInt32 bgPosition = 0;
1267 PRInt32 overflowX = 0, overflowY = 0;
1268 PRInt32 columnRuleWidth = 0, columnRuleStyle = 0, columnRuleColor = 0;
1269 PRUint32 borderPropertiesSet = 0, finalBorderPropertiesToSet = 0;
1270 #ifdef MOZ_SVG
1271 PRInt32 markerEnd = 0, markerMid = 0, markerStart = 0;
1272 #endif
1274 for (index = 0; index < count; index++) {
1275 nsCSSProperty property = OrderValueAt(index);
1276 switch (property) {
1277 case eCSSProperty_border_top_width:
1278 PropertyIsSet(borderTopWidth, index, borderPropertiesSet, B_BORDER_TOP_WIDTH);
1279 break;
1280 case eCSSProperty_border_bottom_width:
1281 PropertyIsSet(borderBottomWidth, index, borderPropertiesSet, B_BORDER_BOTTOM_WIDTH);
1282 break;
1283 case eCSSProperty_border_left_width_value:
1284 PropertyIsSet(borderLeftWidth, index, borderPropertiesSet, B_BORDER_LEFT_WIDTH);
1285 break;
1286 case eCSSProperty_border_right_width_value:
1287 PropertyIsSet(borderRightWidth, index, borderPropertiesSet, B_BORDER_RIGHT_WIDTH);
1288 break;
1289 case eCSSProperty_border_start_width_value:
1290 borderStartWidth = index+1;
1291 break;
1292 case eCSSProperty_border_end_width_value:
1293 borderEndWidth = index+1;
1294 break;
1296 case eCSSProperty_border_top_style:
1297 PropertyIsSet(borderTopStyle, index, borderPropertiesSet, B_BORDER_TOP_STYLE);
1298 break;
1299 case eCSSProperty_border_bottom_style:
1300 PropertyIsSet(borderBottomStyle, index, borderPropertiesSet, B_BORDER_BOTTOM_STYLE);
1301 break;
1302 case eCSSProperty_border_left_style_value:
1303 PropertyIsSet(borderLeftStyle, index, borderPropertiesSet, B_BORDER_LEFT_STYLE);
1304 break;
1305 case eCSSProperty_border_right_style_value:
1306 PropertyIsSet(borderRightStyle, index, borderPropertiesSet, B_BORDER_RIGHT_STYLE);
1307 break;
1308 case eCSSProperty_border_start_style_value:
1309 borderStartStyle = index+1;
1310 break;
1311 case eCSSProperty_border_end_style_value:
1312 borderEndStyle = index+1;
1313 break;
1315 case eCSSProperty_border_top_color:
1316 PropertyIsSet(borderTopColor, index, borderPropertiesSet, B_BORDER_TOP_COLOR);
1317 break;
1318 case eCSSProperty_border_bottom_color:
1319 PropertyIsSet(borderBottomColor, index, borderPropertiesSet, B_BORDER_BOTTOM_COLOR);
1320 break;
1321 case eCSSProperty_border_left_color_value:
1322 PropertyIsSet(borderLeftColor, index, borderPropertiesSet, B_BORDER_LEFT_COLOR);
1323 break;
1324 case eCSSProperty_border_right_color_value:
1325 PropertyIsSet(borderRightColor, index, borderPropertiesSet, B_BORDER_RIGHT_COLOR);
1326 break;
1327 case eCSSProperty_border_start_color_value:
1328 borderStartColor = index+1;
1329 break;
1330 case eCSSProperty_border_end_color_value:
1331 borderEndColor = index+1;
1332 break;
1334 case eCSSProperty_margin_top: marginTop = index+1; break;
1335 case eCSSProperty_margin_bottom: marginBottom = index+1; break;
1336 case eCSSProperty_margin_left_value: marginLeft = index+1; break;
1337 case eCSSProperty_margin_right_value: marginRight = index+1; break;
1339 case eCSSProperty_padding_top: paddingTop = index+1; break;
1340 case eCSSProperty_padding_bottom: paddingBottom = index+1; break;
1341 case eCSSProperty_padding_left_value: paddingLeft = index+1; break;
1342 case eCSSProperty_padding_right_value: paddingRight = index+1; break;
1344 case eCSSProperty_background_color: bgColor = index+1; break;
1345 case eCSSProperty_background_image: bgImage = index+1; break;
1346 case eCSSProperty_background_repeat: bgRepeat = index+1; break;
1347 case eCSSProperty_background_attachment: bgAttachment = index+1; break;
1348 case eCSSProperty_background_position: bgPosition = index+1; break;
1350 case eCSSProperty_overflow_x: overflowX = index+1; break;
1351 case eCSSProperty_overflow_y: overflowY = index+1; break;
1353 case eCSSProperty__moz_column_rule_width: columnRuleWidth = index+1; break;
1354 case eCSSProperty__moz_column_rule_style: columnRuleStyle = index+1; break;
1355 case eCSSProperty__moz_column_rule_color: columnRuleColor = index+1; break;
1357 #ifdef MOZ_SVG
1358 case eCSSProperty_marker_end: markerEnd = index+1; break;
1359 case eCSSProperty_marker_mid: markerMid = index+1; break;
1360 case eCSSProperty_marker_start: markerStart = index+1; break;
1361 #endif
1363 default: break;
1367 if (!TryBorderShorthand(aString, borderPropertiesSet,
1368 borderTopWidth, borderTopStyle, borderTopColor,
1369 borderBottomWidth, borderBottomStyle, borderBottomColor,
1370 borderLeftWidth, borderLeftStyle, borderLeftColor,
1371 borderRightWidth, borderRightStyle, borderRightColor)) {
1372 PRUint32 borderPropertiesToSet = 0;
1373 if ((borderPropertiesSet & B_BORDER_STYLE) != B_BORDER_STYLE ||
1374 !TryFourSidesShorthand(aString, eCSSProperty_border_style,
1375 borderTopStyle, borderBottomStyle,
1376 borderLeftStyle, borderRightStyle,
1377 PR_FALSE)) {
1378 borderPropertiesToSet |= B_BORDER_STYLE;
1380 if ((borderPropertiesSet & B_BORDER_COLOR) != B_BORDER_COLOR ||
1381 !TryFourSidesShorthand(aString, eCSSProperty_border_color,
1382 borderTopColor, borderBottomColor,
1383 borderLeftColor, borderRightColor,
1384 PR_FALSE)) {
1385 borderPropertiesToSet |= B_BORDER_COLOR;
1387 if ((borderPropertiesSet & B_BORDER_WIDTH) != B_BORDER_WIDTH ||
1388 !TryFourSidesShorthand(aString, eCSSProperty_border_width,
1389 borderTopWidth, borderBottomWidth,
1390 borderLeftWidth, borderRightWidth,
1391 PR_FALSE)) {
1392 borderPropertiesToSet |= B_BORDER_WIDTH;
1394 borderPropertiesToSet &= borderPropertiesSet;
1395 if (borderPropertiesToSet) {
1396 if ((borderPropertiesSet & B_BORDER_TOP) != B_BORDER_TOP ||
1397 !TryBorderSideShorthand(aString, eCSSProperty_border_top,
1398 borderTopWidth, borderTopStyle, borderTopColor)) {
1399 finalBorderPropertiesToSet |= B_BORDER_TOP;
1401 if ((borderPropertiesSet & B_BORDER_LEFT) != B_BORDER_LEFT ||
1402 !TryBorderSideShorthand(aString, eCSSProperty_border_left,
1403 borderLeftWidth, borderLeftStyle, borderLeftColor)) {
1404 finalBorderPropertiesToSet |= B_BORDER_LEFT;
1406 if ((borderPropertiesSet & B_BORDER_RIGHT) != B_BORDER_RIGHT ||
1407 !TryBorderSideShorthand(aString, eCSSProperty_border_right,
1408 borderRightWidth, borderRightStyle, borderRightColor)) {
1409 finalBorderPropertiesToSet |= B_BORDER_RIGHT;
1411 if ((borderPropertiesSet & B_BORDER_BOTTOM) != B_BORDER_BOTTOM ||
1412 !TryBorderSideShorthand(aString, eCSSProperty_border_bottom,
1413 borderBottomWidth, borderBottomStyle, borderBottomColor)) {
1414 finalBorderPropertiesToSet |= B_BORDER_BOTTOM;
1416 finalBorderPropertiesToSet &= borderPropertiesToSet;
1420 TryFourSidesShorthand(aString, eCSSProperty_margin,
1421 marginTop, marginBottom,
1422 marginLeft, marginRight,
1423 PR_TRUE);
1424 TryFourSidesShorthand(aString, eCSSProperty_padding,
1425 paddingTop, paddingBottom,
1426 paddingLeft, paddingRight,
1427 PR_TRUE);
1428 TryBackgroundShorthand(aString,
1429 bgColor, bgImage, bgRepeat, bgAttachment,
1430 bgPosition);
1431 TryOverflowShorthand(aString, overflowX, overflowY);
1432 #ifdef MOZ_SVG
1433 TryMarkerShorthand(aString, markerEnd, markerMid, markerStart);
1434 #endif
1436 if (columnRuleColor && columnRuleStyle && columnRuleWidth) {
1437 TryBorderSideShorthand(aString, eCSSProperty__moz_column_rule,
1438 columnRuleWidth, columnRuleStyle, columnRuleColor);
1439 columnRuleWidth = columnRuleStyle = columnRuleColor = 0;
1442 // FIXME The order of the declarations should depend on the *-source
1443 // properties.
1444 if (borderStartWidth && borderStartStyle && borderStartColor &&
1445 TryBorderSideShorthand(aString, eCSSProperty_border_start,
1446 borderStartWidth, borderStartStyle, borderStartColor))
1447 borderStartWidth = borderStartStyle = borderStartColor = 0;
1448 if (borderEndWidth && borderEndStyle && borderEndColor &&
1449 TryBorderSideShorthand(aString, eCSSProperty_border_end,
1450 borderEndWidth, borderEndStyle, borderEndColor))
1451 borderEndWidth = borderEndStyle = borderEndColor = 0;
1453 for (index = 0; index < count; index++) {
1454 nsCSSProperty property = OrderValueAt(index);
1455 switch (property) {
1457 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_STYLE,
1458 eCSSProperty_border_top_style, borderTopStyle)
1459 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_STYLE,
1460 eCSSProperty_border_left_style_value,
1461 eCSSProperty_border_left_style, borderLeftStyle)
1462 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_STYLE,
1463 eCSSProperty_border_right_style_value,
1464 eCSSProperty_border_right_style, borderRightStyle)
1465 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_STYLE,
1466 eCSSProperty_border_bottom_style, borderBottomStyle)
1467 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_style_value,
1468 eCSSProperty_border_start_style, borderStartStyle)
1469 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_style_value,
1470 eCSSProperty_border_end_style, borderEndStyle)
1472 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_COLOR,
1473 eCSSProperty_border_top_color, borderTopColor)
1474 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_COLOR,
1475 eCSSProperty_border_left_color_value,
1476 eCSSProperty_border_left_color, borderLeftColor)
1477 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_COLOR,
1478 eCSSProperty_border_right_color_value,
1479 eCSSProperty_border_right_color, borderRightColor)
1480 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_COLOR,
1481 eCSSProperty_border_bottom_color, borderBottomColor)
1482 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_color_value,
1483 eCSSProperty_border_start_color, borderStartColor)
1484 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_color_value,
1485 eCSSProperty_border_end_color, borderEndColor)
1487 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_WIDTH,
1488 eCSSProperty_border_top_width, borderTopWidth)
1489 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_WIDTH,
1490 eCSSProperty_border_left_width_value,
1491 eCSSProperty_border_left_width, borderLeftWidth)
1492 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_WIDTH,
1493 eCSSProperty_border_right_width_value,
1494 eCSSProperty_border_right_width, borderRightWidth)
1495 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_WIDTH,
1496 eCSSProperty_border_bottom_width, borderBottomWidth)
1497 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_width_value,
1498 eCSSProperty_border_start_width, borderStartWidth)
1499 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_width_value,
1500 eCSSProperty_border_end_width, borderEndWidth)
1502 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_top, marginTop)
1503 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_bottom, marginBottom)
1504 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_left_value,
1505 eCSSProperty_margin_left, marginLeft)
1506 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_right_value,
1507 eCSSProperty_margin_right, marginRight)
1509 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_top, paddingTop)
1510 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_bottom, paddingBottom)
1511 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_left_value,
1512 eCSSProperty_padding_left, paddingLeft)
1513 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_right_value,
1514 eCSSProperty_padding_right, paddingRight)
1516 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_color, bgColor)
1517 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_image, bgImage)
1518 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_repeat, bgRepeat)
1519 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_attachment, bgAttachment)
1520 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_position, bgPosition)
1522 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_x, overflowX)
1523 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_y, overflowY)
1525 #ifdef MOZ_SVG
1526 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_end, markerEnd)
1527 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_mid, markerMid)
1528 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_start, markerStart)
1529 #endif
1531 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_width, columnRuleWidth)
1532 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_style, columnRuleStyle)
1533 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_color, columnRuleColor)
1535 case eCSSProperty_margin_left_ltr_source:
1536 case eCSSProperty_margin_left_rtl_source:
1537 case eCSSProperty_margin_right_ltr_source:
1538 case eCSSProperty_margin_right_rtl_source:
1539 case eCSSProperty_padding_left_ltr_source:
1540 case eCSSProperty_padding_left_rtl_source:
1541 case eCSSProperty_padding_right_ltr_source:
1542 case eCSSProperty_padding_right_rtl_source:
1543 case eCSSProperty_border_left_color_ltr_source:
1544 case eCSSProperty_border_left_color_rtl_source:
1545 case eCSSProperty_border_left_style_ltr_source:
1546 case eCSSProperty_border_left_style_rtl_source:
1547 case eCSSProperty_border_left_width_ltr_source:
1548 case eCSSProperty_border_left_width_rtl_source:
1549 case eCSSProperty_border_right_color_ltr_source:
1550 case eCSSProperty_border_right_color_rtl_source:
1551 case eCSSProperty_border_right_style_ltr_source:
1552 case eCSSProperty_border_right_style_rtl_source:
1553 case eCSSProperty_border_right_width_ltr_source:
1554 case eCSSProperty_border_right_width_rtl_source:
1555 break;
1557 case eCSSProperty_margin_start_value:
1558 AppendPropertyAndValueToString(property, eCSSProperty_margin_start,
1559 aString);
1560 break;
1561 case eCSSProperty_margin_end_value:
1562 AppendPropertyAndValueToString(property, eCSSProperty_margin_end,
1563 aString);
1564 break;
1565 case eCSSProperty_padding_start_value:
1566 AppendPropertyAndValueToString(property, eCSSProperty_padding_start,
1567 aString);
1568 break;
1569 case eCSSProperty_padding_end_value:
1570 AppendPropertyAndValueToString(property, eCSSProperty_padding_end,
1571 aString);
1572 break;
1574 default:
1575 if (0 <= property) {
1576 AppendPropertyAndValueToString(property, aString);
1578 break;
1581 if (! aString.IsEmpty()) {
1582 // if the string is not empty, we have a trailing whitespace we should remove
1583 aString.Truncate(aString.Length() - 1);
1585 return NS_OK;
1588 #ifdef DEBUG
1589 void nsCSSDeclaration::List(FILE* out, PRInt32 aIndent) const
1591 for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
1593 fputs("{ ", out);
1594 nsAutoString s;
1595 ToString(s);
1596 fputs(NS_ConvertUTF16toUTF8(s).get(), out);
1597 fputs("}", out);
1599 #endif
1601 nsresult
1602 nsCSSDeclaration::GetNthProperty(PRUint32 aIndex, nsAString& aReturn) const
1604 aReturn.Truncate();
1605 if (aIndex < mOrder.Length()) {
1606 nsCSSProperty property = OrderValueAt(aIndex);
1607 if (0 <= property) {
1608 AppendASCIItoUTF16(nsCSSProps::GetStringValue(property), aReturn);
1612 return NS_OK;
1615 nsCSSDeclaration*
1616 nsCSSDeclaration::Clone() const
1618 return new nsCSSDeclaration(*this);
1621 PRBool
1622 nsCSSDeclaration::InitializeEmpty()
1624 NS_ASSERTION(!mData && !mImportantData, "already initialized");
1625 mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
1626 return mData != nsnull;