Back to index

lightning-sunbird  0.9+nobinonly
nsCSSValue.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsCSSValue.h"
00038 #include "nsString.h"
00039 #include "nsCSSProps.h"
00040 #include "nsReadableUtils.h"
00041 #include "imgIRequest.h"
00042 #include "nsIDocument.h"
00043 #include "nsContentUtils.h"
00044 
00045 // Paint forcing
00046 #include "prenv.h"
00047 
00048 //#include "nsStyleConsts.h"
00049 
00050 
00051 nsCSSValue::nsCSSValue(PRInt32 aValue, nsCSSUnit aUnit)
00052   : mUnit(aUnit)
00053 {
00054   NS_ASSERTION((eCSSUnit_Integer == aUnit) ||
00055                (eCSSUnit_Enumerated == aUnit), "not an int value");
00056   if ((eCSSUnit_Integer == aUnit) ||
00057       (eCSSUnit_Enumerated == aUnit)) {
00058     mValue.mInt = aValue;
00059   }
00060   else {
00061     mUnit = eCSSUnit_Null;
00062     mValue.mInt = 0;
00063   }
00064 }
00065 
00066 nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit)
00067   : mUnit(aUnit)
00068 {
00069   NS_ASSERTION(eCSSUnit_Percent <= aUnit, "not a float value");
00070   if (eCSSUnit_Percent <= aUnit) {
00071     mValue.mFloat = aValue;
00072   }
00073   else {
00074     mUnit = eCSSUnit_Null;
00075     mValue.mInt = 0;
00076   }
00077 }
00078 
00079 nsCSSValue::nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit)
00080   : mUnit(aUnit)
00081 {
00082   NS_ASSERTION((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr), "not a string value");
00083   if ((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr)) {
00084     mValue.mString = ToNewUnicode(aValue);
00085   }
00086   else {
00087     mUnit = eCSSUnit_Null;
00088     mValue.mInt = 0;
00089   }
00090 }
00091 
00092 nsCSSValue::nsCSSValue(nscolor aValue)
00093   : mUnit(eCSSUnit_Color)
00094 {
00095   mValue.mColor = aValue;
00096 }
00097 
00098 nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
00099   : mUnit(aUnit)
00100 {
00101   NS_ASSERTION(eCSSUnit_Array <= aUnit && aUnit <= eCSSUnit_Counters,
00102                "bad unit");
00103   mValue.mArray = aValue;
00104   mValue.mArray->AddRef();
00105 }
00106 
00107 nsCSSValue::nsCSSValue(nsCSSValue::URL* aValue)
00108   : mUnit(eCSSUnit_URL)
00109 {
00110   mValue.mURL = aValue;
00111   mValue.mURL->AddRef();
00112 }
00113 
00114 nsCSSValue::nsCSSValue(nsCSSValue::Image* aValue)
00115   : mUnit(eCSSUnit_Image)
00116 {
00117   mValue.mImage = aValue;
00118   mValue.mImage->AddRef();
00119 }
00120 
00121 nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
00122   : mUnit(aCopy.mUnit)
00123 {
00124   if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr)) {
00125     if (nsnull != aCopy.mValue.mString) {
00126       mValue.mString = ToNewUnicode(nsDependentString(aCopy.mValue.mString));
00127     }
00128     else {
00129       mValue.mString = nsnull;
00130     }
00131   }
00132   else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
00133     mValue.mInt = aCopy.mValue.mInt;
00134   }
00135   else if (eCSSUnit_Color == mUnit){
00136     mValue.mColor = aCopy.mValue.mColor;
00137   }
00138   else if (eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters) {
00139     mValue.mArray = aCopy.mValue.mArray;
00140     mValue.mArray->AddRef();
00141   }
00142   else if (eCSSUnit_URL == mUnit){
00143     mValue.mURL = aCopy.mValue.mURL;
00144     mValue.mURL->AddRef();
00145   }
00146   else if (eCSSUnit_Image == mUnit){
00147     mValue.mImage = aCopy.mValue.mImage;
00148     mValue.mImage->AddRef();
00149   }
00150   else {
00151     mValue.mFloat = aCopy.mValue.mFloat;
00152   }
00153 }
00154 
00155 nsCSSValue::~nsCSSValue()
00156 {
00157   Reset();
00158 }
00159 
00160 nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
00161 {
00162   if (this != &aCopy) {
00163     Reset();
00164     new (this) nsCSSValue(aCopy);
00165   }
00166   return *this;
00167 }
00168 
00169 PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
00170 {
00171   if (mUnit == aOther.mUnit) {
00172     if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr)) {
00173       if (nsnull == mValue.mString) {
00174         if (nsnull == aOther.mValue.mString) {
00175           return PR_TRUE;
00176         }
00177       }
00178       else if (nsnull != aOther.mValue.mString) {
00179         return (nsCRT::strcmp(mValue.mString, aOther.mValue.mString) == 0);
00180       }
00181     }
00182     else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
00183       return mValue.mInt == aOther.mValue.mInt;
00184     }
00185     else if (eCSSUnit_Color == mUnit) {
00186       return mValue.mColor == aOther.mValue.mColor;
00187     }
00188     else if (eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters) {
00189       return *mValue.mArray == *aOther.mValue.mArray;
00190     }
00191     else if (eCSSUnit_URL == mUnit) {
00192       return *mValue.mURL == *aOther.mValue.mURL;
00193     }
00194     else if (eCSSUnit_Image == mUnit) {
00195       return *mValue.mImage == *aOther.mValue.mImage;
00196     }
00197     else {
00198       return mValue.mFloat == aOther.mValue.mFloat;
00199     }
00200   }
00201   return PR_FALSE;
00202 }
00203 
00204 imgIRequest* nsCSSValue::GetImageValue() const
00205 {
00206   NS_ASSERTION(mUnit == eCSSUnit_Image, "not an Image value");
00207   return mValue.mImage->mRequest;
00208 }
00209 
00210 nscoord nsCSSValue::GetLengthTwips() const
00211 {
00212   NS_ASSERTION(IsFixedLengthUnit(), "not a fixed length unit");
00213 
00214   if (IsFixedLengthUnit()) {
00215     switch (mUnit) {
00216     case eCSSUnit_Inch:        
00217       return NS_INCHES_TO_TWIPS(mValue.mFloat);
00218     case eCSSUnit_Foot:        
00219       return NS_FEET_TO_TWIPS(mValue.mFloat);
00220     case eCSSUnit_Mile:        
00221       return NS_MILES_TO_TWIPS(mValue.mFloat);
00222 
00223     case eCSSUnit_Millimeter:
00224       return NS_MILLIMETERS_TO_TWIPS(mValue.mFloat);
00225     case eCSSUnit_Centimeter:
00226       return NS_CENTIMETERS_TO_TWIPS(mValue.mFloat);
00227     case eCSSUnit_Meter:
00228       return NS_METERS_TO_TWIPS(mValue.mFloat);
00229     case eCSSUnit_Kilometer:
00230       return NS_KILOMETERS_TO_TWIPS(mValue.mFloat);
00231 
00232     case eCSSUnit_Point:
00233       return NSFloatPointsToTwips(mValue.mFloat);
00234     case eCSSUnit_Pica:
00235       return NS_PICAS_TO_TWIPS(mValue.mFloat);
00236     case eCSSUnit_Didot:
00237       return NS_DIDOTS_TO_TWIPS(mValue.mFloat);
00238     case eCSSUnit_Cicero:
00239       return NS_CICEROS_TO_TWIPS(mValue.mFloat);
00240     default:
00241       NS_ERROR("should never get here");
00242       break;
00243     }
00244   }
00245   return 0;
00246 }
00247 
00248 void nsCSSValue::SetIntValue(PRInt32 aValue, nsCSSUnit aUnit)
00249 {
00250   NS_ASSERTION((eCSSUnit_Integer == aUnit) ||
00251                (eCSSUnit_Enumerated == aUnit), "not an int value");
00252   Reset();
00253   if ((eCSSUnit_Integer == aUnit) ||
00254       (eCSSUnit_Enumerated == aUnit)) {
00255     mUnit = aUnit;
00256     mValue.mInt = aValue;
00257   }
00258 }
00259 
00260 void nsCSSValue::SetPercentValue(float aValue)
00261 {
00262   Reset();
00263   mUnit = eCSSUnit_Percent;
00264   mValue.mFloat = aValue;
00265 }
00266 
00267 void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
00268 {
00269   NS_ASSERTION(eCSSUnit_Number <= aUnit, "not a float value");
00270   Reset();
00271   if (eCSSUnit_Number <= aUnit) {
00272     mUnit = aUnit;
00273     mValue.mFloat = aValue;
00274   }
00275 }
00276 
00277 void nsCSSValue::SetStringValue(const nsAString& aValue,
00278                                 nsCSSUnit aUnit)
00279 {
00280   NS_ASSERTION((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr), "not a string unit");
00281   Reset();
00282   if ((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr)) {
00283     mUnit = aUnit;
00284     mValue.mString = ToNewUnicode(aValue);
00285   }
00286 }
00287 
00288 void nsCSSValue::SetColorValue(nscolor aValue)
00289 {
00290   Reset();
00291   mUnit = eCSSUnit_Color;
00292   mValue.mColor = aValue;
00293 }
00294 
00295 void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
00296 {
00297   NS_ASSERTION(eCSSUnit_Array <= aUnit && aUnit <= eCSSUnit_Counters,
00298                "bad unit");
00299   Reset();
00300   mUnit = aUnit;
00301   mValue.mArray = aValue;
00302   mValue.mArray->AddRef();
00303 }
00304 
00305 void nsCSSValue::SetURLValue(nsCSSValue::URL* aValue)
00306 {
00307   Reset();
00308   mUnit = eCSSUnit_URL;
00309   mValue.mURL = aValue;
00310   mValue.mURL->AddRef();
00311 }
00312 
00313 void nsCSSValue::SetImageValue(nsCSSValue::Image* aValue)
00314 {
00315   Reset();
00316   mUnit = eCSSUnit_Image;
00317   mValue.mImage = aValue;
00318   mValue.mImage->AddRef();
00319 }
00320 
00321 void nsCSSValue::SetAutoValue()
00322 {
00323   Reset();
00324   mUnit = eCSSUnit_Auto;
00325 }
00326 
00327 void nsCSSValue::SetInheritValue()
00328 {
00329   Reset();
00330   mUnit = eCSSUnit_Inherit;
00331 }
00332 
00333 void nsCSSValue::SetInitialValue()
00334 {
00335   Reset();
00336   mUnit = eCSSUnit_Initial;
00337 }
00338 
00339 void nsCSSValue::SetNoneValue()
00340 {
00341   Reset();
00342   mUnit = eCSSUnit_None;
00343 }
00344 
00345 void nsCSSValue::SetNormalValue()
00346 {
00347   Reset();
00348   mUnit = eCSSUnit_Normal;
00349 }
00350 
00351 void nsCSSValue::StartImageLoad(nsIDocument* aDocument, PRBool aIsBGImage) const
00352 {
00353   NS_PRECONDITION(eCSSUnit_URL == mUnit, "Not a URL value!");
00354   nsCSSValue::Image* image =
00355     new nsCSSValue::Image(mValue.mURL->mURI,
00356                           mValue.mURL->mString,
00357                           mValue.mURL->mReferrer,
00358                           aDocument, aIsBGImage);
00359   if (image) {
00360     if (image->mString) {
00361       nsCSSValue* writable = NS_CONST_CAST(nsCSSValue*, this);
00362       writable->SetImageValue(image);
00363     } else {
00364       delete image;
00365     }
00366   }
00367 }
00368 
00369 nsCSSValue::Image::Image(nsIURI* aURI, const PRUnichar* aString,
00370                          nsIURI* aReferrer, nsIDocument* aDocument,
00371                          PRBool aIsBGImage)
00372   : URL(aURI, aString, aReferrer)
00373 {
00374   MOZ_COUNT_CTOR(nsCSSValue::Image);
00375 
00376   // Check for failed mString allocation first
00377   if (!mString)
00378     return;
00379 
00380   // If the pref is enabled, force all background image loads to
00381   // complete before firing onload for the document.  Otherwise, background
00382   // image loads are special and don't block onload.
00383   PRInt32 loadFlag = (PRInt32)nsIRequest::LOAD_NORMAL;
00384   if (aIsBGImage) {
00385     static PRBool onloadAfterImageBackgroundLoads =
00386       nsContentUtils::GetBoolPref
00387         ("layout.fire_onload_after_image_background_loads");
00388     if (!onloadAfterImageBackgroundLoads) {
00389       loadFlag = (PRInt32)nsIRequest::LOAD_BACKGROUND;
00390     }
00391   }
00392 
00393   if (mURI &&
00394       nsContentUtils::CanLoadImage(mURI, aDocument, aDocument)) {
00395     nsContentUtils::LoadImage(mURI, aDocument, aReferrer, nsnull,
00396                               loadFlag,
00397                               getter_AddRefs(mRequest));
00398   }
00399 }
00400 
00401 nsCSSValue::Image::~Image()
00402 {
00403   MOZ_COUNT_DTOR(nsCSSValue::Image);
00404 }
00405 
00406 #ifdef DEBUG
00407 
00408 void nsCSSValue::AppendToString(nsAString& aBuffer,
00409                                 nsCSSProperty aPropID) const
00410 {
00411   if (eCSSUnit_Null == mUnit) {
00412     return;
00413   }
00414 
00415   if (-1 < aPropID) {
00416     AppendASCIItoUTF16(nsCSSProps::GetStringValue(aPropID), aBuffer);
00417     aBuffer.AppendLiteral(": ");
00418   }
00419 
00420   switch (mUnit) {
00421     case eCSSUnit_Image:
00422     case eCSSUnit_URL:      aBuffer.AppendLiteral("url(");       break;
00423     case eCSSUnit_Attr:     aBuffer.AppendLiteral("attr(");      break;
00424     case eCSSUnit_Counter:  aBuffer.AppendLiteral("counter(");   break;
00425     case eCSSUnit_Counters: aBuffer.AppendLiteral("counters(");  break;
00426     default:  break;
00427   }
00428   if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr)) {
00429     if (nsnull != mValue.mString) {
00430       aBuffer.Append(PRUnichar('"'));
00431       aBuffer.Append(mValue.mString);
00432       aBuffer.Append(PRUnichar('"'));
00433     }
00434     else {
00435       aBuffer.AppendLiteral("null str");
00436     }
00437   }
00438   else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
00439     nsAutoString intStr;
00440     intStr.AppendInt(mValue.mInt, 10);
00441     aBuffer.Append(intStr);
00442 
00443     aBuffer.AppendLiteral("[0x");
00444 
00445     intStr.Truncate();
00446     intStr.AppendInt(mValue.mInt, 16);
00447     aBuffer.Append(intStr);
00448 
00449     aBuffer.Append(PRUnichar(']'));
00450   }
00451   else if (eCSSUnit_Color == mUnit) {
00452     aBuffer.AppendLiteral("(0x");
00453 
00454     nsAutoString intStr;
00455     intStr.AppendInt(NS_GET_R(mValue.mColor), 16);
00456     aBuffer.Append(intStr);
00457 
00458     aBuffer.AppendLiteral(" 0x");
00459 
00460     intStr.Truncate();
00461     intStr.AppendInt(NS_GET_G(mValue.mColor), 16);
00462     aBuffer.Append(intStr);
00463 
00464     aBuffer.AppendLiteral(" 0x");
00465 
00466     intStr.Truncate();
00467     intStr.AppendInt(NS_GET_B(mValue.mColor), 16);
00468     aBuffer.Append(intStr);
00469 
00470     aBuffer.AppendLiteral(" 0x");
00471 
00472     intStr.Truncate();
00473     intStr.AppendInt(NS_GET_A(mValue.mColor), 16);
00474     aBuffer.Append(intStr);
00475 
00476     aBuffer.Append(PRUnichar(')'));
00477   }
00478   else if (eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters) {
00479     for (PRUint16 i = 0, i_end = mValue.mArray->Count(); i != i_end; ++i) {
00480       (*mValue.mArray)[i].AppendToString(aBuffer, aPropID);
00481     }
00482   }
00483   else if (eCSSUnit_URL == mUnit) {
00484     aBuffer.Append(mValue.mURL->mString);
00485   }
00486   else if (eCSSUnit_Image == mUnit) {
00487     aBuffer.Append(mValue.mImage->mString);
00488   }
00489   else if (eCSSUnit_Percent == mUnit) {
00490     nsAutoString floatString;
00491     floatString.AppendFloat(mValue.mFloat * 100.0f);
00492     aBuffer.Append(floatString);
00493   }
00494   else if (eCSSUnit_Percent < mUnit) {
00495     nsAutoString floatString;
00496     floatString.AppendFloat(mValue.mFloat);
00497     aBuffer.Append(floatString);
00498   }
00499 
00500   switch (mUnit) {
00501     case eCSSUnit_Null:         break;
00502     case eCSSUnit_Auto:         aBuffer.AppendLiteral("auto");     break;
00503     case eCSSUnit_Inherit:      aBuffer.AppendLiteral("inherit");  break;
00504     case eCSSUnit_Initial:      aBuffer.AppendLiteral("-moz-initial"); break;
00505     case eCSSUnit_None:         aBuffer.AppendLiteral("none");     break;
00506     case eCSSUnit_Normal:       aBuffer.AppendLiteral("normal");   break;
00507     case eCSSUnit_Array:
00508     case eCSSUnit_String:       break;
00509     case eCSSUnit_URL:
00510     case eCSSUnit_Image:
00511     case eCSSUnit_Attr:
00512     case eCSSUnit_Counter:
00513     case eCSSUnit_Counters:     aBuffer.Append(NS_LITERAL_STRING(")"));    break;
00514     case eCSSUnit_Integer:      aBuffer.AppendLiteral("int");  break;
00515     case eCSSUnit_Enumerated:   aBuffer.AppendLiteral("enum"); break;
00516     case eCSSUnit_Color:        aBuffer.AppendLiteral("rbga"); break;
00517     case eCSSUnit_Percent:      aBuffer.AppendLiteral("%");    break;
00518     case eCSSUnit_Number:       aBuffer.AppendLiteral("#");    break;
00519     case eCSSUnit_Inch:         aBuffer.AppendLiteral("in");   break;
00520     case eCSSUnit_Foot:         aBuffer.AppendLiteral("ft");   break;
00521     case eCSSUnit_Mile:         aBuffer.AppendLiteral("mi");   break;
00522     case eCSSUnit_Millimeter:   aBuffer.AppendLiteral("mm");   break;
00523     case eCSSUnit_Centimeter:   aBuffer.AppendLiteral("cm");   break;
00524     case eCSSUnit_Meter:        aBuffer.AppendLiteral("m");    break;
00525     case eCSSUnit_Kilometer:    aBuffer.AppendLiteral("km");   break;
00526     case eCSSUnit_Point:        aBuffer.AppendLiteral("pt");   break;
00527     case eCSSUnit_Pica:         aBuffer.AppendLiteral("pc");   break;
00528     case eCSSUnit_Didot:        aBuffer.AppendLiteral("dt");   break;
00529     case eCSSUnit_Cicero:       aBuffer.AppendLiteral("cc");   break;
00530     case eCSSUnit_EM:           aBuffer.AppendLiteral("em");   break;
00531     case eCSSUnit_EN:           aBuffer.AppendLiteral("en");   break;
00532     case eCSSUnit_XHeight:      aBuffer.AppendLiteral("ex");   break;
00533     case eCSSUnit_CapHeight:    aBuffer.AppendLiteral("cap");  break;
00534     case eCSSUnit_Char:         aBuffer.AppendLiteral("ch");   break;
00535     case eCSSUnit_Pixel:        aBuffer.AppendLiteral("px");   break;
00536     case eCSSUnit_Proportional: aBuffer.AppendLiteral("*");    break;
00537     case eCSSUnit_Degree:       aBuffer.AppendLiteral("deg");  break;
00538     case eCSSUnit_Grad:         aBuffer.AppendLiteral("grad"); break;
00539     case eCSSUnit_Radian:       aBuffer.AppendLiteral("rad");  break;
00540     case eCSSUnit_Hertz:        aBuffer.AppendLiteral("Hz");   break;
00541     case eCSSUnit_Kilohertz:    aBuffer.AppendLiteral("kHz");  break;
00542     case eCSSUnit_Seconds:      aBuffer.AppendLiteral("s");    break;
00543     case eCSSUnit_Milliseconds: aBuffer.AppendLiteral("ms");   break;
00544   }
00545   aBuffer.AppendLiteral(" ");
00546 }
00547 
00548 void nsCSSValue::ToString(nsAString& aBuffer,
00549                           nsCSSProperty aPropID) const
00550 {
00551   aBuffer.Truncate();
00552   AppendToString(aBuffer, aPropID);
00553 }
00554 
00555 #endif /* defined(DEBUG) */