Bug 451040 ? Passwords Manager Empty after convert to MozStorage. r=gavin
[wine-gecko.git] / layout / style / nsCSSDeclaration.cpp
blob3da26110912ced172d094d11fc20d9b96c2a5f83
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 nsresult
183 nsCSSDeclaration::GetValue(const nsAString& aProperty,
184 nsAString& aValue) const
186 nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
187 return GetValue(propID, aValue);
190 PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const
192 nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
193 ? mImportantData : mData;
194 const void *storage = data->StorageFor(aProperty);
195 if (storage) {
196 switch (nsCSSProps::kTypeTable[aProperty]) {
197 case eCSSType_Value: {
198 const nsCSSValue *val = static_cast<const nsCSSValue*>(storage);
199 AppendCSSValueToString(aProperty, *val, aResult);
200 } break;
201 case eCSSType_Rect: {
202 const nsCSSRect *rect = static_cast<const nsCSSRect*>(storage);
203 if (rect->mTop.GetUnit() == eCSSUnit_Inherit ||
204 rect->mTop.GetUnit() == eCSSUnit_Initial) {
205 NS_ASSERTION(rect->mRight.GetUnit() == rect->mTop.GetUnit(),
206 "Top inherit or initial, right isn't. Fix the parser!");
207 NS_ASSERTION(rect->mBottom.GetUnit() == rect->mTop.GetUnit(),
208 "Top inherit or initial, bottom isn't. Fix the parser!");
209 NS_ASSERTION(rect->mLeft.GetUnit() == rect->mTop.GetUnit(),
210 "Top inherit or initial, left isn't. Fix the parser!");
211 AppendCSSValueToString(aProperty, rect->mTop, aResult);
212 } else {
213 aResult.AppendLiteral("rect(");
214 AppendCSSValueToString(aProperty, rect->mTop, aResult);
215 NS_NAMED_LITERAL_STRING(comma, ", ");
216 aResult.Append(comma);
217 AppendCSSValueToString(aProperty, rect->mRight, aResult);
218 aResult.Append(comma);
219 AppendCSSValueToString(aProperty, rect->mBottom, aResult);
220 aResult.Append(comma);
221 AppendCSSValueToString(aProperty, rect->mLeft, aResult);
222 aResult.Append(PRUnichar(')'));
224 } break;
225 case eCSSType_ValuePair: {
226 const nsCSSValuePair *pair = static_cast<const nsCSSValuePair*>(storage);
227 AppendCSSValueToString(aProperty, pair->mXValue, aResult);
228 if (pair->mYValue != pair->mXValue ||
229 (aProperty == eCSSProperty_background_position &&
230 pair->mXValue.GetUnit() != eCSSUnit_Inherit &&
231 pair->mXValue.GetUnit() != eCSSUnit_Initial)) {
232 // Only output a Y value if it's different from the X value
233 // or if it's a background-position value other than 'initial'
234 // or 'inherit'.
235 aResult.Append(PRUnichar(' '));
236 AppendCSSValueToString(aProperty, pair->mYValue, aResult);
238 } break;
239 case eCSSType_ValueList: {
240 const nsCSSValueList* val =
241 *static_cast<nsCSSValueList*const*>(storage);
242 do {
243 AppendCSSValueToString(aProperty, val->mValue, aResult);
244 val = val->mNext;
245 if (val) {
246 if (aProperty == eCSSProperty_cursor
247 || aProperty == eCSSProperty_text_shadow
248 || aProperty == eCSSProperty_box_shadow
249 #ifdef MOZ_SVG
250 || aProperty == eCSSProperty_stroke_dasharray
251 #endif
253 aResult.Append(PRUnichar(','));
254 aResult.Append(PRUnichar(' '));
256 } while (val);
257 } break;
258 case eCSSType_ValuePairList: {
259 const nsCSSValuePairList* item =
260 *static_cast<nsCSSValuePairList*const*>(storage);
261 do {
262 NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Null,
263 "unexpected null unit");
264 AppendCSSValueToString(aProperty, item->mXValue, aResult);
265 if (item->mYValue.GetUnit() != eCSSUnit_Null) {
266 aResult.Append(PRUnichar(' '));
267 AppendCSSValueToString(aProperty, item->mYValue, aResult);
269 item = item->mNext;
270 if (item) {
271 aResult.Append(PRUnichar(' '));
273 } while (item);
274 } break;
277 return storage != nsnull;
280 /* static */ PRBool
281 nsCSSDeclaration::AppendCSSValueToString(nsCSSProperty aProperty,
282 const nsCSSValue& aValue,
283 nsAString& aResult)
285 nsCSSUnit unit = aValue.GetUnit();
287 if (eCSSUnit_Null == unit) {
288 return PR_FALSE;
291 if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) {
292 if (unit == eCSSUnit_Attr) {
293 aResult.AppendLiteral("attr(");
295 nsAutoString buffer;
296 aValue.GetStringValue(buffer);
297 aResult.Append(buffer);
299 else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Counters) {
300 switch (unit) {
301 case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break;
302 case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
303 default: break;
306 nsCSSValue::Array *array = aValue.GetArrayValue();
307 PRBool mark = PR_FALSE;
308 for (PRUint16 i = 0, i_end = array->Count(); i < i_end; ++i) {
309 if (aProperty == eCSSProperty_border_image && i >= 5) {
310 if (array->Item(i).GetUnit() == eCSSUnit_Null) {
311 continue;
313 if (i == 5) {
314 aResult.AppendLiteral(" /");
317 if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
318 if (unit == eCSSUnit_Array)
319 aResult.AppendLiteral(" ");
320 else
321 aResult.AppendLiteral(", ");
323 nsCSSProperty prop =
324 ((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) &&
325 i == array->Count() - 1)
326 ? eCSSProperty_list_style_type : aProperty;
327 if (AppendCSSValueToString(prop, array->Item(i), aResult)) {
328 mark = PR_TRUE;
332 else if (eCSSUnit_Integer == unit) {
333 nsAutoString tmpStr;
334 tmpStr.AppendInt(aValue.GetIntValue(), 10);
335 aResult.Append(tmpStr);
337 else if (eCSSUnit_Enumerated == unit) {
338 if (eCSSProperty_text_decoration == aProperty) {
339 PRInt32 intValue = aValue.GetIntValue();
340 if (NS_STYLE_TEXT_DECORATION_NONE != intValue) {
341 PRInt32 mask;
342 for (mask = NS_STYLE_TEXT_DECORATION_UNDERLINE;
343 mask <= NS_STYLE_TEXT_DECORATION_BLINK;
344 mask <<= 1) {
345 if ((mask & intValue) == mask) {
346 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, mask), aResult);
347 intValue &= ~mask;
348 if (0 != intValue) { // more left
349 aResult.Append(PRUnichar(' '));
354 else {
355 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, NS_STYLE_TEXT_DECORATION_NONE), aResult);
358 else if (eCSSProperty_azimuth == aProperty) {
359 PRInt32 intValue = aValue.GetIntValue();
360 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, (intValue & ~NS_STYLE_AZIMUTH_BEHIND)), aResult);
361 if ((NS_STYLE_AZIMUTH_BEHIND & intValue) != 0) {
362 aResult.Append(PRUnichar(' '));
363 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, NS_STYLE_AZIMUTH_BEHIND), aResult);
366 else if (eCSSProperty_marks == aProperty) {
367 PRInt32 intValue = aValue.GetIntValue();
368 if ((NS_STYLE_PAGE_MARKS_CROP & intValue) != 0) {
369 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, NS_STYLE_PAGE_MARKS_CROP), aResult);
371 if ((NS_STYLE_PAGE_MARKS_REGISTER & intValue) != 0) {
372 if ((NS_STYLE_PAGE_MARKS_CROP & intValue) != 0) {
373 aResult.Append(PRUnichar(' '));
375 AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, NS_STYLE_PAGE_MARKS_REGISTER), aResult);
378 else {
379 const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, aValue.GetIntValue());
380 AppendASCIItoUTF16(name, aResult);
383 else if (eCSSUnit_EnumColor == unit) {
384 // we can lookup the property in the ColorTable and then
385 // get a string mapping the name
386 nsCAutoString str;
387 if (nsCSSProps::GetColorName(aValue.GetIntValue(), str)){
388 AppendASCIItoUTF16(str, aResult);
389 } else {
390 NS_NOTREACHED("bad color value");
393 else if (eCSSUnit_Color == unit) {
394 nscolor color = aValue.GetColorValue();
395 if (color == NS_RGBA(0, 0, 0, 0)) {
396 // Use the strictest match for 'transparent' so we do correct
397 // round-tripping of all other rgba() values.
398 aResult.AppendLiteral("transparent");
399 } else {
400 nsAutoString tmpStr;
401 PRUint8 a = NS_GET_A(color);
402 if (a < 255) {
403 tmpStr.AppendLiteral("rgba(");
404 } else {
405 tmpStr.AppendLiteral("rgb(");
408 NS_NAMED_LITERAL_STRING(comma, ", ");
410 tmpStr.AppendInt(NS_GET_R(color), 10);
411 tmpStr.Append(comma);
412 tmpStr.AppendInt(NS_GET_G(color), 10);
413 tmpStr.Append(comma);
414 tmpStr.AppendInt(NS_GET_B(color), 10);
415 if (a < 255) {
416 tmpStr.Append(comma);
417 tmpStr.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
419 tmpStr.Append(PRUnichar(')'));
421 aResult.Append(tmpStr);
424 else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
425 aResult.Append(NS_LITERAL_STRING("url(") +
426 nsDependentString(aValue.GetOriginalURLValue()) +
427 NS_LITERAL_STRING(")"));
429 else if (eCSSUnit_Percent == unit) {
430 nsAutoString tmpStr;
431 tmpStr.AppendFloat(aValue.GetPercentValue() * 100.0f);
432 aResult.Append(tmpStr);
434 else if (eCSSUnit_Percent < unit) { // length unit
435 nsAutoString tmpStr;
436 tmpStr.AppendFloat(aValue.GetFloatValue());
437 aResult.Append(tmpStr);
440 switch (unit) {
441 case eCSSUnit_Null: break;
442 case eCSSUnit_Auto: aResult.AppendLiteral("auto"); break;
443 case eCSSUnit_Inherit: aResult.AppendLiteral("inherit"); break;
444 case eCSSUnit_Initial: aResult.AppendLiteral("-moz-initial"); break;
445 case eCSSUnit_None: aResult.AppendLiteral("none"); break;
446 case eCSSUnit_Normal: aResult.AppendLiteral("normal"); break;
447 case eCSSUnit_System_Font: aResult.AppendLiteral("-moz-use-system-font"); break;
449 case eCSSUnit_String: break;
450 case eCSSUnit_URL: break;
451 case eCSSUnit_Image: break;
452 case eCSSUnit_Array: break;
453 case eCSSUnit_Attr:
454 case eCSSUnit_Counter:
455 case eCSSUnit_Counters: aResult.Append(PRUnichar(')')); break;
456 case eCSSUnit_Integer: break;
457 case eCSSUnit_Enumerated: break;
458 case eCSSUnit_EnumColor: break;
459 case eCSSUnit_Color: break;
460 case eCSSUnit_Percent: aResult.Append(PRUnichar('%')); break;
461 case eCSSUnit_Number: break;
463 case eCSSUnit_Inch: aResult.AppendLiteral("in"); break;
464 case eCSSUnit_Foot: aResult.AppendLiteral("ft"); break;
465 case eCSSUnit_Mile: aResult.AppendLiteral("mi"); break;
466 case eCSSUnit_Millimeter: aResult.AppendLiteral("mm"); break;
467 case eCSSUnit_Centimeter: aResult.AppendLiteral("cm"); break;
468 case eCSSUnit_Meter: aResult.AppendLiteral("m"); break;
469 case eCSSUnit_Kilometer: aResult.AppendLiteral("km"); break;
470 case eCSSUnit_Point: aResult.AppendLiteral("pt"); break;
471 case eCSSUnit_Pica: aResult.AppendLiteral("pc"); break;
472 case eCSSUnit_Didot: aResult.AppendLiteral("dt"); break;
473 case eCSSUnit_Cicero: aResult.AppendLiteral("cc"); break;
475 case eCSSUnit_EM: aResult.AppendLiteral("em"); break;
476 case eCSSUnit_EN: aResult.AppendLiteral("en"); break;
477 case eCSSUnit_XHeight: aResult.AppendLiteral("ex"); break;
478 case eCSSUnit_CapHeight: aResult.AppendLiteral("cap"); break;
479 case eCSSUnit_Char: aResult.AppendLiteral("ch"); break;
481 case eCSSUnit_Pixel: aResult.AppendLiteral("px"); break;
483 case eCSSUnit_Degree: aResult.AppendLiteral("deg"); break;
484 case eCSSUnit_Grad: aResult.AppendLiteral("grad"); break;
485 case eCSSUnit_Radian: aResult.AppendLiteral("rad"); break;
487 case eCSSUnit_Hertz: aResult.AppendLiteral("Hz"); break;
488 case eCSSUnit_Kilohertz: aResult.AppendLiteral("kHz"); break;
490 case eCSSUnit_Seconds: aResult.Append(PRUnichar('s')); break;
491 case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break;
494 return PR_TRUE;
497 nsresult
498 nsCSSDeclaration::GetValue(nsCSSProperty aProperty,
499 nsAString& aValue) const
501 aValue.Truncate(0);
503 // simple properties are easy.
504 if (!nsCSSProps::IsShorthand(aProperty)) {
505 AppendValueToString(aProperty, aValue);
506 return NS_OK;
509 // shorthands
510 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
511 if (!mData->StorageFor(*p) &&
512 (!mImportantData || !mImportantData->StorageFor(*p)))
513 // We don't have all the properties in the shorthand.
514 if (*p != eCSSProperty__x_system_font)
515 return NS_OK;
519 // XXX What about checking the consistency of '!important'?
520 // XXX What about checking that we don't serialize inherit,
521 // -moz-initial, or other illegal values?
522 // XXXldb Can we share shorthand logic with ToString?
523 switch (aProperty) {
524 case eCSSProperty_margin:
525 case eCSSProperty_padding:
526 case eCSSProperty_border_color:
527 case eCSSProperty_border_style:
528 case eCSSProperty__moz_border_radius:
529 case eCSSProperty__moz_outline_radius:
530 case eCSSProperty_border_width: {
531 const nsCSSProperty* subprops =
532 nsCSSProps::SubpropertyEntryFor(aProperty);
533 NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
534 nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
535 nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value &&
536 nsCSSProps::kTypeTable[subprops[3]] == eCSSType_Value,
537 "type mismatch");
538 if (!AppendValueToString(subprops[0], aValue) ||
539 !(aValue.Append(PRUnichar(' ')),
540 AppendValueToString(subprops[1], aValue)) ||
541 !(aValue.Append(PRUnichar(' ')),
542 AppendValueToString(subprops[2], aValue)) ||
543 !(aValue.Append(PRUnichar(' ')),
544 AppendValueToString(subprops[3], aValue))) {
545 aValue.Truncate();
547 break;
549 case eCSSProperty_border:
550 // XXX More consistency checking needed before falling through.
551 aProperty = eCSSProperty_border_top;
552 case eCSSProperty_border_top:
553 case eCSSProperty_border_right:
554 case eCSSProperty_border_bottom:
555 case eCSSProperty_border_left:
556 case eCSSProperty_border_start:
557 case eCSSProperty_border_end:
558 case eCSSProperty__moz_column_rule:
559 case eCSSProperty_outline: {
560 const nsCSSProperty* subprops =
561 nsCSSProps::SubpropertyEntryFor(aProperty);
562 NS_ASSERTION(nsCSSProps::kTypeTable[subprops[0]] == eCSSType_Value &&
563 nsCSSProps::kTypeTable[subprops[1]] == eCSSType_Value &&
564 nsCSSProps::kTypeTable[subprops[2]] == eCSSType_Value,
565 "type mismatch");
566 if (!AppendValueToString(subprops[0], aValue) ||
567 !(aValue.Append(PRUnichar(' ')),
568 AppendValueToString(subprops[1], aValue)) ||
569 !(aValue.Append(PRUnichar(' ')),
570 AppendValueToString(subprops[2], aValue))) {
571 aValue.Truncate();
573 break;
575 case eCSSProperty_margin_left:
576 case eCSSProperty_margin_right:
577 case eCSSProperty_margin_start:
578 case eCSSProperty_margin_end:
579 case eCSSProperty_padding_left:
580 case eCSSProperty_padding_right:
581 case eCSSProperty_padding_start:
582 case eCSSProperty_padding_end:
583 case eCSSProperty_border_left_color:
584 case eCSSProperty_border_left_style:
585 case eCSSProperty_border_left_width:
586 case eCSSProperty_border_right_color:
587 case eCSSProperty_border_right_style:
588 case eCSSProperty_border_right_width:
589 case eCSSProperty_border_start_color:
590 case eCSSProperty_border_start_style:
591 case eCSSProperty_border_start_width:
592 case eCSSProperty_border_end_color:
593 case eCSSProperty_border_end_style:
594 case eCSSProperty_border_end_width: {
595 const nsCSSProperty* subprops =
596 nsCSSProps::SubpropertyEntryFor(aProperty);
597 NS_ASSERTION(subprops[3] == eCSSProperty_UNKNOWN,
598 "not box property with physical vs. logical cascading");
599 AppendValueToString(subprops[0], aValue);
600 break;
602 case eCSSProperty_background: {
603 PRBool appendedSomething = PR_FALSE;
604 if (AppendValueToString(eCSSProperty_background_color, aValue)) {
605 appendedSomething = PR_TRUE;
606 aValue.Append(PRUnichar(' '));
608 if (AppendValueToString(eCSSProperty_background_image, aValue)) {
609 aValue.Append(PRUnichar(' '));
610 appendedSomething = PR_TRUE;
612 if (AppendValueToString(eCSSProperty_background_repeat, aValue)) {
613 aValue.Append(PRUnichar(' '));
614 appendedSomething = PR_TRUE;
616 if (AppendValueToString(eCSSProperty_background_attachment, aValue)) {
617 aValue.Append(PRUnichar(' '));
618 appendedSomething = PR_TRUE;
620 if (!AppendValueToString(eCSSProperty_background_position, aValue) &&
621 appendedSomething) {
622 NS_ASSERTION(!aValue.IsEmpty() && aValue.Last() == PRUnichar(' '),
623 "We appended a space before!");
624 // We appended an extra space. Let's get rid of it
625 aValue.Truncate(aValue.Length() - 1);
627 break;
629 case eCSSProperty_cue: {
630 if (AppendValueToString(eCSSProperty_cue_before, aValue)) {
631 aValue.Append(PRUnichar(' '));
632 if (!AppendValueToString(eCSSProperty_cue_after, aValue))
633 aValue.Truncate();
635 break;
637 case eCSSProperty_font: {
638 nsCSSValue style, variant, weight, size, lh, family, systemFont;
639 GetValueOrImportantValue(eCSSProperty__x_system_font, systemFont);
640 GetValueOrImportantValue(eCSSProperty_font_style, style);
641 GetValueOrImportantValue(eCSSProperty_font_variant, variant);
642 GetValueOrImportantValue(eCSSProperty_font_weight, weight);
643 GetValueOrImportantValue(eCSSProperty_font_size, size);
644 GetValueOrImportantValue(eCSSProperty_line_height, lh);
645 GetValueOrImportantValue(eCSSProperty_font_family, family);
647 if (systemFont.GetUnit() != eCSSUnit_None &&
648 systemFont.GetUnit() != eCSSUnit_Null) {
649 AppendCSSValueToString(eCSSProperty__x_system_font, systemFont, aValue);
650 } else {
651 if (style.GetUnit() != eCSSUnit_Normal) {
652 AppendCSSValueToString(eCSSProperty_font_style, style, aValue);
653 aValue.Append(PRUnichar(' '));
655 if (variant.GetUnit() != eCSSUnit_Normal) {
656 AppendCSSValueToString(eCSSProperty_font_variant, variant, aValue);
657 aValue.Append(PRUnichar(' '));
659 if (weight.GetUnit() != eCSSUnit_Normal) {
660 AppendCSSValueToString(eCSSProperty_font_weight, weight, aValue);
661 aValue.Append(PRUnichar(' '));
663 AppendCSSValueToString(eCSSProperty_font_size, size, aValue);
664 if (lh.GetUnit() != eCSSUnit_Normal) {
665 aValue.Append(PRUnichar('/'));
666 AppendCSSValueToString(eCSSProperty_line_height, lh, aValue);
668 aValue.Append(PRUnichar(' '));
669 AppendCSSValueToString(eCSSProperty_font_family, family, aValue);
671 break;
673 case eCSSProperty_list_style:
674 if (AppendValueToString(eCSSProperty_list_style_type, aValue))
675 aValue.Append(PRUnichar(' '));
676 if (AppendValueToString(eCSSProperty_list_style_position, aValue))
677 aValue.Append(PRUnichar(' '));
678 AppendValueToString(eCSSProperty_list_style_image, aValue);
679 break;
680 case eCSSProperty_overflow: {
681 nsCSSValue xValue, yValue;
682 GetValueOrImportantValue(eCSSProperty_overflow_x, xValue);
683 GetValueOrImportantValue(eCSSProperty_overflow_y, yValue);
684 if (xValue == yValue)
685 AppendValueToString(eCSSProperty_overflow_x, aValue);
686 break;
688 case eCSSProperty_pause: {
689 if (AppendValueToString(eCSSProperty_pause_before, aValue)) {
690 aValue.Append(PRUnichar(' '));
691 if (!AppendValueToString(eCSSProperty_pause_after, aValue))
692 aValue.Truncate();
694 break;
696 #ifdef MOZ_SVG
697 case eCSSProperty_marker: {
698 nsCSSValue endValue, midValue, startValue;
699 GetValueOrImportantValue(eCSSProperty_marker_end, endValue);
700 GetValueOrImportantValue(eCSSProperty_marker_mid, midValue);
701 GetValueOrImportantValue(eCSSProperty_marker_start, startValue);
702 if (endValue == midValue && midValue == startValue)
703 AppendValueToString(eCSSProperty_marker_end, aValue);
704 break;
706 #endif
707 default:
708 NS_NOTREACHED("no other shorthands");
709 break;
711 return NS_OK;
714 PRBool
715 nsCSSDeclaration::GetValueIsImportant(const nsAString& aProperty) const
717 nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
718 return GetValueIsImportant(propID);
721 PRBool
722 nsCSSDeclaration::GetValueIsImportant(nsCSSProperty aProperty) const
724 if (!mImportantData)
725 return PR_FALSE;
727 // Inefficient, but we can assume '!important' is rare.
728 return mImportantData->StorageFor(aProperty) != nsnull;
731 // XXXldb Bug 376075 All callers of AllPropertiesSameImportance also
732 // need to check for 'inherit' and 'initial' values, since you can't
733 // output a mix of either mixed with other values in the same shorthand!
734 PRBool
735 nsCSSDeclaration::AllPropertiesSameImportance(PRInt32 aFirst, PRInt32 aSecond,
736 PRInt32 aThird, PRInt32 aFourth,
737 PRInt32 aFifth,
738 PRBool & aImportance) const
740 aImportance = GetValueIsImportant(OrderValueAt(aFirst-1));
741 if ((aSecond && aImportance != GetValueIsImportant(OrderValueAt(aSecond-1))) ||
742 (aThird && aImportance != GetValueIsImportant(OrderValueAt(aThird-1))) ||
743 (aFourth && aImportance != GetValueIsImportant(OrderValueAt(aFourth-1))) ||
744 (aFifth && aImportance != GetValueIsImportant(OrderValueAt(aFifth-1)))) {
745 return PR_FALSE;
747 return PR_TRUE;
750 PRBool
751 nsCSSDeclaration::AllPropertiesSameValue(PRInt32 aFirst, PRInt32 aSecond,
752 PRInt32 aThird, PRInt32 aFourth) const
754 nsCSSValue firstValue, otherValue;
755 // TryBorderShorthand does the bounds-checking for us; valid values there
756 // are > 0; 0 is a flag for "not set". We here are passed the actual
757 // index, which comes from finding the value in the mOrder property array.
758 // Of course, re-getting the mOrder value here is pretty silly.
759 GetValueOrImportantValue(OrderValueAt(aFirst-1), firstValue);
760 GetValueOrImportantValue(OrderValueAt(aSecond-1), otherValue);
761 if (firstValue != otherValue) {
762 return PR_FALSE;
764 GetValueOrImportantValue(OrderValueAt(aThird-1), otherValue);
765 if (firstValue != otherValue) {
766 return PR_FALSE;
768 GetValueOrImportantValue(OrderValueAt(aFourth-1), otherValue);
769 if (firstValue != otherValue) {
770 return PR_FALSE;
772 return PR_TRUE;
775 /* static */ void
776 nsCSSDeclaration::AppendImportanceToString(PRBool aIsImportant,
777 nsAString& aString)
779 if (aIsImportant) {
780 aString.AppendLiteral(" ! important");
784 void
785 nsCSSDeclaration::AppendPropertyAndValueToString(nsCSSProperty aProperty,
786 nsCSSProperty aPropertyName,
787 nsAString& aResult) const
789 NS_ASSERTION(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
790 "property enum out of range");
791 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aPropertyName), aResult);
792 aResult.AppendLiteral(": ");
793 AppendValueToString(aProperty, aResult);
794 PRBool isImportant = GetValueIsImportant(aProperty);
795 AppendImportanceToString(isImportant, aResult);
796 aResult.AppendLiteral("; ");
799 PRBool
800 nsCSSDeclaration::TryBorderShorthand(nsAString & aString, PRUint32 aPropertiesSet,
801 PRInt32 aBorderTopWidth,
802 PRInt32 aBorderTopStyle,
803 PRInt32 aBorderTopColor,
804 PRInt32 aBorderBottomWidth,
805 PRInt32 aBorderBottomStyle,
806 PRInt32 aBorderBottomColor,
807 PRInt32 aBorderLeftWidth,
808 PRInt32 aBorderLeftStyle,
809 PRInt32 aBorderLeftColor,
810 PRInt32 aBorderRightWidth,
811 PRInt32 aBorderRightStyle,
812 PRInt32 aBorderRightColor) const
814 PRBool border = PR_FALSE, isImportant = PR_FALSE;
815 // 0 means not in the mOrder array; otherwise it's index+1
816 if (B_BORDER == aPropertiesSet
817 && AllPropertiesSameValue(aBorderTopWidth, aBorderBottomWidth,
818 aBorderLeftWidth, aBorderRightWidth)
819 && AllPropertiesSameValue(aBorderTopStyle, aBorderBottomStyle,
820 aBorderLeftStyle, aBorderRightStyle)
821 && AllPropertiesSameValue(aBorderTopColor, aBorderBottomColor,
822 aBorderLeftColor, aBorderRightColor)) {
823 border = PR_TRUE;
825 if (border) {
826 border = PR_FALSE;
827 PRBool isWidthImportant, isStyleImportant, isColorImportant;
828 if (AllPropertiesSameImportance(aBorderTopWidth, aBorderBottomWidth,
829 aBorderLeftWidth, aBorderRightWidth,
831 isWidthImportant) &&
832 AllPropertiesSameImportance(aBorderTopStyle, aBorderBottomStyle,
833 aBorderLeftStyle, aBorderRightStyle,
835 isStyleImportant) &&
836 AllPropertiesSameImportance(aBorderTopColor, aBorderBottomColor,
837 aBorderLeftColor, aBorderRightColor,
839 isColorImportant)) {
840 if (isWidthImportant == isStyleImportant && isWidthImportant == isColorImportant) {
841 border = PR_TRUE;
842 isImportant = isWidthImportant;
846 if (border) {
847 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_border), aString);
848 aString.AppendLiteral(": ");
850 AppendValueToString(eCSSProperty_border_top_width, aString);
851 aString.Append(PRUnichar(' '));
853 AppendValueToString(eCSSProperty_border_top_style, aString);
854 aString.Append(PRUnichar(' '));
856 nsAutoString valueString;
857 AppendValueToString(eCSSProperty_border_top_color, valueString);
858 if (!valueString.EqualsLiteral("-moz-use-text-color")) {
859 /* don't output this value, it's proprietary Mozilla and */
860 /* not intended to be exposed ; we can remove it from the */
861 /* values of the shorthand since this value represents the */
862 /* initial value of border-*-color */
863 aString.Append(valueString);
865 AppendImportanceToString(isImportant, aString);
866 aString.AppendLiteral("; ");
868 return border;
871 PRBool
872 nsCSSDeclaration::TryBorderSideShorthand(nsAString & aString,
873 nsCSSProperty aShorthand,
874 PRInt32 aBorderWidth,
875 PRInt32 aBorderStyle,
876 PRInt32 aBorderColor) const
878 PRBool isImportant;
879 if (AllPropertiesSameImportance(aBorderWidth, aBorderStyle, aBorderColor,
880 0, 0,
881 isImportant)) {
882 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand), aString);
883 aString.AppendLiteral(": ");
885 AppendValueToString(OrderValueAt(aBorderWidth-1), aString);
887 aString.Append(PRUnichar(' '));
888 AppendValueToString(OrderValueAt(aBorderStyle-1), aString);
890 nsAutoString valueString;
891 AppendValueToString(OrderValueAt(aBorderColor-1), valueString);
892 if (!valueString.EqualsLiteral("-moz-use-text-color")) {
893 aString.AppendLiteral(" ");
894 aString.Append(valueString);
896 AppendImportanceToString(isImportant, aString);
897 aString.AppendLiteral("; ");
898 return PR_TRUE;
900 return PR_FALSE;
903 PRBool
904 nsCSSDeclaration::TryFourSidesShorthand(nsAString & aString,
905 nsCSSProperty aShorthand,
906 PRInt32 & aTop,
907 PRInt32 & aBottom,
908 PRInt32 & aLeft,
909 PRInt32 & aRight,
910 PRBool aClearIndexes) const
912 // 0 means not in the mOrder array; otherwise it's index+1
913 PRBool isImportant;
914 if (aTop && aBottom && aLeft && aRight &&
915 AllPropertiesSameImportance(aTop, aBottom, aLeft, aRight,
917 isImportant)) {
918 // all 4 properties are set, we can output a shorthand
919 AppendASCIItoUTF16(nsCSSProps::GetStringValue(aShorthand), aString);
920 aString.AppendLiteral(": ");
921 nsCSSValue topValue, bottomValue, leftValue, rightValue;
922 nsCSSProperty topProp = OrderValueAt(aTop-1);
923 nsCSSProperty bottomProp = OrderValueAt(aBottom-1);
924 nsCSSProperty leftProp = OrderValueAt(aLeft-1);
925 nsCSSProperty rightProp = OrderValueAt(aRight-1);
926 GetValueOrImportantValue(topProp, topValue);
927 GetValueOrImportantValue(bottomProp, bottomValue);
928 GetValueOrImportantValue(leftProp, leftValue);
929 GetValueOrImportantValue(rightProp, rightValue);
930 AppendCSSValueToString(topProp, topValue, aString);
931 if (topValue != rightValue || topValue != leftValue || topValue != bottomValue) {
932 aString.Append(PRUnichar(' '));
933 AppendCSSValueToString(rightProp, rightValue, aString);
934 if (topValue != bottomValue || rightValue != leftValue) {
935 aString.Append(PRUnichar(' '));
936 AppendCSSValueToString(bottomProp, bottomValue, aString);
937 if (rightValue != leftValue) {
938 aString.Append(PRUnichar(' '));
939 AppendCSSValueToString(leftProp, leftValue, aString);
943 if (aClearIndexes) {
944 aTop = 0; aBottom = 0; aLeft = 0; aRight = 0;
946 AppendImportanceToString(isImportant, aString);
947 aString.AppendLiteral("; ");
948 return PR_TRUE;
950 return PR_FALSE;
953 void
954 nsCSSDeclaration::TryBackgroundShorthand(nsAString & aString,
955 PRInt32 & aBgColor,
956 PRInt32 & aBgImage,
957 PRInt32 & aBgRepeat,
958 PRInt32 & aBgAttachment,
959 PRInt32 & aBgPosition) const
961 // 0 means not in the mOrder array; otherwise it's index+1
962 // check if we have at least two properties set; otherwise, no need to
963 // use a shorthand
964 PRBool isImportant;
965 if (aBgColor && aBgImage && aBgRepeat && aBgAttachment && aBgPosition &&
966 AllPropertiesSameImportance(aBgColor, aBgImage, aBgRepeat, aBgAttachment,
967 aBgPosition, isImportant)) {
968 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_background), aString);
969 aString.AppendLiteral(": ");
971 AppendValueToString(eCSSProperty_background_color, aString);
972 aBgColor = 0;
974 aString.Append(PRUnichar(' '));
975 AppendValueToString(eCSSProperty_background_image, aString);
976 aBgImage = 0;
978 aString.Append(PRUnichar(' '));
979 AppendValueToString(eCSSProperty_background_repeat, aString);
980 aBgRepeat = 0;
982 aString.Append(PRUnichar(' '));
983 AppendValueToString(eCSSProperty_background_attachment, aString);
984 aBgAttachment = 0;
986 aString.Append(PRUnichar(' '));
987 AppendValueToString(eCSSProperty_background_position, aString);
988 aBgPosition = 0;
990 AppendImportanceToString(isImportant, aString);
991 aString.AppendLiteral("; ");
995 void
996 nsCSSDeclaration::TryOverflowShorthand(nsAString & aString,
997 PRInt32 & aOverflowX,
998 PRInt32 & aOverflowY) const
1000 PRBool isImportant;
1001 if (aOverflowX && aOverflowY &&
1002 AllPropertiesSameImportance(aOverflowX, aOverflowY,
1003 0, 0, 0, isImportant)) {
1004 nsCSSValue xValue, yValue;
1005 GetValueOrImportantValue(eCSSProperty_overflow_x, xValue);
1006 GetValueOrImportantValue(eCSSProperty_overflow_y, yValue);
1007 if (xValue == yValue) {
1008 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_overflow),
1009 aString);
1010 aString.AppendLiteral(": ");
1012 AppendCSSValueToString(eCSSProperty_overflow_x, xValue, aString);
1013 AppendImportanceToString(isImportant, aString);
1014 aString.AppendLiteral("; ");
1015 aOverflowX = aOverflowY = 0;
1020 #ifdef MOZ_SVG
1021 void
1022 nsCSSDeclaration::TryMarkerShorthand(nsAString & aString,
1023 PRInt32 & aMarkerEnd,
1024 PRInt32 & aMarkerMid,
1025 PRInt32 & aMarkerStart) const
1027 PRBool isImportant;
1028 if (aMarkerEnd && aMarkerMid && aMarkerEnd &&
1029 AllPropertiesSameImportance(aMarkerEnd, aMarkerMid, aMarkerStart,
1030 0, 0, isImportant)) {
1031 nsCSSValue endValue, midValue, startValue;
1032 GetValueOrImportantValue(eCSSProperty_marker_end, endValue);
1033 GetValueOrImportantValue(eCSSProperty_marker_mid, midValue);
1034 GetValueOrImportantValue(eCSSProperty_marker_start, startValue);
1035 if (endValue == midValue && midValue == startValue) {
1036 AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_marker),
1037 aString);
1038 aString.AppendLiteral(": ");
1040 AppendCSSValueToString(eCSSProperty_marker_end, endValue, aString);
1041 AppendImportanceToString(isImportant, aString);
1042 aString.AppendLiteral("; ");
1043 aMarkerEnd = aMarkerMid = aMarkerStart = 0;
1047 #endif
1049 #define NS_CASE_OUTPUT_PROPERTY_VALUE(_prop, _index) \
1050 case _prop: \
1051 if (_index) { \
1052 AppendPropertyAndValueToString(property, aString); \
1053 _index = 0; \
1055 break;
1057 #define NS_CASE_OUTPUT_PROPERTY_VALUE_AS(_prop, _propas, _index) \
1058 case _prop: \
1059 if (_index) { \
1060 AppendPropertyAndValueToString(property, _propas, aString); \
1061 _index = 0; \
1063 break;
1065 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(_condition, _prop, _index) \
1066 case _prop: \
1067 if ((_condition) && _index) { \
1068 AppendPropertyAndValueToString(property, aString); \
1069 _index = 0; \
1071 break;
1073 #define NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(_condition, _prop, _propas, _index) \
1074 case _prop: \
1075 if ((_condition) && _index) { \
1076 AppendPropertyAndValueToString(property, _propas, aString); \
1077 _index = 0; \
1079 break;
1081 void nsCSSDeclaration::PropertyIsSet(PRInt32 & aPropertyIndex, PRInt32 aIndex, PRUint32 & aSet, PRUint32 aValue) const
1083 aPropertyIndex = aIndex + 1;
1084 aSet |= aValue;
1087 nsresult
1088 nsCSSDeclaration::ToString(nsAString& aString) const
1090 PRInt32 count = mOrder.Length();
1091 PRInt32 index;
1092 // 0 means not in the mOrder array; otherwise it's index+1
1093 PRInt32 borderTopWidth = 0, borderTopStyle = 0, borderTopColor = 0;
1094 PRInt32 borderBottomWidth = 0, borderBottomStyle = 0, borderBottomColor = 0;
1095 PRInt32 borderLeftWidth = 0, borderLeftStyle = 0, borderLeftColor = 0;
1096 PRInt32 borderRightWidth = 0, borderRightStyle = 0, borderRightColor = 0;
1097 PRInt32 borderStartWidth = 0, borderStartStyle = 0, borderStartColor = 0;
1098 PRInt32 borderEndWidth = 0, borderEndStyle = 0, borderEndColor = 0;
1099 PRInt32 marginTop = 0, marginBottom = 0, marginLeft = 0, marginRight = 0;
1100 PRInt32 paddingTop = 0, paddingBottom = 0, paddingLeft = 0, paddingRight = 0;
1101 PRInt32 bgColor = 0, bgImage = 0, bgRepeat = 0, bgAttachment = 0;
1102 PRInt32 bgPosition = 0;
1103 PRInt32 overflowX = 0, overflowY = 0;
1104 PRInt32 columnRuleWidth = 0, columnRuleStyle = 0, columnRuleColor = 0;
1105 PRUint32 borderPropertiesSet = 0, finalBorderPropertiesToSet = 0;
1106 #ifdef MOZ_SVG
1107 PRInt32 markerEnd = 0, markerMid = 0, markerStart = 0;
1108 #endif
1110 for (index = 0; index < count; index++) {
1111 nsCSSProperty property = OrderValueAt(index);
1112 switch (property) {
1113 case eCSSProperty_border_top_width:
1114 PropertyIsSet(borderTopWidth, index, borderPropertiesSet, B_BORDER_TOP_WIDTH);
1115 break;
1116 case eCSSProperty_border_bottom_width:
1117 PropertyIsSet(borderBottomWidth, index, borderPropertiesSet, B_BORDER_BOTTOM_WIDTH);
1118 break;
1119 case eCSSProperty_border_left_width_value:
1120 PropertyIsSet(borderLeftWidth, index, borderPropertiesSet, B_BORDER_LEFT_WIDTH);
1121 break;
1122 case eCSSProperty_border_right_width_value:
1123 PropertyIsSet(borderRightWidth, index, borderPropertiesSet, B_BORDER_RIGHT_WIDTH);
1124 break;
1125 case eCSSProperty_border_start_width_value:
1126 borderStartWidth = index+1;
1127 break;
1128 case eCSSProperty_border_end_width_value:
1129 borderEndWidth = index+1;
1130 break;
1132 case eCSSProperty_border_top_style:
1133 PropertyIsSet(borderTopStyle, index, borderPropertiesSet, B_BORDER_TOP_STYLE);
1134 break;
1135 case eCSSProperty_border_bottom_style:
1136 PropertyIsSet(borderBottomStyle, index, borderPropertiesSet, B_BORDER_BOTTOM_STYLE);
1137 break;
1138 case eCSSProperty_border_left_style_value:
1139 PropertyIsSet(borderLeftStyle, index, borderPropertiesSet, B_BORDER_LEFT_STYLE);
1140 break;
1141 case eCSSProperty_border_right_style_value:
1142 PropertyIsSet(borderRightStyle, index, borderPropertiesSet, B_BORDER_RIGHT_STYLE);
1143 break;
1144 case eCSSProperty_border_start_style_value:
1145 borderStartStyle = index+1;
1146 break;
1147 case eCSSProperty_border_end_style_value:
1148 borderEndStyle = index+1;
1149 break;
1151 case eCSSProperty_border_top_color:
1152 PropertyIsSet(borderTopColor, index, borderPropertiesSet, B_BORDER_TOP_COLOR);
1153 break;
1154 case eCSSProperty_border_bottom_color:
1155 PropertyIsSet(borderBottomColor, index, borderPropertiesSet, B_BORDER_BOTTOM_COLOR);
1156 break;
1157 case eCSSProperty_border_left_color_value:
1158 PropertyIsSet(borderLeftColor, index, borderPropertiesSet, B_BORDER_LEFT_COLOR);
1159 break;
1160 case eCSSProperty_border_right_color_value:
1161 PropertyIsSet(borderRightColor, index, borderPropertiesSet, B_BORDER_RIGHT_COLOR);
1162 break;
1163 case eCSSProperty_border_start_color_value:
1164 borderStartColor = index+1;
1165 break;
1166 case eCSSProperty_border_end_color_value:
1167 borderEndColor = index+1;
1168 break;
1170 case eCSSProperty_margin_top: marginTop = index+1; break;
1171 case eCSSProperty_margin_bottom: marginBottom = index+1; break;
1172 case eCSSProperty_margin_left_value: marginLeft = index+1; break;
1173 case eCSSProperty_margin_right_value: marginRight = index+1; break;
1175 case eCSSProperty_padding_top: paddingTop = index+1; break;
1176 case eCSSProperty_padding_bottom: paddingBottom = index+1; break;
1177 case eCSSProperty_padding_left_value: paddingLeft = index+1; break;
1178 case eCSSProperty_padding_right_value: paddingRight = index+1; break;
1180 case eCSSProperty_background_color: bgColor = index+1; break;
1181 case eCSSProperty_background_image: bgImage = index+1; break;
1182 case eCSSProperty_background_repeat: bgRepeat = index+1; break;
1183 case eCSSProperty_background_attachment: bgAttachment = index+1; break;
1184 case eCSSProperty_background_position: bgPosition = index+1; break;
1186 case eCSSProperty_overflow_x: overflowX = index+1; break;
1187 case eCSSProperty_overflow_y: overflowY = index+1; break;
1189 case eCSSProperty__moz_column_rule_width: columnRuleWidth = index+1; break;
1190 case eCSSProperty__moz_column_rule_style: columnRuleStyle = index+1; break;
1191 case eCSSProperty__moz_column_rule_color: columnRuleColor = index+1; break;
1193 #ifdef MOZ_SVG
1194 case eCSSProperty_marker_end: markerEnd = index+1; break;
1195 case eCSSProperty_marker_mid: markerMid = index+1; break;
1196 case eCSSProperty_marker_start: markerStart = index+1; break;
1197 #endif
1199 default: break;
1203 if (!TryBorderShorthand(aString, borderPropertiesSet,
1204 borderTopWidth, borderTopStyle, borderTopColor,
1205 borderBottomWidth, borderBottomStyle, borderBottomColor,
1206 borderLeftWidth, borderLeftStyle, borderLeftColor,
1207 borderRightWidth, borderRightStyle, borderRightColor)) {
1208 PRUint32 borderPropertiesToSet = 0;
1209 if ((borderPropertiesSet & B_BORDER_STYLE) != B_BORDER_STYLE ||
1210 !TryFourSidesShorthand(aString, eCSSProperty_border_style,
1211 borderTopStyle, borderBottomStyle,
1212 borderLeftStyle, borderRightStyle,
1213 PR_FALSE)) {
1214 borderPropertiesToSet |= B_BORDER_STYLE;
1216 if ((borderPropertiesSet & B_BORDER_COLOR) != B_BORDER_COLOR ||
1217 !TryFourSidesShorthand(aString, eCSSProperty_border_color,
1218 borderTopColor, borderBottomColor,
1219 borderLeftColor, borderRightColor,
1220 PR_FALSE)) {
1221 borderPropertiesToSet |= B_BORDER_COLOR;
1223 if ((borderPropertiesSet & B_BORDER_WIDTH) != B_BORDER_WIDTH ||
1224 !TryFourSidesShorthand(aString, eCSSProperty_border_width,
1225 borderTopWidth, borderBottomWidth,
1226 borderLeftWidth, borderRightWidth,
1227 PR_FALSE)) {
1228 borderPropertiesToSet |= B_BORDER_WIDTH;
1230 borderPropertiesToSet &= borderPropertiesSet;
1231 if (borderPropertiesToSet) {
1232 if ((borderPropertiesSet & B_BORDER_TOP) != B_BORDER_TOP ||
1233 !TryBorderSideShorthand(aString, eCSSProperty_border_top,
1234 borderTopWidth, borderTopStyle, borderTopColor)) {
1235 finalBorderPropertiesToSet |= B_BORDER_TOP;
1237 if ((borderPropertiesSet & B_BORDER_LEFT) != B_BORDER_LEFT ||
1238 !TryBorderSideShorthand(aString, eCSSProperty_border_left,
1239 borderLeftWidth, borderLeftStyle, borderLeftColor)) {
1240 finalBorderPropertiesToSet |= B_BORDER_LEFT;
1242 if ((borderPropertiesSet & B_BORDER_RIGHT) != B_BORDER_RIGHT ||
1243 !TryBorderSideShorthand(aString, eCSSProperty_border_right,
1244 borderRightWidth, borderRightStyle, borderRightColor)) {
1245 finalBorderPropertiesToSet |= B_BORDER_RIGHT;
1247 if ((borderPropertiesSet & B_BORDER_BOTTOM) != B_BORDER_BOTTOM ||
1248 !TryBorderSideShorthand(aString, eCSSProperty_border_bottom,
1249 borderBottomWidth, borderBottomStyle, borderBottomColor)) {
1250 finalBorderPropertiesToSet |= B_BORDER_BOTTOM;
1252 finalBorderPropertiesToSet &= borderPropertiesToSet;
1256 TryFourSidesShorthand(aString, eCSSProperty_margin,
1257 marginTop, marginBottom,
1258 marginLeft, marginRight,
1259 PR_TRUE);
1260 TryFourSidesShorthand(aString, eCSSProperty_padding,
1261 paddingTop, paddingBottom,
1262 paddingLeft, paddingRight,
1263 PR_TRUE);
1264 TryBackgroundShorthand(aString,
1265 bgColor, bgImage, bgRepeat, bgAttachment,
1266 bgPosition);
1267 TryOverflowShorthand(aString, overflowX, overflowY);
1268 #ifdef MOZ_SVG
1269 TryMarkerShorthand(aString, markerEnd, markerMid, markerStart);
1270 #endif
1272 if (columnRuleColor && columnRuleStyle && columnRuleWidth) {
1273 TryBorderSideShorthand(aString, eCSSProperty__moz_column_rule,
1274 columnRuleWidth, columnRuleStyle, columnRuleColor);
1275 columnRuleWidth = columnRuleStyle = columnRuleColor = 0;
1278 // FIXME The order of the declarations should depend on the *-source
1279 // properties.
1280 if (borderStartWidth && borderStartStyle && borderStartColor &&
1281 TryBorderSideShorthand(aString, eCSSProperty_border_start,
1282 borderStartWidth, borderStartStyle, borderStartColor))
1283 borderStartWidth = borderStartStyle = borderStartColor = 0;
1284 if (borderEndWidth && borderEndStyle && borderEndColor &&
1285 TryBorderSideShorthand(aString, eCSSProperty_border_end,
1286 borderEndWidth, borderEndStyle, borderEndColor))
1287 borderEndWidth = borderEndStyle = borderEndColor = 0;
1289 for (index = 0; index < count; index++) {
1290 nsCSSProperty property = OrderValueAt(index);
1291 switch (property) {
1293 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_STYLE,
1294 eCSSProperty_border_top_style, borderTopStyle)
1295 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_STYLE,
1296 eCSSProperty_border_left_style_value,
1297 eCSSProperty_border_left_style, borderLeftStyle)
1298 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_STYLE,
1299 eCSSProperty_border_right_style_value,
1300 eCSSProperty_border_right_style, borderRightStyle)
1301 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_STYLE,
1302 eCSSProperty_border_bottom_style, borderBottomStyle)
1303 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_style_value,
1304 eCSSProperty_border_start_style, borderStartStyle)
1305 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_style_value,
1306 eCSSProperty_border_end_style, borderEndStyle)
1308 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_COLOR,
1309 eCSSProperty_border_top_color, borderTopColor)
1310 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_COLOR,
1311 eCSSProperty_border_left_color_value,
1312 eCSSProperty_border_left_color, borderLeftColor)
1313 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_COLOR,
1314 eCSSProperty_border_right_color_value,
1315 eCSSProperty_border_right_color, borderRightColor)
1316 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_COLOR,
1317 eCSSProperty_border_bottom_color, borderBottomColor)
1318 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_color_value,
1319 eCSSProperty_border_start_color, borderStartColor)
1320 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_color_value,
1321 eCSSProperty_border_end_color, borderEndColor)
1323 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_TOP_WIDTH,
1324 eCSSProperty_border_top_width, borderTopWidth)
1325 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_LEFT_WIDTH,
1326 eCSSProperty_border_left_width_value,
1327 eCSSProperty_border_left_width, borderLeftWidth)
1328 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE_AS(finalBorderPropertiesToSet & B_BORDER_RIGHT_WIDTH,
1329 eCSSProperty_border_right_width_value,
1330 eCSSProperty_border_right_width, borderRightWidth)
1331 NS_CASE_CONDITIONAL_OUTPUT_PROPERTY_VALUE(finalBorderPropertiesToSet & B_BORDER_BOTTOM_WIDTH,
1332 eCSSProperty_border_bottom_width, borderBottomWidth)
1333 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_start_width_value,
1334 eCSSProperty_border_start_width, borderStartWidth)
1335 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_border_end_width_value,
1336 eCSSProperty_border_end_width, borderEndWidth)
1338 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_top, marginTop)
1339 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_margin_bottom, marginBottom)
1340 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_left_value,
1341 eCSSProperty_margin_left, marginLeft)
1342 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_margin_right_value,
1343 eCSSProperty_margin_right, marginRight)
1345 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_top, paddingTop)
1346 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_padding_bottom, paddingBottom)
1347 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_left_value,
1348 eCSSProperty_padding_left, paddingLeft)
1349 NS_CASE_OUTPUT_PROPERTY_VALUE_AS(eCSSProperty_padding_right_value,
1350 eCSSProperty_padding_right, paddingRight)
1352 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_color, bgColor)
1353 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_image, bgImage)
1354 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_repeat, bgRepeat)
1355 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_attachment, bgAttachment)
1356 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_background_position, bgPosition)
1358 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_x, overflowX)
1359 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_y, overflowY)
1361 #ifdef MOZ_SVG
1362 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_end, markerEnd)
1363 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_mid, markerMid)
1364 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_start, markerStart)
1365 #endif
1367 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_width, columnRuleWidth)
1368 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_style, columnRuleStyle)
1369 NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty__moz_column_rule_color, columnRuleColor)
1371 case eCSSProperty_margin_left_ltr_source:
1372 case eCSSProperty_margin_left_rtl_source:
1373 case eCSSProperty_margin_right_ltr_source:
1374 case eCSSProperty_margin_right_rtl_source:
1375 case eCSSProperty_padding_left_ltr_source:
1376 case eCSSProperty_padding_left_rtl_source:
1377 case eCSSProperty_padding_right_ltr_source:
1378 case eCSSProperty_padding_right_rtl_source:
1379 case eCSSProperty_border_left_color_ltr_source:
1380 case eCSSProperty_border_left_color_rtl_source:
1381 case eCSSProperty_border_left_style_ltr_source:
1382 case eCSSProperty_border_left_style_rtl_source:
1383 case eCSSProperty_border_left_width_ltr_source:
1384 case eCSSProperty_border_left_width_rtl_source:
1385 case eCSSProperty_border_right_color_ltr_source:
1386 case eCSSProperty_border_right_color_rtl_source:
1387 case eCSSProperty_border_right_style_ltr_source:
1388 case eCSSProperty_border_right_style_rtl_source:
1389 case eCSSProperty_border_right_width_ltr_source:
1390 case eCSSProperty_border_right_width_rtl_source:
1391 break;
1393 case eCSSProperty_margin_start_value:
1394 AppendPropertyAndValueToString(property, eCSSProperty_margin_start,
1395 aString);
1396 break;
1397 case eCSSProperty_margin_end_value:
1398 AppendPropertyAndValueToString(property, eCSSProperty_margin_end,
1399 aString);
1400 break;
1401 case eCSSProperty_padding_start_value:
1402 AppendPropertyAndValueToString(property, eCSSProperty_padding_start,
1403 aString);
1404 break;
1405 case eCSSProperty_padding_end_value:
1406 AppendPropertyAndValueToString(property, eCSSProperty_padding_end,
1407 aString);
1408 break;
1410 default:
1411 if (0 <= property) {
1412 AppendPropertyAndValueToString(property, aString);
1414 break;
1417 if (! aString.IsEmpty()) {
1418 // if the string is not empty, we have a trailing whitespace we should remove
1419 aString.Truncate(aString.Length() - 1);
1421 return NS_OK;
1424 #ifdef DEBUG
1425 void nsCSSDeclaration::List(FILE* out, PRInt32 aIndent) const
1427 for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
1429 fputs("{ ", out);
1430 nsAutoString s;
1431 ToString(s);
1432 fputs(NS_ConvertUTF16toUTF8(s).get(), out);
1433 fputs("}", out);
1435 #endif
1437 nsresult
1438 nsCSSDeclaration::GetNthProperty(PRUint32 aIndex, nsAString& aReturn) const
1440 aReturn.Truncate();
1441 if (aIndex < mOrder.Length()) {
1442 nsCSSProperty property = OrderValueAt(aIndex);
1443 if (0 <= property) {
1444 AppendASCIItoUTF16(nsCSSProps::GetStringValue(property), aReturn);
1448 return NS_OK;
1451 nsCSSDeclaration*
1452 nsCSSDeclaration::Clone() const
1454 return new nsCSSDeclaration(*this);
1457 PRBool
1458 nsCSSDeclaration::InitializeEmpty()
1460 NS_ASSERTION(!mData && !mImportantData, "already initialized");
1461 mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
1462 return mData != nsnull;