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
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.
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 /* representation of simple property values within CSS declarations */
40 #include "nsCSSValue.h"
42 #include "nsCSSProps.h"
43 #include "nsReadableUtils.h"
44 #include "imgIRequest.h"
45 #include "nsIDocument.h"
46 #include "nsContentUtils.h"
47 #include "nsIPrincipal.h"
52 nsCSSValue::nsCSSValue(PRInt32 aValue
, nsCSSUnit aUnit
)
55 NS_ASSERTION(aUnit
== eCSSUnit_Integer
|| aUnit
== eCSSUnit_Enumerated
||
56 aUnit
== eCSSUnit_EnumColor
, "not an int value");
57 if (aUnit
== eCSSUnit_Integer
|| aUnit
== eCSSUnit_Enumerated
||
58 aUnit
== eCSSUnit_EnumColor
) {
62 mUnit
= eCSSUnit_Null
;
67 nsCSSValue::nsCSSValue(float aValue
, nsCSSUnit aUnit
)
70 NS_ASSERTION(eCSSUnit_Percent
<= aUnit
, "not a float value");
71 if (eCSSUnit_Percent
<= aUnit
) {
72 mValue
.mFloat
= aValue
;
75 mUnit
= eCSSUnit_Null
;
80 nsCSSValue::nsCSSValue(const nsString
& aValue
, nsCSSUnit aUnit
)
83 NS_ASSERTION(UnitHasStringValue(), "not a string value");
84 if (UnitHasStringValue()) {
85 mValue
.mString
= BufferFromString(aValue
);
86 if (NS_UNLIKELY(!mValue
.mString
)) {
87 // XXXbz not much we can do here; just make sure that our promise of a
88 // non-null mValue.mString holds for string units.
89 mUnit
= eCSSUnit_Null
;
93 mUnit
= eCSSUnit_Null
;
98 nsCSSValue::nsCSSValue(nscolor aValue
)
99 : mUnit(eCSSUnit_Color
)
101 mValue
.mColor
= aValue
;
104 nsCSSValue::nsCSSValue(nsCSSValue::Array
* aValue
, nsCSSUnit aUnit
)
107 NS_ASSERTION(eCSSUnit_Array
<= aUnit
&& aUnit
<= eCSSUnit_Function
,
109 mValue
.mArray
= aValue
;
110 mValue
.mArray
->AddRef();
113 nsCSSValue::nsCSSValue(nsCSSValue::URL
* aValue
)
114 : mUnit(eCSSUnit_URL
)
116 mValue
.mURL
= aValue
;
117 mValue
.mURL
->AddRef();
120 nsCSSValue::nsCSSValue(nsCSSValue::Image
* aValue
)
121 : mUnit(eCSSUnit_Image
)
123 mValue
.mImage
= aValue
;
124 mValue
.mImage
->AddRef();
127 nsCSSValue::nsCSSValue(const nsCSSValue
& aCopy
)
130 if (mUnit
<= eCSSUnit_RectIsAuto
) {
131 // nothing to do, but put this important case first
133 else if (eCSSUnit_Percent
<= mUnit
) {
134 mValue
.mFloat
= aCopy
.mValue
.mFloat
;
136 else if (UnitHasStringValue()) {
137 mValue
.mString
= aCopy
.mValue
.mString
;
138 mValue
.mString
->AddRef();
140 else if (eCSSUnit_Integer
<= mUnit
&& mUnit
<= eCSSUnit_EnumColor
) {
141 mValue
.mInt
= aCopy
.mValue
.mInt
;
143 else if (eCSSUnit_Color
== mUnit
) {
144 mValue
.mColor
= aCopy
.mValue
.mColor
;
146 else if (eCSSUnit_Array
<= mUnit
&& mUnit
<= eCSSUnit_Function
) {
147 mValue
.mArray
= aCopy
.mValue
.mArray
;
148 mValue
.mArray
->AddRef();
150 else if (eCSSUnit_URL
== mUnit
) {
151 mValue
.mURL
= aCopy
.mValue
.mURL
;
152 mValue
.mURL
->AddRef();
154 else if (eCSSUnit_Image
== mUnit
) {
155 mValue
.mImage
= aCopy
.mValue
.mImage
;
156 mValue
.mImage
->AddRef();
159 NS_NOTREACHED("unknown unit");
163 nsCSSValue
& nsCSSValue::operator=(const nsCSSValue
& aCopy
)
165 if (this != &aCopy
) {
167 new (this) nsCSSValue(aCopy
);
172 PRBool
nsCSSValue::operator==(const nsCSSValue
& aOther
) const
174 if (mUnit
== aOther
.mUnit
) {
175 if (mUnit
<= eCSSUnit_RectIsAuto
) {
178 else if (UnitHasStringValue()) {
179 return (NS_strcmp(GetBufferValue(mValue
.mString
),
180 GetBufferValue(aOther
.mValue
.mString
)) == 0);
182 else if ((eCSSUnit_Integer
<= mUnit
) && (mUnit
<= eCSSUnit_EnumColor
)) {
183 return mValue
.mInt
== aOther
.mValue
.mInt
;
185 else if (eCSSUnit_Color
== mUnit
) {
186 return mValue
.mColor
== aOther
.mValue
.mColor
;
188 else if (eCSSUnit_Array
<= mUnit
&& mUnit
<= eCSSUnit_Function
) {
189 return *mValue
.mArray
== *aOther
.mValue
.mArray
;
191 else if (eCSSUnit_URL
== mUnit
) {
192 return *mValue
.mURL
== *aOther
.mValue
.mURL
;
194 else if (eCSSUnit_Image
== mUnit
) {
195 return *mValue
.mImage
== *aOther
.mValue
.mImage
;
198 return mValue
.mFloat
== aOther
.mValue
.mFloat
;
204 imgIRequest
* nsCSSValue::GetImageValue() const
206 NS_ASSERTION(mUnit
== eCSSUnit_Image
, "not an Image value");
207 return mValue
.mImage
->mRequest
;
210 nscoord
nsCSSValue::GetLengthTwips() const
212 NS_ASSERTION(IsFixedLengthUnit(), "not a fixed length unit");
214 if (IsFixedLengthUnit()) {
217 return NS_INCHES_TO_TWIPS(mValue
.mFloat
);
219 return NS_FEET_TO_TWIPS(mValue
.mFloat
);
221 return NS_MILES_TO_TWIPS(mValue
.mFloat
);
223 case eCSSUnit_Millimeter
:
224 return NS_MILLIMETERS_TO_TWIPS(mValue
.mFloat
);
225 case eCSSUnit_Centimeter
:
226 return NS_CENTIMETERS_TO_TWIPS(mValue
.mFloat
);
228 return NS_METERS_TO_TWIPS(mValue
.mFloat
);
229 case eCSSUnit_Kilometer
:
230 return NS_KILOMETERS_TO_TWIPS(mValue
.mFloat
);
233 return NS_POINTS_TO_TWIPS(mValue
.mFloat
);
235 return NS_PICAS_TO_TWIPS(mValue
.mFloat
);
237 return NS_DIDOTS_TO_TWIPS(mValue
.mFloat
);
238 case eCSSUnit_Cicero
:
239 return NS_CICEROS_TO_TWIPS(mValue
.mFloat
);
241 NS_ERROR("should never get here");
248 void nsCSSValue::DoReset()
250 if (UnitHasStringValue()) {
251 mValue
.mString
->Release();
252 } else if (eCSSUnit_Array
<= mUnit
&& mUnit
<= eCSSUnit_Function
) {
253 mValue
.mArray
->Release();
254 } else if (eCSSUnit_URL
== mUnit
) {
255 mValue
.mURL
->Release();
256 } else if (eCSSUnit_Image
== mUnit
) {
257 mValue
.mImage
->Release();
259 mUnit
= eCSSUnit_Null
;
262 void nsCSSValue::SetIntValue(PRInt32 aValue
, nsCSSUnit aUnit
)
264 NS_ASSERTION(aUnit
== eCSSUnit_Integer
|| aUnit
== eCSSUnit_Enumerated
||
265 aUnit
== eCSSUnit_EnumColor
, "not an int value");
267 if (aUnit
== eCSSUnit_Integer
|| aUnit
== eCSSUnit_Enumerated
||
268 aUnit
== eCSSUnit_EnumColor
) {
270 mValue
.mInt
= aValue
;
274 void nsCSSValue::SetPercentValue(float aValue
)
277 mUnit
= eCSSUnit_Percent
;
278 mValue
.mFloat
= aValue
;
281 void nsCSSValue::SetFloatValue(float aValue
, nsCSSUnit aUnit
)
283 NS_ASSERTION(eCSSUnit_Number
<= aUnit
, "not a float value");
285 if (eCSSUnit_Number
<= aUnit
) {
287 mValue
.mFloat
= aValue
;
291 void nsCSSValue::SetStringValue(const nsString
& aValue
,
296 NS_ASSERTION(UnitHasStringValue(), "not a string unit");
297 if (UnitHasStringValue()) {
298 mValue
.mString
= BufferFromString(aValue
);
299 if (NS_UNLIKELY(!mValue
.mString
)) {
300 // XXXbz not much we can do here; just make sure that our promise of a
301 // non-null mValue.mString holds for string units.
302 mUnit
= eCSSUnit_Null
;
305 mUnit
= eCSSUnit_Null
;
308 void nsCSSValue::SetColorValue(nscolor aValue
)
311 mUnit
= eCSSUnit_Color
;
312 mValue
.mColor
= aValue
;
315 void nsCSSValue::SetArrayValue(nsCSSValue::Array
* aValue
, nsCSSUnit aUnit
)
317 NS_ASSERTION(eCSSUnit_Array
<= aUnit
&& aUnit
<= eCSSUnit_Function
,
321 mValue
.mArray
= aValue
;
322 mValue
.mArray
->AddRef();
325 void nsCSSValue::SetURLValue(nsCSSValue::URL
* aValue
)
328 mUnit
= eCSSUnit_URL
;
329 mValue
.mURL
= aValue
;
330 mValue
.mURL
->AddRef();
333 void nsCSSValue::SetImageValue(nsCSSValue::Image
* aValue
)
336 mUnit
= eCSSUnit_Image
;
337 mValue
.mImage
= aValue
;
338 mValue
.mImage
->AddRef();
341 void nsCSSValue::SetAutoValue()
344 mUnit
= eCSSUnit_Auto
;
347 void nsCSSValue::SetInheritValue()
350 mUnit
= eCSSUnit_Inherit
;
353 void nsCSSValue::SetInitialValue()
356 mUnit
= eCSSUnit_Initial
;
359 void nsCSSValue::SetNoneValue()
362 mUnit
= eCSSUnit_None
;
365 void nsCSSValue::SetNormalValue()
368 mUnit
= eCSSUnit_Normal
;
371 void nsCSSValue::SetSystemFontValue()
374 mUnit
= eCSSUnit_System_Font
;
377 void nsCSSValue::SetDummyValue()
380 mUnit
= eCSSUnit_Dummy
;
383 void nsCSSValue::SetDummyInheritValue()
386 mUnit
= eCSSUnit_DummyInherit
;
389 void nsCSSValue::SetRectIsAutoValue()
392 mUnit
= eCSSUnit_RectIsAuto
;
395 void nsCSSValue::StartImageLoad(nsIDocument
* aDocument
) const
397 NS_PRECONDITION(eCSSUnit_URL
== mUnit
, "Not a URL value!");
398 nsCSSValue::Image
* image
=
399 new nsCSSValue::Image(mValue
.mURL
->mURI
,
400 mValue
.mURL
->mString
,
401 mValue
.mURL
->mReferrer
,
402 mValue
.mURL
->mOriginPrincipal
,
405 nsCSSValue
* writable
= const_cast<nsCSSValue
*>(this);
406 writable
->SetImageValue(image
);
412 nsCSSValue::BufferFromString(const nsString
& aValue
)
414 nsStringBuffer
* buffer
= nsStringBuffer::FromString(aValue
);
420 PRUnichar length
= aValue
.Length();
421 buffer
= nsStringBuffer::Alloc((length
+ 1) * sizeof(PRUnichar
));
422 if (NS_LIKELY(buffer
!= 0)) {
423 PRUnichar
* data
= static_cast<PRUnichar
*>(buffer
->Data());
424 nsCharTraits
<PRUnichar
>::copy(data
, aValue
.get(), length
);
432 nsCSSValue::URL::URL(nsIURI
* aURI
, nsStringBuffer
* aString
, nsIURI
* aReferrer
,
433 nsIPrincipal
* aOriginPrincipal
)
436 mReferrer(aReferrer
),
437 mOriginPrincipal(aOriginPrincipal
),
440 NS_PRECONDITION(aOriginPrincipal
, "Must have an origin principal");
443 MOZ_COUNT_CTOR(nsCSSValue::URL
);
446 nsCSSValue::URL::~URL()
449 MOZ_COUNT_DTOR(nsCSSValue::URL
);
453 nsCSSValue::URL::operator==(const URL
& aOther
) const
456 return NS_strcmp(GetBufferValue(mString
),
457 GetBufferValue(aOther
.mString
)) == 0 &&
458 (mURI
== aOther
.mURI
|| // handles null == null
459 (mURI
&& aOther
.mURI
&&
460 NS_SUCCEEDED(mURI
->Equals(aOther
.mURI
, &eq
)) &&
462 (mOriginPrincipal
== aOther
.mOriginPrincipal
||
463 (NS_SUCCEEDED(mOriginPrincipal
->Equals(aOther
.mOriginPrincipal
,
468 nsCSSValue::URL::URIEquals(const URL
& aOther
) const
471 // Worth comparing mURI to aOther.mURI and mOriginPrincipal to
472 // aOther.mOriginPrincipal, because in the (probably common) case when this
473 // value was one of the ones that in fact did not change this will be our
474 // fast path to equality
475 return (mURI
== aOther
.mURI
||
476 (NS_SUCCEEDED(mURI
->Equals(aOther
.mURI
, &eq
)) && eq
)) &&
477 (mOriginPrincipal
== aOther
.mOriginPrincipal
||
478 (NS_SUCCEEDED(mOriginPrincipal
->Equals(aOther
.mOriginPrincipal
,
482 nsCSSValue::Image::Image(nsIURI
* aURI
, nsStringBuffer
* aString
,
483 nsIURI
* aReferrer
, nsIPrincipal
* aOriginPrincipal
,
484 nsIDocument
* aDocument
)
485 : URL(aURI
, aString
, aReferrer
, aOriginPrincipal
)
487 MOZ_COUNT_CTOR(nsCSSValue::Image
);
490 nsContentUtils::CanLoadImage(mURI
, aDocument
, aDocument
,
492 nsContentUtils::LoadImage(mURI
, aDocument
, aOriginPrincipal
, aReferrer
,
493 nsnull
, nsIRequest::LOAD_NORMAL
,
494 getter_AddRefs(mRequest
));
498 nsCSSValue::Image::~Image()
500 MOZ_COUNT_DTOR(nsCSSValue::Image
);