Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* DOM object representing values in DOM computed style */
8 #include "nsROCSSPrimitiveValue.h"
10 #include "mozilla/dom/CSSPrimitiveValueBinding.h"
11 #include "nsPresContext.h"
12 #include "nsStyleUtil.h"
13 #include "nsDOMCSSRGBColor.h"
14 #include "nsDOMCSSRect.h"
15 #include "nsIURI.h"
16 #include "nsError.h"
18 using namespace mozilla;
20 nsROCSSPrimitiveValue::nsROCSSPrimitiveValue()
21 : CSSValue(), mType(CSS_PX)
22 {
23 mValue.mAppUnits = 0;
24 SetIsDOMBinding();
25 }
28 nsROCSSPrimitiveValue::~nsROCSSPrimitiveValue()
29 {
30 Reset();
31 }
33 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsROCSSPrimitiveValue)
34 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsROCSSPrimitiveValue)
37 // QueryInterface implementation for nsROCSSPrimitiveValue
38 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsROCSSPrimitiveValue)
39 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
40 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPrimitiveValue)
41 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSValue)
42 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, CSSValue)
43 NS_INTERFACE_MAP_END
45 NS_IMPL_CYCLE_COLLECTION_CLASS(nsROCSSPrimitiveValue)
47 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsROCSSPrimitiveValue)
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsROCSSPrimitiveValue)
50 if (tmp->mType == CSS_URI) {
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mValue.mURI)
52 } else if (tmp->mType == CSS_RGBCOLOR) {
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mValue.mColor)
54 } else if (tmp->mType == CSS_RECT) {
55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mValue.mRect)
56 }
57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
58 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
60 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsROCSSPrimitiveValue)
61 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
62 tmp->Reset();
63 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
65 JSObject*
66 nsROCSSPrimitiveValue::WrapObject(JSContext *cx)
67 {
68 return dom::CSSPrimitiveValueBinding::Wrap(cx, this);
69 }
71 // nsIDOMCSSValue
74 NS_IMETHODIMP
75 nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
76 {
77 nsAutoString tmpStr;
78 aCssText.Truncate();
79 nsresult result = NS_OK;
81 switch (mType) {
82 case CSS_PX :
83 {
84 float val = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
85 nsStyleUtil::AppendCSSNumber(val, tmpStr);
86 tmpStr.AppendLiteral("px");
87 break;
88 }
89 case CSS_IDENT :
90 {
91 AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword),
92 tmpStr);
93 break;
94 }
95 case CSS_STRING :
96 case CSS_COUNTER : /* FIXME: COUNTER should use an object */
97 {
98 tmpStr.Append(mValue.mString);
99 break;
100 }
101 case CSS_URI :
102 {
103 if (mValue.mURI) {
104 nsAutoCString specUTF8;
105 mValue.mURI->GetSpec(specUTF8);
107 tmpStr.AssignLiteral("url(");
108 nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8),
109 tmpStr);
110 tmpStr.AppendLiteral(")");
111 } else {
112 // http://dev.w3.org/csswg/css3-values/#attr defines
113 // 'about:invalid' as the default value for url attributes,
114 // so let's also use it here as the default computed value
115 // for invalid URLs.
116 tmpStr.Assign(NS_LITERAL_STRING("url(about:invalid)"));
117 }
118 break;
119 }
120 case CSS_ATTR :
121 {
122 tmpStr.AppendLiteral("attr(");
123 tmpStr.Append(mValue.mString);
124 tmpStr.Append(char16_t(')'));
125 break;
126 }
127 case CSS_PERCENTAGE :
128 {
129 nsStyleUtil::AppendCSSNumber(mValue.mFloat * 100, tmpStr);
130 tmpStr.Append(char16_t('%'));
131 break;
132 }
133 case CSS_NUMBER :
134 {
135 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
136 break;
137 }
138 case CSS_NUMBER_INT32 :
139 {
140 tmpStr.AppendInt(mValue.mInt32);
141 break;
142 }
143 case CSS_NUMBER_UINT32 :
144 {
145 tmpStr.AppendInt(mValue.mUint32);
146 break;
147 }
148 case CSS_DEG :
149 {
150 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
151 tmpStr.AppendLiteral("deg");
152 break;
153 }
154 case CSS_GRAD :
155 {
156 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
157 tmpStr.AppendLiteral("grad");
158 break;
159 }
160 case CSS_RAD :
161 {
162 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
163 tmpStr.AppendLiteral("rad");
164 break;
165 }
166 case CSS_TURN :
167 {
168 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
169 tmpStr.AppendLiteral("turn");
170 break;
171 }
172 case CSS_RECT :
173 {
174 NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
175 NS_NAMED_LITERAL_STRING(comma, ", ");
176 nsCOMPtr<nsIDOMCSSPrimitiveValue> sideCSSValue;
177 nsAutoString sideValue;
178 tmpStr.AssignLiteral("rect(");
179 // get the top
180 result = mValue.mRect->GetTop(getter_AddRefs(sideCSSValue));
181 if (NS_FAILED(result))
182 break;
183 result = sideCSSValue->GetCssText(sideValue);
184 if (NS_FAILED(result))
185 break;
186 tmpStr.Append(sideValue + comma);
187 // get the right
188 result = mValue.mRect->GetRight(getter_AddRefs(sideCSSValue));
189 if (NS_FAILED(result))
190 break;
191 result = sideCSSValue->GetCssText(sideValue);
192 if (NS_FAILED(result))
193 break;
194 tmpStr.Append(sideValue + comma);
195 // get the bottom
196 result = mValue.mRect->GetBottom(getter_AddRefs(sideCSSValue));
197 if (NS_FAILED(result))
198 break;
199 result = sideCSSValue->GetCssText(sideValue);
200 if (NS_FAILED(result))
201 break;
202 tmpStr.Append(sideValue + comma);
203 // get the left
204 result = mValue.mRect->GetLeft(getter_AddRefs(sideCSSValue));
205 if (NS_FAILED(result))
206 break;
207 result = sideCSSValue->GetCssText(sideValue);
208 if (NS_FAILED(result))
209 break;
210 tmpStr.Append(sideValue + NS_LITERAL_STRING(")"));
211 break;
212 }
213 case CSS_RGBCOLOR :
214 {
215 NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
216 ErrorResult error;
217 NS_NAMED_LITERAL_STRING(comma, ", ");
218 nsAutoString colorValue;
219 if (mValue.mColor->HasAlpha())
220 tmpStr.AssignLiteral("rgba(");
221 else
222 tmpStr.AssignLiteral("rgb(");
224 // get the red component
225 mValue.mColor->Red()->GetCssText(colorValue, error);
226 if (error.Failed())
227 break;
228 tmpStr.Append(colorValue + comma);
230 // get the green component
231 mValue.mColor->Green()->GetCssText(colorValue, error);
232 if (error.Failed())
233 break;
234 tmpStr.Append(colorValue + comma);
236 // get the blue component
237 mValue.mColor->Blue()->GetCssText(colorValue, error);
238 if (error.Failed())
239 break;
240 tmpStr.Append(colorValue);
242 if (mValue.mColor->HasAlpha()) {
243 // get the alpha component
244 mValue.mColor->Alpha()->GetCssText(colorValue, error);
245 if (error.Failed())
246 break;
247 tmpStr.Append(comma + colorValue);
248 }
250 tmpStr.Append(NS_LITERAL_STRING(")"));
252 break;
253 }
254 case CSS_S :
255 {
256 nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr);
257 tmpStr.AppendLiteral("s");
258 break;
259 }
260 case CSS_CM :
261 case CSS_MM :
262 case CSS_IN :
263 case CSS_PT :
264 case CSS_PC :
265 case CSS_UNKNOWN :
266 case CSS_EMS :
267 case CSS_EXS :
268 case CSS_MS :
269 case CSS_HZ :
270 case CSS_KHZ :
271 case CSS_DIMENSION :
272 NS_ERROR("We have a bogus value set. This should not happen");
273 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
274 }
276 if (NS_SUCCEEDED(result)) {
277 aCssText.Assign(tmpStr);
278 }
280 return NS_OK;
281 }
283 void
284 nsROCSSPrimitiveValue::GetCssText(nsString& aText, ErrorResult& aRv)
285 {
286 aRv = GetCssText(aText);
287 }
289 NS_IMETHODIMP
290 nsROCSSPrimitiveValue::SetCssText(const nsAString& aCssText)
291 {
292 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
293 }
295 void
296 nsROCSSPrimitiveValue::SetCssText(const nsAString& aText, ErrorResult& aRv)
297 {
298 aRv = SetCssText(aText);
299 }
302 NS_IMETHODIMP
303 nsROCSSPrimitiveValue::GetCssValueType(uint16_t* aValueType)
304 {
305 NS_ENSURE_ARG_POINTER(aValueType);
306 *aValueType = nsIDOMCSSValue::CSS_PRIMITIVE_VALUE;
307 return NS_OK;
308 }
310 uint16_t
311 nsROCSSPrimitiveValue::CssValueType() const
312 {
313 return nsIDOMCSSValue::CSS_PRIMITIVE_VALUE;
314 }
317 // nsIDOMCSSPrimitiveValue
319 NS_IMETHODIMP
320 nsROCSSPrimitiveValue::GetPrimitiveType(uint16_t* aPrimitiveType)
321 {
322 NS_ENSURE_ARG_POINTER(aPrimitiveType);
323 *aPrimitiveType = PrimitiveType();
325 return NS_OK;
326 }
329 NS_IMETHODIMP
330 nsROCSSPrimitiveValue::SetFloatValue(uint16_t aUnitType, float aFloatValue)
331 {
332 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
333 }
335 void
336 nsROCSSPrimitiveValue::SetFloatValue(uint16_t aType, float aVal,
337 ErrorResult& aRv)
338 {
339 aRv = SetFloatValue(aType, aVal);
340 }
342 float
343 nsROCSSPrimitiveValue::GetFloatValue(uint16_t aUnitType, ErrorResult& aRv)
344 {
345 switch(aUnitType) {
346 case CSS_PX :
347 if (mType == CSS_PX) {
348 return nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
349 }
351 break;
352 case CSS_CM :
353 if (mType == CSS_PX) {
354 return mValue.mAppUnits * CM_PER_INCH_FLOAT /
355 nsPresContext::AppUnitsPerCSSInch();
356 }
358 break;
359 case CSS_MM :
360 if (mType == CSS_PX) {
361 return mValue.mAppUnits * MM_PER_INCH_FLOAT /
362 nsPresContext::AppUnitsPerCSSInch();
363 }
365 break;
366 case CSS_IN :
367 if (mType == CSS_PX) {
368 return mValue.mAppUnits / nsPresContext::AppUnitsPerCSSInch();
369 }
371 break;
372 case CSS_PT :
373 if (mType == CSS_PX) {
374 return mValue.mAppUnits * POINTS_PER_INCH_FLOAT /
375 nsPresContext::AppUnitsPerCSSInch();
376 }
378 break;
379 case CSS_PC :
380 if (mType == CSS_PX) {
381 return mValue.mAppUnits * 6.0f /
382 nsPresContext::AppUnitsPerCSSInch();
383 }
385 break;
386 case CSS_PERCENTAGE :
387 if (mType == CSS_PERCENTAGE) {
388 return mValue.mFloat * 100;
389 }
391 break;
392 case CSS_NUMBER :
393 if (mType == CSS_NUMBER) {
394 return mValue.mFloat;
395 }
396 if (mType == CSS_NUMBER_INT32) {
397 return mValue.mInt32;
398 }
399 if (mType == CSS_NUMBER_UINT32) {
400 return mValue.mUint32;
401 }
403 break;
404 case CSS_UNKNOWN :
405 case CSS_EMS :
406 case CSS_EXS :
407 case CSS_DEG :
408 case CSS_RAD :
409 case CSS_GRAD :
410 case CSS_MS :
411 case CSS_S :
412 case CSS_HZ :
413 case CSS_KHZ :
414 case CSS_DIMENSION :
415 case CSS_STRING :
416 case CSS_URI :
417 case CSS_IDENT :
418 case CSS_ATTR :
419 case CSS_COUNTER :
420 case CSS_RECT :
421 case CSS_RGBCOLOR :
422 break;
423 }
425 aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
426 return 0;
427 }
429 NS_IMETHODIMP
430 nsROCSSPrimitiveValue::GetFloatValue(uint16_t aType, float *aVal)
431 {
432 ErrorResult rv;
433 *aVal = GetFloatValue(aType, rv);
434 return rv.ErrorCode();
435 }
438 NS_IMETHODIMP
439 nsROCSSPrimitiveValue::SetStringValue(uint16_t aStringType,
440 const nsAString& aStringValue)
441 {
442 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
443 }
445 void
446 nsROCSSPrimitiveValue::SetStringValue(uint16_t aType, const nsAString& aString,
447 mozilla::ErrorResult& aRv)
448 {
449 aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
450 }
453 NS_IMETHODIMP
454 nsROCSSPrimitiveValue::GetStringValue(nsAString& aReturn)
455 {
456 switch (mType) {
457 case CSS_IDENT:
458 CopyUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword), aReturn);
459 break;
460 case CSS_STRING:
461 case CSS_ATTR:
462 aReturn.Assign(mValue.mString);
463 break;
464 case CSS_URI: {
465 nsAutoCString spec;
466 if (mValue.mURI)
467 mValue.mURI->GetSpec(spec);
468 CopyUTF8toUTF16(spec, aReturn);
469 } break;
470 default:
471 aReturn.Truncate();
472 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
473 }
474 return NS_OK;
475 }
477 void
478 nsROCSSPrimitiveValue::GetStringValue(nsString& aString, ErrorResult& aRv)
479 {
480 aRv = GetStringValue(aString);
481 }
484 NS_IMETHODIMP
485 nsROCSSPrimitiveValue::GetCounterValue(nsIDOMCounter** aReturn)
486 {
487 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
488 }
490 already_AddRefed<nsIDOMCounter>
491 nsROCSSPrimitiveValue::GetCounterValue(ErrorResult& aRv)
492 {
493 aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
494 return nullptr;
495 }
497 nsDOMCSSRect*
498 nsROCSSPrimitiveValue::GetRectValue(ErrorResult& aRv)
499 {
500 if (mType != CSS_RECT) {
501 aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
502 return nullptr;
503 }
505 NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
506 return mValue.mRect;
507 }
509 NS_IMETHODIMP
510 nsROCSSPrimitiveValue::GetRectValue(nsIDOMRect** aRect)
511 {
512 ErrorResult error;
513 NS_IF_ADDREF(*aRect = GetRectValue(error));
514 return error.ErrorCode();
515 }
517 nsDOMCSSRGBColor*
518 nsROCSSPrimitiveValue::GetRGBColorValue(ErrorResult& aRv)
519 {
520 if (mType != CSS_RGBCOLOR) {
521 aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
522 return nullptr;
523 }
525 NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
526 return mValue.mColor;
527 }
529 void
530 nsROCSSPrimitiveValue::SetNumber(float aValue)
531 {
532 Reset();
533 mValue.mFloat = aValue;
534 mType = CSS_NUMBER;
535 }
537 void
538 nsROCSSPrimitiveValue::SetNumber(int32_t aValue)
539 {
540 Reset();
541 mValue.mInt32 = aValue;
542 mType = CSS_NUMBER_INT32;
543 }
545 void
546 nsROCSSPrimitiveValue::SetNumber(uint32_t aValue)
547 {
548 Reset();
549 mValue.mUint32 = aValue;
550 mType = CSS_NUMBER_UINT32;
551 }
553 void
554 nsROCSSPrimitiveValue::SetPercent(float aValue)
555 {
556 Reset();
557 mValue.mFloat = aValue;
558 mType = CSS_PERCENTAGE;
559 }
561 void
562 nsROCSSPrimitiveValue::SetDegree(float aValue)
563 {
564 Reset();
565 mValue.mFloat = aValue;
566 mType = CSS_DEG;
567 }
569 void
570 nsROCSSPrimitiveValue::SetGrad(float aValue)
571 {
572 Reset();
573 mValue.mFloat = aValue;
574 mType = CSS_GRAD;
575 }
577 void
578 nsROCSSPrimitiveValue::SetRadian(float aValue)
579 {
580 Reset();
581 mValue.mFloat = aValue;
582 mType = CSS_RAD;
583 }
585 void
586 nsROCSSPrimitiveValue::SetTurn(float aValue)
587 {
588 Reset();
589 mValue.mFloat = aValue;
590 mType = CSS_TURN;
591 }
593 void
594 nsROCSSPrimitiveValue::SetAppUnits(nscoord aValue)
595 {
596 Reset();
597 mValue.mAppUnits = aValue;
598 mType = CSS_PX;
599 }
601 void
602 nsROCSSPrimitiveValue::SetAppUnits(float aValue)
603 {
604 SetAppUnits(NSToCoordRound(aValue));
605 }
607 void
608 nsROCSSPrimitiveValue::SetIdent(nsCSSKeyword aKeyword)
609 {
610 NS_PRECONDITION(aKeyword != eCSSKeyword_UNKNOWN &&
611 0 <= aKeyword && aKeyword < eCSSKeyword_COUNT,
612 "bad keyword");
613 Reset();
614 mValue.mKeyword = aKeyword;
615 mType = CSS_IDENT;
616 }
618 // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
619 void
620 nsROCSSPrimitiveValue::SetString(const nsACString& aString, uint16_t aType)
621 {
622 Reset();
623 mValue.mString = ToNewUnicode(aString);
624 if (mValue.mString) {
625 mType = aType;
626 } else {
627 // XXXcaa We should probably let the caller know we are out of memory
628 mType = CSS_UNKNOWN;
629 }
630 }
632 // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
633 void
634 nsROCSSPrimitiveValue::SetString(const nsAString& aString, uint16_t aType)
635 {
636 Reset();
637 mValue.mString = ToNewUnicode(aString);
638 if (mValue.mString) {
639 mType = aType;
640 } else {
641 // XXXcaa We should probably let the caller know we are out of memory
642 mType = CSS_UNKNOWN;
643 }
644 }
646 void
647 nsROCSSPrimitiveValue::SetURI(nsIURI *aURI)
648 {
649 Reset();
650 mValue.mURI = aURI;
651 NS_IF_ADDREF(mValue.mURI);
652 mType = CSS_URI;
653 }
655 void
656 nsROCSSPrimitiveValue::SetColor(nsDOMCSSRGBColor* aColor)
657 {
658 NS_PRECONDITION(aColor, "Null RGBColor being set!");
659 Reset();
660 mValue.mColor = aColor;
661 if (mValue.mColor) {
662 NS_ADDREF(mValue.mColor);
663 mType = CSS_RGBCOLOR;
664 }
665 else {
666 mType = CSS_UNKNOWN;
667 }
668 }
670 void
671 nsROCSSPrimitiveValue::SetRect(nsDOMCSSRect* aRect)
672 {
673 NS_PRECONDITION(aRect, "Null rect being set!");
674 Reset();
675 mValue.mRect = aRect;
676 if (mValue.mRect) {
677 NS_ADDREF(mValue.mRect);
678 mType = CSS_RECT;
679 }
680 else {
681 mType = CSS_UNKNOWN;
682 }
683 }
685 void
686 nsROCSSPrimitiveValue::SetTime(float aValue)
687 {
688 Reset();
689 mValue.mFloat = aValue;
690 mType = CSS_S;
691 }
693 void
694 nsROCSSPrimitiveValue::Reset()
695 {
696 switch (mType) {
697 case CSS_IDENT:
698 break;
699 case CSS_STRING:
700 case CSS_ATTR:
701 case CSS_COUNTER: // FIXME: Counter should use an object
702 NS_ASSERTION(mValue.mString, "Null string should never happen");
703 nsMemory::Free(mValue.mString);
704 mValue.mString = nullptr;
705 break;
706 case CSS_URI:
707 NS_IF_RELEASE(mValue.mURI);
708 break;
709 case CSS_RECT:
710 NS_ASSERTION(mValue.mRect, "Null Rect should never happen");
711 NS_RELEASE(mValue.mRect);
712 break;
713 case CSS_RGBCOLOR:
714 NS_ASSERTION(mValue.mColor, "Null RGBColor should never happen");
715 NS_RELEASE(mValue.mColor);
716 break;
717 }
719 mType = CSS_UNKNOWN;
720 }