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
4 : *
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/
9 : *
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.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
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.
21 : *
22 : * Contributor(s):
23 : *
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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /* DOM object representing values in DOM computed style */
39 :
40 : #include "nsROCSSPrimitiveValue.h"
41 :
42 : #include "nsPresContext.h"
43 : #include "nsStyleUtil.h"
44 : #include "nsDOMCSSRGBColor.h"
45 : #include "nsIDOMRect.h"
46 : #include "nsDOMClassInfoID.h" // DOMCI_DATA
47 :
48 0 : nsROCSSPrimitiveValue::nsROCSSPrimitiveValue()
49 0 : : mType(CSS_PX)
50 : {
51 0 : mValue.mAppUnits = 0;
52 0 : }
53 :
54 :
55 0 : nsROCSSPrimitiveValue::~nsROCSSPrimitiveValue()
56 : {
57 0 : Reset();
58 0 : }
59 :
60 0 : NS_IMPL_ADDREF(nsROCSSPrimitiveValue)
61 0 : NS_IMPL_RELEASE(nsROCSSPrimitiveValue)
62 :
63 :
64 : DOMCI_DATA(ROCSSPrimitiveValue, nsROCSSPrimitiveValue)
65 :
66 : // QueryInterface implementation for nsROCSSPrimitiveValue
67 0 : NS_INTERFACE_MAP_BEGIN(nsROCSSPrimitiveValue)
68 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPrimitiveValue)
69 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCSSValue)
70 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
71 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ROCSSPrimitiveValue)
72 0 : NS_INTERFACE_MAP_END
73 :
74 :
75 : // nsIDOMCSSValue
76 :
77 :
78 : NS_IMETHODIMP
79 0 : nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
80 : {
81 0 : nsAutoString tmpStr;
82 0 : aCssText.Truncate();
83 0 : nsresult result = NS_OK;
84 :
85 0 : switch (mType) {
86 : case CSS_PX :
87 : {
88 0 : float val = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
89 0 : tmpStr.AppendFloat(val);
90 0 : tmpStr.AppendLiteral("px");
91 0 : break;
92 : }
93 : case CSS_IDENT :
94 : {
95 0 : AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword),
96 0 : tmpStr);
97 0 : break;
98 : }
99 : case CSS_STRING :
100 : case CSS_COUNTER : /* FIXME: COUNTER should use an object */
101 : {
102 0 : tmpStr.Append(mValue.mString);
103 0 : break;
104 : }
105 : case CSS_URI :
106 : {
107 0 : if (mValue.mURI) {
108 0 : nsCAutoString specUTF8;
109 0 : mValue.mURI->GetSpec(specUTF8);
110 :
111 0 : tmpStr.AssignLiteral("url(");
112 0 : nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8),
113 0 : tmpStr);
114 0 : tmpStr.AppendLiteral(")");
115 : } else {
116 : // XXXldb Any better ideas? It's good to have something that
117 : // doesn't parse so that things round-trip "correctly".
118 0 : tmpStr.Assign(NS_LITERAL_STRING("url(invalid-url:)"));
119 : }
120 0 : break;
121 : }
122 : case CSS_ATTR :
123 : {
124 0 : tmpStr.AppendLiteral("attr(");
125 0 : tmpStr.Append(mValue.mString);
126 0 : tmpStr.Append(PRUnichar(')'));
127 0 : break;
128 : }
129 : case CSS_PERCENTAGE :
130 : {
131 0 : tmpStr.AppendFloat(mValue.mFloat * 100);
132 0 : tmpStr.Append(PRUnichar('%'));
133 0 : break;
134 : }
135 : case CSS_NUMBER :
136 : {
137 0 : tmpStr.AppendFloat(mValue.mFloat);
138 0 : break;
139 : }
140 : case CSS_RECT :
141 : {
142 0 : NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
143 0 : NS_NAMED_LITERAL_STRING(comma, ", ");
144 0 : nsCOMPtr<nsIDOMCSSPrimitiveValue> sideCSSValue;
145 0 : nsAutoString sideValue;
146 0 : tmpStr.AssignLiteral("rect(");
147 : // get the top
148 0 : result = mValue.mRect->GetTop(getter_AddRefs(sideCSSValue));
149 0 : if (NS_FAILED(result))
150 : break;
151 0 : result = sideCSSValue->GetCssText(sideValue);
152 0 : if (NS_FAILED(result))
153 : break;
154 0 : tmpStr.Append(sideValue + comma);
155 : // get the right
156 0 : result = mValue.mRect->GetRight(getter_AddRefs(sideCSSValue));
157 0 : if (NS_FAILED(result))
158 : break;
159 0 : result = sideCSSValue->GetCssText(sideValue);
160 0 : if (NS_FAILED(result))
161 : break;
162 0 : tmpStr.Append(sideValue + comma);
163 : // get the bottom
164 0 : result = mValue.mRect->GetBottom(getter_AddRefs(sideCSSValue));
165 0 : if (NS_FAILED(result))
166 : break;
167 0 : result = sideCSSValue->GetCssText(sideValue);
168 0 : if (NS_FAILED(result))
169 : break;
170 0 : tmpStr.Append(sideValue + comma);
171 : // get the left
172 0 : result = mValue.mRect->GetLeft(getter_AddRefs(sideCSSValue));
173 0 : if (NS_FAILED(result))
174 : break;
175 0 : result = sideCSSValue->GetCssText(sideValue);
176 0 : if (NS_FAILED(result))
177 : break;
178 0 : tmpStr.Append(sideValue + NS_LITERAL_STRING(")"));
179 : break;
180 : }
181 : case CSS_RGBCOLOR :
182 : {
183 0 : NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
184 0 : NS_NAMED_LITERAL_STRING(comma, ", ");
185 0 : nsCOMPtr<nsIDOMCSSPrimitiveValue> colorCSSValue;
186 0 : nsAutoString colorValue;
187 0 : if (mValue.mColor->HasAlpha())
188 0 : tmpStr.AssignLiteral("rgba(");
189 : else
190 0 : tmpStr.AssignLiteral("rgb(");
191 :
192 : // get the red component
193 0 : result = mValue.mColor->GetRed(getter_AddRefs(colorCSSValue));
194 0 : if (NS_FAILED(result))
195 : break;
196 0 : result = colorCSSValue->GetCssText(colorValue);
197 0 : if (NS_FAILED(result))
198 : break;
199 0 : tmpStr.Append(colorValue + comma);
200 :
201 : // get the green component
202 0 : result = mValue.mColor->GetGreen(getter_AddRefs(colorCSSValue));
203 0 : if (NS_FAILED(result))
204 : break;
205 0 : result = colorCSSValue->GetCssText(colorValue);
206 0 : if (NS_FAILED(result))
207 : break;
208 0 : tmpStr.Append(colorValue + comma);
209 :
210 : // get the blue component
211 0 : result = mValue.mColor->GetBlue(getter_AddRefs(colorCSSValue));
212 0 : if (NS_FAILED(result))
213 : break;
214 0 : result = colorCSSValue->GetCssText(colorValue);
215 0 : if (NS_FAILED(result))
216 : break;
217 0 : tmpStr.Append(colorValue);
218 :
219 0 : if (mValue.mColor->HasAlpha()) {
220 : // get the alpha component
221 0 : result = mValue.mColor->GetAlpha(getter_AddRefs(colorCSSValue));
222 0 : if (NS_FAILED(result))
223 : break;
224 0 : result = colorCSSValue->GetCssText(colorValue);
225 0 : if (NS_FAILED(result))
226 : break;
227 0 : tmpStr.Append(comma + colorValue);
228 : }
229 :
230 0 : tmpStr.Append(NS_LITERAL_STRING(")"));
231 :
232 : break;
233 : }
234 : case CSS_S :
235 : {
236 0 : tmpStr.AppendFloat(mValue.mFloat);
237 0 : tmpStr.AppendLiteral("s");
238 0 : break;
239 : }
240 : case CSS_CM :
241 : case CSS_MM :
242 : case CSS_IN :
243 : case CSS_PT :
244 : case CSS_PC :
245 : case CSS_UNKNOWN :
246 : case CSS_EMS :
247 : case CSS_EXS :
248 : case CSS_DEG :
249 : case CSS_RAD :
250 : case CSS_GRAD :
251 : case CSS_MS :
252 : case CSS_HZ :
253 : case CSS_KHZ :
254 : case CSS_DIMENSION :
255 0 : NS_ERROR("We have a bogus value set. This should not happen");
256 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
257 : }
258 :
259 0 : if (NS_SUCCEEDED(result)) {
260 0 : aCssText.Assign(tmpStr);
261 : }
262 :
263 0 : return NS_OK;
264 : }
265 :
266 :
267 : NS_IMETHODIMP
268 0 : nsROCSSPrimitiveValue::SetCssText(const nsAString& aCssText)
269 : {
270 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
271 : }
272 :
273 :
274 : NS_IMETHODIMP
275 0 : nsROCSSPrimitiveValue::GetCssValueType(PRUint16* aValueType)
276 : {
277 0 : NS_ENSURE_ARG_POINTER(aValueType);
278 0 : *aValueType = nsIDOMCSSValue::CSS_PRIMITIVE_VALUE;
279 0 : return NS_OK;
280 : }
281 :
282 :
283 : // nsIDOMCSSPrimitiveValue
284 :
285 : NS_IMETHODIMP
286 0 : nsROCSSPrimitiveValue::GetPrimitiveType(PRUint16* aPrimitiveType)
287 : {
288 0 : NS_ENSURE_ARG_POINTER(aPrimitiveType);
289 0 : *aPrimitiveType = mType;
290 :
291 0 : return NS_OK;
292 : }
293 :
294 :
295 : NS_IMETHODIMP
296 0 : nsROCSSPrimitiveValue::SetFloatValue(PRUint16 aUnitType, float aFloatValue)
297 : {
298 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
299 : }
300 :
301 :
302 : NS_IMETHODIMP
303 0 : nsROCSSPrimitiveValue::GetFloatValue(PRUint16 aUnitType, float* aReturn)
304 : {
305 0 : NS_ENSURE_ARG_POINTER(aReturn);
306 0 : *aReturn = 0;
307 :
308 0 : switch(aUnitType) {
309 : case CSS_PX :
310 0 : if (mType != CSS_PX)
311 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
312 0 : *aReturn = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits);
313 0 : break;
314 : case CSS_CM :
315 0 : if (mType != CSS_PX)
316 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
317 : *aReturn = mValue.mAppUnits * CM_PER_INCH_FLOAT /
318 0 : nsPresContext::AppUnitsPerCSSInch();
319 0 : break;
320 : case CSS_MM :
321 0 : if (mType != CSS_PX)
322 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
323 : *aReturn = mValue.mAppUnits * MM_PER_INCH_FLOAT /
324 0 : nsPresContext::AppUnitsPerCSSInch();
325 0 : break;
326 : case CSS_IN :
327 0 : if (mType != CSS_PX)
328 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
329 0 : *aReturn = mValue.mAppUnits / nsPresContext::AppUnitsPerCSSInch();
330 0 : break;
331 : case CSS_PT :
332 0 : if (mType != CSS_PX)
333 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
334 : *aReturn = mValue.mAppUnits * POINTS_PER_INCH_FLOAT /
335 0 : nsPresContext::AppUnitsPerCSSInch();
336 0 : break;
337 : case CSS_PC :
338 0 : if (mType != CSS_PX)
339 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
340 : *aReturn = mValue.mAppUnits * 6.0f /
341 0 : nsPresContext::AppUnitsPerCSSInch();
342 0 : break;
343 : case CSS_PERCENTAGE :
344 0 : if (mType != CSS_PERCENTAGE)
345 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
346 0 : *aReturn = mValue.mFloat * 100;
347 0 : break;
348 : case CSS_NUMBER :
349 0 : if (mType != CSS_NUMBER)
350 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
351 0 : *aReturn = mValue.mFloat;
352 0 : break;
353 : case CSS_UNKNOWN :
354 : case CSS_EMS :
355 : case CSS_EXS :
356 : case CSS_DEG :
357 : case CSS_RAD :
358 : case CSS_GRAD :
359 : case CSS_MS :
360 : case CSS_S :
361 : case CSS_HZ :
362 : case CSS_KHZ :
363 : case CSS_DIMENSION :
364 : case CSS_STRING :
365 : case CSS_URI :
366 : case CSS_IDENT :
367 : case CSS_ATTR :
368 : case CSS_COUNTER :
369 : case CSS_RECT :
370 : case CSS_RGBCOLOR :
371 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
372 : }
373 :
374 0 : return NS_OK;
375 : }
376 :
377 :
378 : NS_IMETHODIMP
379 0 : nsROCSSPrimitiveValue::SetStringValue(PRUint16 aStringType,
380 : const nsAString& aStringValue)
381 : {
382 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
383 : }
384 :
385 :
386 : NS_IMETHODIMP
387 0 : nsROCSSPrimitiveValue::GetStringValue(nsAString& aReturn)
388 : {
389 0 : switch (mType) {
390 : case CSS_IDENT:
391 0 : CopyUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword), aReturn);
392 0 : break;
393 : case CSS_STRING:
394 : case CSS_ATTR:
395 0 : aReturn.Assign(mValue.mString);
396 0 : break;
397 : case CSS_URI: {
398 0 : nsCAutoString spec;
399 0 : if (mValue.mURI)
400 0 : mValue.mURI->GetSpec(spec);
401 0 : CopyUTF8toUTF16(spec, aReturn);
402 0 : } break;
403 : default:
404 0 : aReturn.Truncate();
405 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
406 : }
407 0 : return NS_OK;
408 : }
409 :
410 :
411 : NS_IMETHODIMP
412 0 : nsROCSSPrimitiveValue::GetCounterValue(nsIDOMCounter** aReturn)
413 : {
414 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
415 : }
416 :
417 :
418 : NS_IMETHODIMP
419 0 : nsROCSSPrimitiveValue::GetRectValue(nsIDOMRect** aReturn)
420 : {
421 0 : if (mType != CSS_RECT) {
422 0 : *aReturn = nsnull;
423 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
424 : }
425 0 : NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
426 0 : NS_ADDREF(*aReturn = mValue.mRect);
427 0 : return NS_OK;
428 : }
429 :
430 :
431 : NS_IMETHODIMP
432 0 : nsROCSSPrimitiveValue::GetRGBColorValue(nsIDOMRGBColor** aReturn)
433 : {
434 0 : if (mType != CSS_RGBCOLOR) {
435 0 : *aReturn = nsnull;
436 0 : return NS_ERROR_DOM_INVALID_ACCESS_ERR;
437 : }
438 0 : NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null");
439 0 : NS_ADDREF(*aReturn = mValue.mColor);
440 0 : return NS_OK;
441 : }
442 :
443 : void
444 0 : nsROCSSPrimitiveValue::SetNumber(float aValue)
445 : {
446 0 : Reset();
447 0 : mValue.mFloat = aValue;
448 0 : mType = CSS_NUMBER;
449 0 : }
450 :
451 : void
452 0 : nsROCSSPrimitiveValue::SetNumber(PRInt32 aValue)
453 : {
454 0 : Reset();
455 0 : mValue.mFloat = float(aValue);
456 0 : mType = CSS_NUMBER;
457 0 : }
458 :
459 : void
460 0 : nsROCSSPrimitiveValue::SetNumber(PRUint32 aValue)
461 : {
462 0 : Reset();
463 0 : mValue.mFloat = float(aValue);
464 0 : mType = CSS_NUMBER;
465 0 : }
466 :
467 : void
468 0 : nsROCSSPrimitiveValue::SetPercent(float aValue)
469 : {
470 0 : Reset();
471 0 : mValue.mFloat = aValue;
472 0 : mType = CSS_PERCENTAGE;
473 0 : }
474 :
475 : void
476 0 : nsROCSSPrimitiveValue::SetAppUnits(nscoord aValue)
477 : {
478 0 : Reset();
479 0 : mValue.mAppUnits = aValue;
480 0 : mType = CSS_PX;
481 0 : }
482 :
483 : void
484 0 : nsROCSSPrimitiveValue::SetAppUnits(float aValue)
485 : {
486 0 : SetAppUnits(NSToCoordRound(aValue));
487 0 : }
488 :
489 : void
490 0 : nsROCSSPrimitiveValue::SetIdent(nsCSSKeyword aKeyword)
491 : {
492 0 : NS_PRECONDITION(aKeyword != eCSSKeyword_UNKNOWN &&
493 : 0 <= aKeyword && aKeyword < eCSSKeyword_COUNT,
494 : "bad keyword");
495 0 : Reset();
496 0 : mValue.mKeyword = aKeyword;
497 0 : mType = CSS_IDENT;
498 0 : }
499 :
500 : // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
501 : void
502 0 : nsROCSSPrimitiveValue::SetString(const nsACString& aString, PRUint16 aType)
503 : {
504 0 : Reset();
505 0 : mValue.mString = ToNewUnicode(aString);
506 0 : if (mValue.mString) {
507 0 : mType = aType;
508 : } else {
509 : // XXXcaa We should probably let the caller know we are out of memory
510 0 : mType = CSS_UNKNOWN;
511 : }
512 0 : }
513 :
514 : // FIXME: CSS_STRING should imply a string with "" and a need for escaping.
515 : void
516 0 : nsROCSSPrimitiveValue::SetString(const nsAString& aString, PRUint16 aType)
517 : {
518 0 : Reset();
519 0 : mValue.mString = ToNewUnicode(aString);
520 0 : if (mValue.mString) {
521 0 : mType = aType;
522 : } else {
523 : // XXXcaa We should probably let the caller know we are out of memory
524 0 : mType = CSS_UNKNOWN;
525 : }
526 0 : }
527 :
528 : void
529 0 : nsROCSSPrimitiveValue::SetURI(nsIURI *aURI)
530 : {
531 0 : Reset();
532 0 : mValue.mURI = aURI;
533 0 : NS_IF_ADDREF(mValue.mURI);
534 0 : mType = CSS_URI;
535 0 : }
536 :
537 : void
538 0 : nsROCSSPrimitiveValue::SetColor(nsDOMCSSRGBColor* aColor)
539 : {
540 0 : NS_PRECONDITION(aColor, "Null RGBColor being set!");
541 0 : Reset();
542 0 : mValue.mColor = aColor;
543 0 : if (mValue.mColor) {
544 0 : NS_ADDREF(mValue.mColor);
545 0 : mType = CSS_RGBCOLOR;
546 : }
547 : else {
548 0 : mType = CSS_UNKNOWN;
549 : }
550 0 : }
551 :
552 : void
553 0 : nsROCSSPrimitiveValue::SetRect(nsIDOMRect* aRect)
554 : {
555 0 : NS_PRECONDITION(aRect, "Null rect being set!");
556 0 : Reset();
557 0 : mValue.mRect = aRect;
558 0 : if (mValue.mRect) {
559 0 : NS_ADDREF(mValue.mRect);
560 0 : mType = CSS_RECT;
561 : }
562 : else {
563 0 : mType = CSS_UNKNOWN;
564 : }
565 0 : }
566 :
567 : void
568 0 : nsROCSSPrimitiveValue::SetTime(float aValue)
569 : {
570 0 : Reset();
571 0 : mValue.mFloat = aValue;
572 0 : mType = CSS_S;
573 0 : }
574 :
575 : void
576 0 : nsROCSSPrimitiveValue::Reset()
577 : {
578 0 : switch (mType) {
579 : case CSS_IDENT:
580 0 : break;
581 : case CSS_STRING:
582 : case CSS_ATTR:
583 : case CSS_COUNTER: // FIXME: Counter should use an object
584 0 : NS_ASSERTION(mValue.mString, "Null string should never happen");
585 0 : nsMemory::Free(mValue.mString);
586 0 : mValue.mString = nsnull;
587 0 : break;
588 : case CSS_URI:
589 0 : NS_IF_RELEASE(mValue.mURI);
590 0 : break;
591 : case CSS_RECT:
592 0 : NS_ASSERTION(mValue.mRect, "Null Rect should never happen");
593 0 : NS_RELEASE(mValue.mRect);
594 0 : break;
595 : case CSS_RGBCOLOR:
596 0 : NS_ASSERTION(mValue.mColor, "Null RGBColor should never happen");
597 0 : NS_RELEASE(mValue.mColor);
598 0 : break;
599 : }
600 0 : }
|