Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / style / nsCSSDeclaration.cpp
blob9eaa2b91d22ba5f9d459e1e1d3ff54112a315d9f
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_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;
508 return PR_TRUE;
511 nsresult
512 nsCSSDeclaration::GetValue(nsCSSProperty aProperty,
513 nsAString& aValue) const
515 aValue.Truncate(0);
517 // simple properties are easy.
518 if (!nsCSSProps::IsShorthand(aProperty)) {
519 AppendValueToString(aProperty, aValue);
520 return NS_OK;
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
533 // string.
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
537 // those values.
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.
550 continue;
552 ++totalCount;
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) {
557 ++importantCount;
558 storage = mImportantData->StorageFor(*p);
560 if (!storage) {
561 // Case (1) above: some subproperties not specified.
562 return NS_OK;
564 nsCSSUnit unit;
565 switch (nsCSSProps::kTypeTable[*p]) {
566 case eCSSType_Value: {
567 const nsCSSValue *val = static_cast<const nsCSSValue*>(storage);
568 unit = val->GetUnit();
569 } break;
570 case eCSSType_Rect: {
571 const nsCSSRect *rect = static_cast<const nsCSSRect*>(storage);
572 unit = rect->mTop.GetUnit();
573 } break;
574 case eCSSType_ValuePair: {
575 const nsCSSValuePair *pair = static_cast<const nsCSSValuePair*>(storage);
576 unit = pair->mXValue.GetUnit();
577 } break;
578 case eCSSType_ValueList: {
579 const nsCSSValueList* item =
580 *static_cast<nsCSSValueList*const*>(storage);
581 if (item) {
582 unit = item->mValue.GetUnit();
583 } else {
584 unit = eCSSUnit_Null;
586 } break;
587 case eCSSType_ValuePairList: {
588 const nsCSSValuePairList* item =
589 *static_cast<nsCSSValuePairList*const*>(storage);
590 if (item) {
591 unit = item->mXValue.GetUnit();
592 } else {
593 unit = eCSSUnit_Null;
595 } break;
597 if (unit == eCSSUnit_Inherit) {
598 ++inheritCount;
599 } else if (unit == eCSSUnit_Initial) {
600 ++initialCount;
603 if (importantCount != 0 && importantCount != totalCount) {
604 // Case (3), no consistent importance.
605 return NS_OK;
607 if (initialCount == totalCount) {
608 // Simplify serialization below by serializing initial up-front.
609 AppendCSSValueToString(eCSSProperty_UNKNOWN, nsCSSValue(eCSSUnit_Initial),
610 aValue);
611 return NS_OK;
613 if (inheritCount == totalCount) {
614 // Simplify serialization below by serializing inherit up-front.
615 AppendCSSValueToString(eCSSProperty_UNKNOWN, nsCSSValue(eCSSUnit_Inherit),
616 aValue);
617 return NS_OK;
619 if (initialCount != 0 || inheritCount != 0) {
620 // Case (2): partially initial or inherit.
621 return NS_OK;
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?
629 switch (aProperty) {
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,
641 "type mismatch");
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))) {
649 aValue.Truncate();
651 break;
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,
661 "type mismatch");
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);
694 break;
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,
712 "type mismatch");
713 if (!AppendValueToString(subprops[0], aValue) ||
714 !(aValue.Append(PRUnichar(' ')),
715 AppendValueToString(subprops[1], aValue)) ||
716 !(aValue.Append(PRUnichar(' ')),
717 AppendValueToString(subprops[2], aValue))) {
718 aValue.Truncate();
720 break;
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);
747 break;
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) &&
768 appendedSomething) {
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);
774 break;
776 case eCSSProperty_cue: {
777 if (AppendValueToString(eCSSProperty_cue_before, aValue)) {
778 aValue.Append(PRUnichar(' '));
779 if (!AppendValueToString(eCSSProperty_cue_after, aValue))
780 aValue.Truncate();
782 break;
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);
797 } else {
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);
818 break;
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);
826 break;
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);
833 break;
835 case eCSSProperty_pause: {
836 if (AppendValueToString(eCSSProperty_pause_before, aValue)) {
837 aValue.Append(PRUnichar(' '));
838 if (!AppendValueToString(eCSSProperty_pause_after, aValue))
839 aValue.Truncate();
841 break;
843 #ifdef MOZ_SVG
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);
851 break;
853 #endif
854 default:
855 NS_NOTREACHED("no other shorthands");
856 break;
858 return NS_OK;
861 PRBool
862 nsCSSDeclaration::GetValueIsImportant(const nsAString& aProperty) const
864 nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
865 return GetValueIsImportant(propID);
868 PRBool
869 nsCSSDeclaration::GetValueIsImportant(nsCSSProperty aProperty) const
871 if (!mImportantData)
872 return PR_FALSE;
874 // Calling StorageFor is inefficient, but we can assume '!important'
875 // is rare.
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.
881 continue;
883 if (!mImportantData->StorageFor(*p)) {
884 return PR_FALSE;
887 return PR_TRUE;
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!
896 PRBool
897 nsCSSDeclaration::AllPropertiesSameImportance(PRInt32 aFirst, PRInt32 aSecond,
898 PRInt32 aThird, PRInt32 aFourth,
899 PRInt32 aFifth,
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)))) {
907 return PR_FALSE;
909 return PR_TRUE;
912 PRBool
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) {
924 return PR_FALSE;
926 GetValueOrImportantValue(OrderValueAt(aThird-1), otherValue);
927 if (firstValue != otherValue) {
928 return PR_FALSE;
930 GetValueOrImportantValue(OrderValueAt(aFourth-1), otherValue);
931 if (firstValue != otherValue) {
932 return PR_FALSE;
934 return PR_TRUE;
937 /* static */ void
938 nsCSSDeclaration::AppendImportanceToString(PRBool aIsImportant,
939 nsAString& aString)
941 if (aIsImportant) {
942 aString.AppendLiteral(" ! important");
946 void
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("; ");
961 PRBool
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)) {
985 border = PR_TRUE;
987 if (border) {
988 border = PR_FALSE;
989 PRBool isWidthImportant, isStyleImportant, isColorImportant;
990 if (AllPropertiesSameImportance(aBorderTopWidth, aBorderBottomWidth,
991 aBorderLeftWidth, aBorderRightWidth,
993 isWidthImportant) &&
994 AllPropertiesSameImportance(aBorderTopStyle, aBorderBottomStyle,
995 aBorderLeftStyle, aBorderRightStyle,
997 isStyleImportant) &&
998 AllPropertiesSameImportance(aBorderTopColor, aBorderBottomColor,
999 aBorderLeftColor, aBorderRightColor,
1001 isColorImportant)) {
1002 if (isWidthImportant == isStyleImportant && isWidthImportant == isColorImportant) {
1003 border = PR_TRUE;
1004 isImportant = isWidthImportant;
1008 if (border) {
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("; ");
1030 return border;
1033 PRBool
1034 nsCSSDeclaration::TryBorderSideShorthand(nsAString & aString,
1035 nsCSSProperty aShorthand,
1036 PRInt32 aBorderWidth,
1037 PRInt32 aBorderStyle,
1038 PRInt32 aBorderColor) const
1040 PRBool isImportant;
1041 if (AllPropertiesSameImportance(aBorderWidth, aBorderStyle, aBorderColor,
1042 0, 0,
1043 isImportant)) {
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("; ");
1060 return PR_TRUE;
1062 return PR_FALSE;
1065 PRBool
1066 nsCSSDeclaration::TryFourSidesShorthand(nsAString & aString,
1067 nsCSSProperty aShorthand,
1068 PRInt32 & aTop,
1069 PRInt32 & aBottom,
1070 PRInt32 & aLeft,
1071 PRInt32 & aRight,
1072 PRBool aClearIndexes) const
1074 // 0 means not in the mOrder array; otherwise it's index+1
1075 PRBool isImportant;
1076 if (aTop && aBottom && aLeft && aRight &&
1077 AllPropertiesSameImportance(aTop, aBottom, aLeft, aRight,
1079 isImportant)) {
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("; ");
1110 return PR_TRUE;
1112 return PR_FALSE;
1115 void
1116 nsCSSDeclaration::TryBackgroundShorthand(nsAString & aString,
1117 PRInt32 & aBgColor,
1118 PRInt32 & aBgImage,
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
1125 // use a shorthand
1126 PRBool isImportant;
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);
1134 aBgColor = 0;
1136 aString.Append(PRUnichar(' '));
1137 AppendValueToString(eCSSProperty_background_image, aString);
1138 aBgImage = 0;
1140 aString.Append(PRUnichar(' '));
1141 AppendValueToString(eCSSProperty_background_repeat, aString);
1142 aBgRepeat = 0;
1144 aString.Append(PRUnichar(' '));
1145 AppendValueToString(eCSSProperty_background_attachment, aString);
1146 aBgAttachment = 0;
1148 aString.Append(PRUnichar(' '));
1149 AppendValueToString(eCSSProperty_background_position, aString);
1150 aBgPosition = 0;
1152 AppendImportanceToString(isImportant, aString);
1153 aString.AppendLiteral("; ");
1157 void
1158 nsCSSDeclaration::TryOverflowShorthand(nsAString & aString,
1159 PRInt32 & aOverflowX,
1160 PRInt32 & aOverflowY) const
1162 PRBool isImportant;
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),
1171 aString);
1172 aString.AppendLiteral(": ");
1174 AppendCSSValueToString(eCSSProperty_overflow_x, xValue, aString);
1175 AppendImportanceToString(isImportant, aString);
1176 aString.AppendLiteral("; ");
1177 aOverflowX = aOverflowY = 0;
1182 #ifdef MOZ_SVG
1183 void
1184 nsCSSDeclaration::TryMarkerShorthand(nsAString & aString,
1185 PRInt32 & aMarkerEnd,
1186 PRInt32 & aMarkerMid,
1187 PRInt32 & aMarkerStart) const
1189 PRBool isImportant;
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),
1199 aString);
1200 aString.AppendLiteral(": ");
1202 AppendCSSValueToString(eCSSProperty_marker_end, endValue, aString);
1203 AppendImportanceToString(isImportant, aString);
1204 aString.AppendLiteral("; ");
1205 aMarkerEnd = aMarkerMid = aMarkerStart = 0;
1209 #endif
1211 #define NS_CASE_OUTPUT_PROPERTY_VALUE(_prop, _index) \
1212 case _prop: \
1213 if (_index) { \
1214 AppendPropertyAndValueToString(property, aString); \
1215 _index = 0; \
1217 break;
1219 #define NS_CASE_OUTPUT_PROPERTY_VALUE_AS(_prop, _propas, _index) \
1220 case _prop: \
1221 if (_index) { \
1222 AppendPropertyAndValueToString(property, _propas, aString); \
1223 _index = 0; \
1225 break;
1227 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(_condition, _prop, _index) \
1228 case _prop: \
1229 if ((_condition) && _index) { \
1230 AppendPropertyAndValueToString(property, aString); \
1231 _index = 0; \
1233 break;
1235 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(_condition, _prop, _propas, _index) \
1236 case _prop: \
1237 if ((_condition) && _index) { \
1238 AppendPropertyAndValueToString(property, _propas, aString); \
1239 _index = 0; \
1241 break;
1243 void nsCSSDeclaration::PropertyIsSet(PRInt32 & aPropertyIndex, PRInt32 aIndex, PRUint32 & aSet, PRUint32 aValue) const
1245 aPropertyIndex = aIndex + 1;
1246 aSet |= aValue;
1249 nsresult
1250 nsCSSDeclaration::ToString(nsAString& aString) const
1252 PRInt32 count = mOrder.Length();
1253 PRInt32 index;
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;
1268 #ifdef MOZ_SVG
1269 PRInt32 markerEnd = 0, markerMid = 0, markerStart = 0;
1270 #endif
1272 for (index = 0; index < count; index++) {
1273 nsCSSProperty property = OrderValueAt(index);
1274 switch (property) {
1275 case eCSSProperty_border_top_width:
1276 PropertyIsSet(borderTopWidth, index, borderPropertiesSet, B_BORDER_TOP_WIDTH);
1277 break;
1278 case eCSSProperty_border_bottom_width:
1279 PropertyIsSet(borderBottomWidth, index, borderPropertiesSet, B_BORDER_BOTTOM_WIDTH);
1280 break;
1281 case eCSSProperty_border_left_width_value:
1282 PropertyIsSet(borderLeftWidth, index, borderPropertiesSet, B_BORDER_LEFT_WIDTH);
1283 break;
1284 case eCSSProperty_border_right_width_value:
1285 PropertyIsSet(borderRightWidth, index, borderPropertiesSet, B_BORDER_RIGHT_WIDTH);
1286 break;
1287 case eCSSProperty_border_start_width_value:
1288 borderStartWidth = index+1;
1289 break;
1290 case eCSSProperty_border_end_width_value:
1291 borderEndWidth = index+1;
1292 break;
1294 case eCSSProperty_border_top_style:
1295 PropertyIsSet(borderTopStyle, index, borderPropertiesSet, B_BORDER_TOP_STYLE);
1296 break;
1297 case eCSSProperty_border_bottom_style:
1298 PropertyIsSet(borderBottomStyle, index, borderPropertiesSet, B_BORDER_BOTTOM_STYLE);
1299 break;
1300 case eCSSProperty_border_left_style_value:
1301 PropertyIsSet(borderLeftStyle, index, borderPropertiesSet, B_BORDER_LEFT_STYLE);
1302 break;
1303 case eCSSProperty_border_right_style_value:
1304 PropertyIsSet(borderRightStyle, index, borderPropertiesSet, B_BORDER_RIGHT_STYLE);
1305 break;
1306 case eCSSProperty_border_start_style_value:
1307 borderStartStyle = index+1;
1308 break;
1309 case eCSSProperty_border_end_style_value:
1310 borderEndStyle = index+1;
1311 break;
1313 case eCSSProperty_border_top_color:
1314 PropertyIsSet(borderTopColor, index, borderPropertiesSet, B_BORDER_TOP_COLOR);
1315 break;
1316 case eCSSProperty_border_bottom_color:
1317 PropertyIsSet(borderBottomColor, index, borderPropertiesSet, B_BORDER_BOTTOM_COLOR);
1318 break;
1319 case eCSSProperty_border_left_color_value:
1320 PropertyIsSet(borderLeftColor, index, borderPropertiesSet, B_BORDER_LEFT_COLOR);
1321 break;
1322 case eCSSProperty_border_right_color_value:
1323 PropertyIsSet(borderRightColor, index, borderPropertiesSet, B_BORDER_RIGHT_COLOR);
1324 break;
1325 case eCSSProperty_border_start_color_value:
1326 borderStartColor = index+1;
1327 break;
1328 case eCSSProperty_border_end_color_value:
1329 borderEndColor = index+1;
1330 break;
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;
1355 #ifdef MOZ_SVG
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;
1359 #endif
1361 default: 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,
1375 PR_FALSE)) {
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,
1382 PR_FALSE)) {
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,
1389 PR_FALSE)) {
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,
1421 PR_TRUE);
1422 TryFourSidesShorthand(aString, eCSSProperty_padding,
1423 paddingTop, paddingBottom,
1424 paddingLeft, paddingRight,
1425 PR_TRUE);
1426 TryBackgroundShorthand(aString,
1427 bgColor, bgImage, bgRepeat, bgAttachment,
1428 bgPosition);
1429 TryOverflowShorthand(aString, overflowX, overflowY);
1430 #ifdef MOZ_SVG
1431 TryMarkerShorthand(aString, markerEnd, markerMid, markerStart);
1432 #endif
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
1441 // properties.
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);
1453 switch (property) {
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)
1523 #ifdef MOZ_SVG
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)
1527 #endif
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:
1553 break;
1555 case eCSSProperty_margin_start_value:
1556 AppendPropertyAndValueToString(property, eCSSProperty_margin_start,
1557 aString);
1558 break;
1559 case eCSSProperty_margin_end_value:
1560 AppendPropertyAndValueToString(property, eCSSProperty_margin_end,
1561 aString);
1562 break;
1563 case eCSSProperty_padding_start_value:
1564 AppendPropertyAndValueToString(property, eCSSProperty_padding_start,
1565 aString);
1566 break;
1567 case eCSSProperty_padding_end_value:
1568 AppendPropertyAndValueToString(property, eCSSProperty_padding_end,
1569 aString);
1570 break;
1572 default:
1573 if (0 <= property) {
1574 AppendPropertyAndValueToString(property, aString);
1576 break;
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);
1583 return NS_OK;
1586 #ifdef DEBUG
1587 void nsCSSDeclaration::List(FILE* out, PRInt32 aIndent) const
1589 for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
1591 fputs("{ ", out);
1592 nsAutoString s;
1593 ToString(s);
1594 fputs(NS_ConvertUTF16toUTF8(s).get(), out);
1595 fputs("}", out);
1597 #endif
1599 nsresult
1600 nsCSSDeclaration::GetNthProperty(PRUint32 aIndex, nsAString& aReturn) const
1602 aReturn.Truncate();
1603 if (aIndex < mOrder.Length()) {
1604 nsCSSProperty property = OrderValueAt(aIndex);
1605 if (0 <= property) {
1606 AppendASCIItoUTF16(nsCSSProps::GetStringValue(property), aReturn);
1610 return NS_OK;
1613 nsCSSDeclaration*
1614 nsCSSDeclaration::Clone() const
1616 return new nsCSSDeclaration(*this);
1619 PRBool
1620 nsCSSDeclaration::InitializeEmpty()
1622 NS_ASSERTION(!mData && !mImportantData, "already initialized");
1623 mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
1624 return mData != nsnull;