CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / layout / style / nsROCSSPrimitiveValue.cpp
blob00e7a8b3044a173cd15ad02f9b8123007c9983c1
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):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /* DOM object representing values in DOM computed style */
40 #include "nsROCSSPrimitiveValue.h"
42 #include "nsPresContext.h"
43 #include "nsStyleUtil.h"
44 #include "nsDOMCSSRGBColor.h"
45 #include "nsIDOMRect.h"
47 nsROCSSPrimitiveValue::nsROCSSPrimitiveValue()
48 : mType(CSS_PX)
50 mValue.mAppUnits = 0;
54 nsROCSSPrimitiveValue::~nsROCSSPrimitiveValue()
56 Reset();
59 NS_IMPL_ADDREF(nsROCSSPrimitiveValue)
60 NS_IMPL_RELEASE(nsROCSSPrimitiveValue)
63 DOMCI_DATA(ROCSSPrimitiveValue, nsROCSSPrimitiveValue)
65 // QueryInterface implementation for nsROCSSPrimitiveValue
66 NS_INTERFACE_MAP_BEGIN(nsROCSSPrimitiveValue)
67 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPrimitiveValue)
68 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSValue)
69 NS_INTERFACE_MAP_ENTRY(nsISupports)
70 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ROCSSPrimitiveValue)
71 NS_INTERFACE_MAP_END
74 // nsIDOMCSSValue
77 NS_IMETHODIMP
78 nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
80 nsAutoString tmpStr;
81 aCssText.Truncate();
82 nsresult result = NS_OK;
84 switch (mType) {
85 case CSS_PX :
87 float val = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
88 tmpStr.AppendFloat(val);
89 tmpStr.AppendLiteral("px");
90 break;
92 case CSS_IDENT :
94 AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword),
95 tmpStr);
96 break;
98 case CSS_STRING :
99 case CSS_COUNTER : /* FIXME: COUNTER should use an object */
101 tmpStr.Append(mValue.mString);
102 break;
104 case CSS_URI :
106 if (mValue.mURI) {
107 nsCAutoString specUTF8;
108 mValue.mURI->GetSpec(specUTF8);
110 tmpStr.AssignLiteral("url(");
111 nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8),
112 tmpStr);
113 tmpStr.AppendLiteral(")");
114 } else {
115 // XXXldb Any better ideas? It's good to have something that
116 // doesn't parse so that things round-trip "correctly".
117 tmpStr.Assign(NS_LITERAL_STRING("url(invalid-url:)"));
119 break;
121 case CSS_ATTR :
123 tmpStr.AppendLiteral("attr(");
124 tmpStr.Append(mValue.mString);
125 tmpStr.Append(PRUnichar(')'));
126 break;
128 case CSS_PERCENTAGE :
130 tmpStr.AppendFloat(mValue.mFloat * 100);
131 tmpStr.Append(PRUnichar('%'));
132 break;
134 case CSS_NUMBER :
136 tmpStr.AppendFloat(mValue.mFloat);
137 break;
139 case CSS_RECT :
141 NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
142 NS_NAMED_LITERAL_STRING(comma, ", ");
143 nsCOMPtr<nsIDOMCSSPrimitiveValue> sideCSSValue;
144 nsAutoString sideValue;
145 tmpStr.AssignLiteral("rect(");
146 // get the top
147 result = mValue.mRect->GetTop(getter_AddRefs(sideCSSValue));
148 if (NS_FAILED(result))
149 break;
150 result = sideCSSValue->GetCssText(sideValue);
151 if (NS_FAILED(result))
152 break;
153 tmpStr.Append(sideValue + comma);
154 // get the right
155 result = mValue.mRect->GetRight(getter_AddRefs(sideCSSValue));
156 if (NS_FAILED(result))
157 break;
158 result = sideCSSValue->GetCssText(sideValue);
159 if (NS_FAILED(result))
160 break;
161 tmpStr.Append(sideValue + comma);
162 // get the bottom
163 result = mValue.mRect->GetBottom(getter_AddRefs(sideCSSValue));
164 if (NS_FAILED(result))
165 break;
166 result = sideCSSValue->GetCssText(sideValue);
167 if (NS_FAILED(result))
168 break;
169 tmpStr.Append(sideValue + comma);
170 // get the left
171 result = mValue.mRect->GetLeft(getter_AddRefs(sideCSSValue));
172 if (NS_FAILED(result))
173 break;
174 result = sideCSSValue->GetCssText(sideValue);
175 if (NS_FAILED(result))
176 break;
177 tmpStr.Append(sideValue + NS_LITERAL_STRING(")"));
178 break;
180 case CSS_RGBCOLOR :
182 NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
183 NS_NAMED_LITERAL_STRING(comma, ", ");
184 nsCOMPtr<nsIDOMCSSPrimitiveValue> colorCSSValue;
185 nsAutoString colorValue;
186 if (mValue.mColor->HasAlpha())
187 tmpStr.AssignLiteral("rgba(");
188 else
189 tmpStr.AssignLiteral("rgb(");
191 // get the red component
192 result = mValue.mColor->GetRed(getter_AddRefs(colorCSSValue));
193 if (NS_FAILED(result))
194 break;
195 result = colorCSSValue->GetCssText(colorValue);
196 if (NS_FAILED(result))
197 break;
198 tmpStr.Append(colorValue + comma);
200 // get the green component
201 result = mValue.mColor->GetGreen(getter_AddRefs(colorCSSValue));
202 if (NS_FAILED(result))
203 break;
204 result = colorCSSValue->GetCssText(colorValue);
205 if (NS_FAILED(result))
206 break;
207 tmpStr.Append(colorValue + comma);
209 // get the blue component
210 result = mValue.mColor->GetBlue(getter_AddRefs(colorCSSValue));
211 if (NS_FAILED(result))
212 break;
213 result = colorCSSValue->GetCssText(colorValue);
214 if (NS_FAILED(result))
215 break;
216 tmpStr.Append(colorValue);
218 if (mValue.mColor->HasAlpha()) {
219 // get the alpha component
220 result = mValue.mColor->GetAlpha(getter_AddRefs(colorCSSValue));
221 if (NS_FAILED(result))
222 break;
223 result = colorCSSValue->GetCssText(colorValue);
224 if (NS_FAILED(result))
225 break;
226 tmpStr.Append(comma + colorValue);
229 tmpStr.Append(NS_LITERAL_STRING(")"));
231 break;
233 case CSS_S :
235 tmpStr.AppendFloat(mValue.mFloat);
236 tmpStr.AppendLiteral("s");
237 break;
239 case CSS_CM :
240 case CSS_MM :
241 case CSS_IN :
242 case CSS_PT :
243 case CSS_PC :
244 case CSS_UNKNOWN :
245 case CSS_EMS :
246 case CSS_EXS :
247 case CSS_DEG :
248 case CSS_RAD :
249 case CSS_GRAD :
250 case CSS_MS :
251 case CSS_HZ :
252 case CSS_KHZ :
253 case CSS_DIMENSION :
254 NS_ERROR("We have a bogus value set. This should not happen");
255 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
258 if (NS_SUCCEEDED(result)) {
259 aCssText.Assign(tmpStr);
262 return NS_OK;
266 NS_IMETHODIMP
267 nsROCSSPrimitiveValue::SetCssText(const nsAString& aCssText)
269 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
273 NS_IMETHODIMP
274 nsROCSSPrimitiveValue::GetCssValueType(PRUint16* aValueType)
276 NS_ENSURE_ARG_POINTER(aValueType);
277 *aValueType = nsIDOMCSSValue::CSS_PRIMITIVE_VALUE;
278 return NS_OK;
282 // nsIDOMCSSPrimitiveValue
284 NS_IMETHODIMP
285 nsROCSSPrimitiveValue::GetPrimitiveType(PRUint16* aPrimitiveType)
287 NS_ENSURE_ARG_POINTER(aPrimitiveType);
288 *aPrimitiveType = mType;
290 return NS_OK;
294 NS_IMETHODIMP
295 nsROCSSPrimitiveValue::SetFloatValue(PRUint16 aUnitType, float aFloatValue)
297 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
301 NS_IMETHODIMP
302 nsROCSSPrimitiveValue::GetFloatValue(PRUint16 aUnitType, float* aReturn)
304 NS_ENSURE_ARG_POINTER(aReturn);
305 *aReturn = 0;
307 switch(aUnitType) {
308 case CSS_PX :
309 if (mType != CSS_PX)
310 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
311 *aReturn = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
312 break;
313 case CSS_CM :
314 if (mType != CSS_PX)
315 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
316 *aReturn = mValue.mAppUnits * CM_PER_INCH_FLOAT /
317 nsPresContext::AppUnitsPerCSSInch();
318 break;
319 case CSS_MM :
320 if (mType != CSS_PX)
321 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
322 *aReturn = mValue.mAppUnits * MM_PER_INCH_FLOAT /
323 nsPresContext::AppUnitsPerCSSInch();
324 break;
325 case CSS_IN :
326 if (mType != CSS_PX)
327 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
328 *aReturn = mValue.mAppUnits / nsPresContext::AppUnitsPerCSSInch();
329 break;
330 case CSS_PT :
331 if (mType != CSS_PX)
332 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
333 *aReturn = mValue.mAppUnits * POINTS_PER_INCH_FLOAT /
334 nsPresContext::AppUnitsPerCSSInch();
335 break;
336 case CSS_PC :
337 if (mType != CSS_PX)
338 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
339 *aReturn = mValue.mAppUnits * 6.0f /
340 nsPresContext::AppUnitsPerCSSInch();
341 break;
342 case CSS_PERCENTAGE :
343 if (mType != CSS_PERCENTAGE)
344 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
345 *aReturn = mValue.mFloat * 100;
346 break;
347 case CSS_NUMBER :
348 if (mType != CSS_NUMBER)
349 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
350 *aReturn = mValue.mFloat;
351 break;
352 case CSS_UNKNOWN :
353 case CSS_EMS :
354 case CSS_EXS :
355 case CSS_DEG :
356 case CSS_RAD :
357 case CSS_GRAD :
358 case CSS_MS :
359 case CSS_S :
360 case CSS_HZ :
361 case CSS_KHZ :
362 case CSS_DIMENSION :
363 case CSS_STRING :
364 case CSS_URI :
365 case CSS_IDENT :
366 case CSS_ATTR :
367 case CSS_COUNTER :
368 case CSS_RECT :
369 case CSS_RGBCOLOR :
370 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
373 return NS_OK;
377 NS_IMETHODIMP
378 nsROCSSPrimitiveValue::SetStringValue(PRUint16 aStringType,
379 const nsAString& aStringValue)
381 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
385 NS_IMETHODIMP
386 nsROCSSPrimitiveValue::GetStringValue(nsAString& aReturn)
388 switch (mType) {
389 case CSS_IDENT:
390 CopyUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword), aReturn);
391 break;
392 case CSS_STRING:
393 case CSS_ATTR:
394 aReturn.Assign(mValue.mString);
395 break;
396 case CSS_URI: {
397 nsCAutoString spec;
398 if (mValue.mURI)
399 mValue.mURI->GetSpec(spec);
400 CopyUTF8toUTF16(spec, aReturn);
401 } break;
402 default:
403 aReturn.Truncate();
404 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
406 return NS_OK;
410 NS_IMETHODIMP
411 nsROCSSPrimitiveValue::GetCounterValue(nsIDOMCounter** aReturn)
413 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
417 NS_IMETHODIMP
418 nsROCSSPrimitiveValue::GetRectValue(nsIDOMRect** aReturn)
420 if (mType != CSS_RECT) {
421 *aReturn = nsnull;
422 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
424 NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
425 NS_ADDREF(*aReturn = mValue.mRect);
426 return NS_OK;
430 NS_IMETHODIMP
431 nsROCSSPrimitiveValue::GetRGBColorValue(nsIDOMRGBColor** aReturn)
433 if (mType != CSS_RGBCOLOR) {
434 *aReturn = nsnull;
435 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
437 NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
438 NS_ADDREF(*aReturn = mValue.mColor);
439 return NS_OK;
442 void
443 nsROCSSPrimitiveValue::SetNumber(float aValue)
445 Reset();
446 mValue.mFloat = aValue;
447 mType = CSS_NUMBER;
450 void
451 nsROCSSPrimitiveValue::SetNumber(PRInt32 aValue)
453 Reset();
454 mValue.mFloat = float(aValue);
455 mType = CSS_NUMBER;
458 void
459 nsROCSSPrimitiveValue::SetNumber(PRUint32 aValue)
461 Reset();
462 mValue.mFloat = float(aValue);
463 mType = CSS_NUMBER;
466 void
467 nsROCSSPrimitiveValue::SetPercent(float aValue)
469 Reset();
470 mValue.mFloat = aValue;
471 mType = CSS_PERCENTAGE;
474 void
475 nsROCSSPrimitiveValue::SetAppUnits(nscoord aValue)
477 Reset();
478 mValue.mAppUnits = aValue;
479 mType = CSS_PX;
482 void
483 nsROCSSPrimitiveValue::SetAppUnits(float aValue)
485 SetAppUnits(NSToCoordRound(aValue));
488 void
489 nsROCSSPrimitiveValue::SetIdent(nsCSSKeyword aKeyword)
491 NS_PRECONDITION(aKeyword != eCSSKeyword_UNKNOWN &&
492 0 <= aKeyword && aKeyword < eCSSKeyword_COUNT,
493 "bad keyword");
494 Reset();
495 mValue.mKeyword = aKeyword;
496 mType = CSS_IDENT;
499 // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
500 void
501 nsROCSSPrimitiveValue::SetString(const nsACString& aString, PRUint16 aType)
503 Reset();
504 mValue.mString = ToNewUnicode(aString);
505 if (mValue.mString) {
506 mType = aType;
507 } else {
508 // XXXcaa We should probably let the caller know we are out of memory
509 mType = CSS_UNKNOWN;
513 // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
514 void
515 nsROCSSPrimitiveValue::SetString(const nsAString& aString, PRUint16 aType)
517 Reset();
518 mValue.mString = ToNewUnicode(aString);
519 if (mValue.mString) {
520 mType = aType;
521 } else {
522 // XXXcaa We should probably let the caller know we are out of memory
523 mType = CSS_UNKNOWN;
527 void
528 nsROCSSPrimitiveValue::SetURI(nsIURI *aURI)
530 Reset();
531 mValue.mURI = aURI;
532 NS_IF_ADDREF(mValue.mURI);
533 mType = CSS_URI;
536 void
537 nsROCSSPrimitiveValue::SetColor(nsDOMCSSRGBColor* aColor)
539 NS_PRECONDITION(aColor, "Null RGBColor being set!");
540 Reset();
541 mValue.mColor = aColor;
542 if (mValue.mColor) {
543 NS_ADDREF(mValue.mColor);
544 mType = CSS_RGBCOLOR;
546 else {
547 mType = CSS_UNKNOWN;
551 void
552 nsROCSSPrimitiveValue::SetRect(nsIDOMRect* aRect)
554 NS_PRECONDITION(aRect, "Null rect being set!");
555 Reset();
556 mValue.mRect = aRect;
557 if (mValue.mRect) {
558 NS_ADDREF(mValue.mRect);
559 mType = CSS_RECT;
561 else {
562 mType = CSS_UNKNOWN;
566 void
567 nsROCSSPrimitiveValue::SetTime(float aValue)
569 Reset();
570 mValue.mFloat = aValue;
571 mType = CSS_S;
574 void
575 nsROCSSPrimitiveValue::Reset()
577 switch (mType) {
578 case CSS_IDENT:
579 break;
580 case CSS_STRING:
581 case CSS_ATTR:
582 case CSS_COUNTER: // FIXME: Counter should use an object
583 NS_ASSERTION(mValue.mString, "Null string should never happen");
584 nsMemory::Free(mValue.mString);
585 mValue.mString = nsnull;
586 break;
587 case CSS_URI:
588 NS_IF_RELEASE(mValue.mURI);
589 break;
590 case CSS_RECT:
591 NS_ASSERTION(mValue.mRect, "Null Rect should never happen");
592 NS_RELEASE(mValue.mRect);
593 break;
594 case CSS_RGBCOLOR:
595 NS_ASSERTION(mValue.mColor, "Null RGBColor should never happen");
596 NS_RELEASE(mValue.mColor);
597 break;