Back to index

lightning-sunbird  0.9+nobinonly
nsCSSValue.h
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 #ifndef nsCSSValue_h___
00038 #define nsCSSValue_h___
00039 
00040 #include "nsColor.h"
00041 #include "nsString.h"
00042 #include "nsCRT.h"
00043 #include "nsCoord.h"
00044 #include "nsCSSProperty.h"
00045 #include "nsUnitConversion.h"
00046 #include "nsIURI.h"
00047 #include "nsCOMPtr.h"
00048 #include "nsAutoPtr.h"
00049 
00050 class imgIRequest;
00051 class nsIDocument;
00052 
00053 enum nsCSSUnit {
00054   eCSSUnit_Null         = 0,      // (n/a) null unit, value is not specified
00055   eCSSUnit_Auto         = 1,      // (n/a) value is algorithmic
00056   eCSSUnit_Inherit      = 2,      // (n/a) value is inherited
00057   eCSSUnit_Initial      = 3,      // (n/a) value is default UA value
00058   eCSSUnit_None         = 4,      // (n/a) value is none
00059   eCSSUnit_Normal       = 5,      // (n/a) value is normal (algorithmic, different than auto)
00060   eCSSUnit_String       = 10,     // (PRUnichar*) a string value
00061   eCSSUnit_Attr         = 11,     // (PRUnichar*) a attr(string) value
00062   eCSSUnit_Array        = 20,     // (nsCSSValue::Array*) a list of values
00063   eCSSUnit_Counter      = 21,     // (nsCSSValue::Array*) a counter(string,[string]) value
00064   eCSSUnit_Counters     = 22,     // (nsCSSValue::Array*) a counters(string,string[,string]) value
00065   eCSSUnit_URL          = 30,     // (nsCSSValue::URL*) value
00066   eCSSUnit_Image        = 31,     // (nsCSSValue::Image*) value
00067   eCSSUnit_Integer      = 50,     // (int) simple value
00068   eCSSUnit_Enumerated   = 51,     // (int) value has enumerated meaning
00069   eCSSUnit_Color        = 80,     // (color) an RGBA value
00070   eCSSUnit_Percent      = 90,     // (float) 1.0 == 100%) value is percentage of something
00071   eCSSUnit_Number       = 91,     // (float) value is numeric (usually multiplier, different behavior that percent)
00072 
00073   // Length units - fixed
00074   // US English
00075   eCSSUnit_Inch         = 100,    // (float) 0.0254 meters
00076   eCSSUnit_Foot         = 101,    // (float) 12 inches
00077   eCSSUnit_Mile         = 102,    // (float) 5280 feet
00078 
00079   // Metric
00080   eCSSUnit_Millimeter   = 207,    // (float) 1/1000 meter
00081   eCSSUnit_Centimeter   = 208,    // (float) 1/100 meter
00082   eCSSUnit_Meter        = 210,    // (float) Standard length
00083   eCSSUnit_Kilometer    = 213,    // (float) 1000 meters
00084 
00085   // US Typographic
00086   eCSSUnit_Point        = 300,    // (float) 1/72 inch
00087   eCSSUnit_Pica         = 301,    // (float) 12 points == 1/6 inch
00088 
00089   // European Typographic
00090   eCSSUnit_Didot        = 400,    // (float) 15 didots == 16 points
00091   eCSSUnit_Cicero       = 401,    // (float) 12 didots
00092 
00093   // Length units - relative
00094   // Font relative measure
00095   eCSSUnit_EM           = 800,    // (float) == current font size
00096   eCSSUnit_EN           = 801,    // (float) .5 em
00097   eCSSUnit_XHeight      = 802,    // (float) distance from top of lower case x to baseline
00098   eCSSUnit_CapHeight    = 803,    // (float) distance from top of uppercase case H to baseline
00099   eCSSUnit_Char         = 804,    // (float) number of characters, used for width with monospace font
00100 
00101   // Screen relative measure
00102   eCSSUnit_Pixel        = 900,    // (float) CSS pixel unit
00103 
00104   // Proportional Unit (for columns in tables)
00105   eCSSUnit_Proportional = 950, 
00106 
00107   // Angular units
00108   eCSSUnit_Degree       = 1000,    // (float) 360 per circle
00109   eCSSUnit_Grad         = 1001,    // (float) 400 per circle
00110   eCSSUnit_Radian       = 1002,    // (float) 2*pi per circle
00111 
00112   // Frequency units
00113   eCSSUnit_Hertz        = 2000,    // (float) 1/seconds
00114   eCSSUnit_Kilohertz    = 2001,    // (float) 1000 Hertz
00115 
00116   // Time units
00117   eCSSUnit_Seconds      = 3000,    // (float) Standard time
00118   eCSSUnit_Milliseconds = 3001     // (float) 1/1000 second
00119 };
00120 
00121 class nsCSSValue {
00122 public:
00123   struct Array;
00124   friend struct Array;
00125 
00126   struct URL;
00127   friend struct URL;
00128 
00129   struct Image;
00130   friend struct Image;
00131   
00132   // for valueless units only (null, auto, inherit, none, normal)
00133   explicit nsCSSValue(nsCSSUnit aUnit = eCSSUnit_Null)
00134     : mUnit(aUnit)
00135   {
00136     NS_ASSERTION(aUnit <= eCSSUnit_Normal, "not a valueless unit");
00137     if (aUnit > eCSSUnit_Normal) {
00138       mUnit = eCSSUnit_Null;
00139     }
00140     mValue.mInt = 0;
00141   }
00142 
00143   nsCSSValue(PRInt32 aValue, nsCSSUnit aUnit) NS_HIDDEN;
00144   nsCSSValue(float aValue, nsCSSUnit aUnit) NS_HIDDEN;
00145   nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit) NS_HIDDEN;
00146   explicit nsCSSValue(nscolor aValue) NS_HIDDEN;
00147   nsCSSValue(Array* aArray, nsCSSUnit aUnit) NS_HIDDEN;
00148   explicit nsCSSValue(URL* aValue) NS_HIDDEN;
00149   explicit nsCSSValue(Image* aValue) NS_HIDDEN;
00150   nsCSSValue(const nsCSSValue& aCopy) NS_HIDDEN;
00151   NS_FASTCALL ~nsCSSValue() NS_HIDDEN;
00152 
00153   NS_HIDDEN_(nsCSSValue&)  operator=(const nsCSSValue& aCopy);
00154   NS_HIDDEN_(PRBool)      operator==(const nsCSSValue& aOther) const;
00155 
00156   PRBool operator!=(const nsCSSValue& aOther) const
00157   {
00158     return !(*this == aOther);
00159   }
00160 
00161   nsCSSUnit GetUnit() const { return mUnit; };
00162   PRBool    IsLengthUnit() const
00163     { return PRBool((eCSSUnit_Inch <= mUnit) && (mUnit <= eCSSUnit_Proportional)); }
00164   PRBool    IsFixedLengthUnit() const  
00165     { return PRBool((eCSSUnit_Inch <= mUnit) && (mUnit <= eCSSUnit_Cicero)); }
00166   PRBool    IsRelativeLengthUnit() const  
00167     { return PRBool((eCSSUnit_EM <= mUnit) && (mUnit <= eCSSUnit_Proportional)); }
00168   PRBool    IsAngularUnit() const  
00169     { return PRBool((eCSSUnit_Degree <= mUnit) && (mUnit <= eCSSUnit_Radian)); }
00170   PRBool    IsFrequencyUnit() const  
00171     { return PRBool((eCSSUnit_Hertz <= mUnit) && (mUnit <= eCSSUnit_Kilohertz)); }
00172   PRBool    IsTimeUnit() const  
00173     { return PRBool((eCSSUnit_Seconds <= mUnit) && (mUnit <= eCSSUnit_Milliseconds)); }
00174 
00175   PRInt32 GetIntValue() const
00176   {
00177     NS_ASSERTION(mUnit == eCSSUnit_Integer || mUnit == eCSSUnit_Enumerated,
00178                  "not an int value");
00179     return mValue.mInt;
00180   }
00181 
00182   float GetPercentValue() const
00183   {
00184     NS_ASSERTION(mUnit == eCSSUnit_Percent, "not a percent value");
00185     return mValue.mFloat;
00186   }
00187 
00188   float GetFloatValue() const
00189   {
00190     NS_ASSERTION(eCSSUnit_Number <= mUnit, "not a float value");
00191     return mValue.mFloat;
00192   }
00193 
00194   nsAString& GetStringValue(nsAString& aBuffer) const
00195   {
00196     NS_ASSERTION(eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Attr,
00197                  "not a string value");
00198     aBuffer.Truncate();
00199     if (nsnull != mValue.mString) {
00200       aBuffer.Append(mValue.mString);
00201     }
00202     return aBuffer;
00203   }
00204 
00205   const PRUnichar* GetStringBufferValue() const
00206   {
00207     NS_ASSERTION(eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Attr,
00208                  "not a string value");
00209     return mValue.mString;
00210   }
00211 
00212   nscolor GetColorValue() const
00213   {
00214     NS_ASSERTION((mUnit == eCSSUnit_Color), "not a color value");
00215     return mValue.mColor;
00216   }
00217 
00218   Array* GetArrayValue() const
00219   {
00220     NS_ASSERTION(eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters,
00221                  "not an array value");
00222     return mValue.mArray;
00223   }
00224 
00225   nsIURI* GetURLValue() const
00226   {
00227     NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
00228                  "not a URL value");
00229     return mUnit == eCSSUnit_URL ?
00230       mValue.mURL->mURI : mValue.mImage->mURI;
00231   }
00232 
00233   const PRUnichar* GetOriginalURLValue() const
00234   {
00235     NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
00236                  "not a URL value");
00237     return mUnit == eCSSUnit_URL ?
00238       mValue.mURL->mString : mValue.mImage->mString;
00239   }
00240 
00241   // Not making this inline because that would force us to include
00242   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
00243   // all over.
00244   NS_HIDDEN_(imgIRequest*) GetImageValue() const;
00245 
00246   NS_HIDDEN_(nscoord)   GetLengthTwips() const;
00247 
00248   NS_HIDDEN_(void)  Reset()  // sets to null
00249   {
00250     if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr) &&
00251         (nsnull != mValue.mString)) {
00252       NS_Free(mValue.mString);
00253     } else if (eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters) {
00254       mValue.mArray->Release();
00255     } else if (eCSSUnit_URL == mUnit) {
00256       mValue.mURL->Release();
00257     } else if (eCSSUnit_Image == mUnit) {
00258       mValue.mImage->Release();
00259     }
00260     mUnit = eCSSUnit_Null;
00261     mValue.mInt = 0;
00262   }
00263 
00264   NS_HIDDEN_(void)  SetIntValue(PRInt32 aValue, nsCSSUnit aUnit);
00265   NS_HIDDEN_(void)  SetPercentValue(float aValue);
00266   NS_HIDDEN_(void)  SetFloatValue(float aValue, nsCSSUnit aUnit);
00267   NS_HIDDEN_(void)  SetStringValue(const nsAString& aValue, nsCSSUnit aUnit);
00268   NS_HIDDEN_(void)  SetColorValue(nscolor aValue);
00269   NS_HIDDEN_(void)  SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
00270   NS_HIDDEN_(void)  SetURLValue(nsCSSValue::URL* aURI);
00271   NS_HIDDEN_(void)  SetImageValue(nsCSSValue::Image* aImage);
00272   NS_HIDDEN_(void)  SetAutoValue();
00273   NS_HIDDEN_(void)  SetInheritValue();
00274   NS_HIDDEN_(void)  SetInitialValue();
00275   NS_HIDDEN_(void)  SetNoneValue();
00276   NS_HIDDEN_(void)  SetNormalValue();
00277   NS_HIDDEN_(void)  StartImageLoad(nsIDocument* aDocument,
00278                                    PRBool aIsBGImage = PR_FALSE)
00279                                    const;  // Not really const, but pretending
00280 
00281 #ifdef DEBUG
00282   NS_HIDDEN_(void)
00283     AppendToString(nsAString& aBuffer,
00284                    nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const;
00285   NS_HIDDEN_(void)
00286     ToString(nsAString& aBuffer,
00287              nsCSSProperty aPropID = eCSSProperty_UNKNOWN) const;
00288 #endif
00289 
00290   MOZ_DECL_CTOR_COUNTER(nsCSSValue::Array)
00291 
00292   struct Array {
00293 
00294     // return |Array| with reference count of zero
00295     static Array* Create(PRUint16 aItemCount) {
00296       return new (aItemCount) Array(aItemCount);
00297     }
00298 
00299     nsCSSValue& operator[](PRUint16 aIndex) {
00300       NS_ASSERTION(aIndex < mCount, "out of range");
00301       return *(First() + aIndex);
00302     }
00303 
00304     const nsCSSValue& operator[](PRUint16 aIndex) const {
00305       NS_ASSERTION(aIndex < mCount, "out of range");
00306       return *(First() + aIndex);
00307     }
00308 
00309     nsCSSValue& Item(PRUint16 aIndex) { return (*this)[aIndex]; }
00310     const nsCSSValue& Item(PRUint16 aIndex) const { return (*this)[aIndex]; }
00311 
00312     PRUint16 Count() { return mCount; }
00313 
00314     PRBool operator==(const Array& aOther)
00315     {
00316       if (mCount != aOther.mCount)
00317         return PR_FALSE;
00318       for (PRUint16 i = 0; i < mCount; ++i)
00319         if ((*this)[i] != aOther[i])
00320           return PR_FALSE;
00321       return PR_TRUE;
00322     }
00323 
00324     void AddRef() {
00325       if (mRefCnt == PR_UINT16_MAX) {
00326         NS_WARNING("refcount overflow, leaking nsCSSValue::Array");
00327         return;
00328       }
00329       ++mRefCnt;
00330       NS_LOG_ADDREF(this, mRefCnt, "nsCSSValue::Array", sizeof(*this));
00331     }
00332     void Release() {
00333       if (mRefCnt == PR_UINT16_MAX) {
00334         NS_WARNING("refcount overflow, leaking nsCSSValue::Array");
00335         return;
00336       }
00337       --mRefCnt;
00338       NS_LOG_RELEASE(this, mRefCnt, "nsCSSValue::Array");
00339       if (mRefCnt == 0)
00340         delete this;
00341     }
00342 
00343   private:
00344 
00345     PRUint16 mRefCnt;
00346     PRUint16 mCount;
00347 
00348     void* operator new(size_t aSelfSize, PRUint16 aItemCount) CPP_THROW_NEW {
00349       return ::operator new(aSelfSize + sizeof(nsCSSValue)*aItemCount);
00350     }
00351 
00352     void operator delete(void* aPtr) { ::operator delete(aPtr); }
00353 
00354     nsCSSValue* First() {
00355       return (nsCSSValue*) (((char*)this) + sizeof(*this));
00356     }
00357 
00358     const nsCSSValue* First() const {
00359       return (const nsCSSValue*) (((const char*)this) + sizeof(*this));
00360     }
00361 
00362 #define CSSVALUE_LIST_FOR_VALUES(var)                                         \
00363   for (nsCSSValue *var = First(), *var##_end = var + mCount;                  \
00364        var != var##_end; ++var)
00365 
00366     Array(PRUint16 aItemCount)
00367       : mRefCnt(0)
00368       , mCount(aItemCount)
00369     {
00370       MOZ_COUNT_CTOR(nsCSSValue::Array);
00371       CSSVALUE_LIST_FOR_VALUES(val) {
00372         new (val) nsCSSValue();
00373       }
00374     }
00375 
00376     ~Array()
00377     {
00378       MOZ_COUNT_DTOR(nsCSSValue::Array);
00379       CSSVALUE_LIST_FOR_VALUES(val) {
00380         val->~nsCSSValue();
00381       }
00382     }
00383 
00384 #undef CSSVALUE_LIST_FOR_VALUES
00385 
00386   private:
00387     Array(const Array& aOther); // not to be implemented
00388   };
00389 
00390   MOZ_DECL_CTOR_COUNTER(nsCSSValue::URL)
00391 
00392   struct URL {
00393     // Caller must delete this object immediately if the allocation of
00394     // |mString| fails.
00395     URL(nsIURI* aURI, const PRUnichar* aString, nsIURI* aReferrer)
00396       : mURI(aURI),
00397         mString(ToNewUnicode(nsDependentString(aString))),
00398         mReferrer(aReferrer),
00399         mRefCnt(0)
00400     {
00401       MOZ_COUNT_CTOR(nsCSSValue::URL);
00402     }
00403 
00404     ~URL()
00405     {
00406       // null |mString| isn't valid normally, but is checked by callers
00407       // of the constructor
00408       if (mString)
00409         NS_Free(mString);
00410       MOZ_COUNT_DTOR(nsCSSValue::URL);
00411     }
00412 
00413     PRBool operator==(const URL& aOther)
00414     {
00415       PRBool eq;
00416       return nsCRT::strcmp(mString, aOther.mString) == 0 &&
00417              (mURI == aOther.mURI || // handles null == null
00418               (mURI && aOther.mURI &&
00419                NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
00420                eq));
00421     }
00422 
00423     nsCOMPtr<nsIURI> mURI; // null == invalid URL
00424     PRUnichar* mString;
00425     nsCOMPtr<nsIURI> mReferrer;
00426 
00427     void AddRef() { ++mRefCnt; }
00428     void Release() { if (--mRefCnt == 0) delete this; }
00429   protected:
00430     nsrefcnt mRefCnt;
00431   };
00432 
00433   MOZ_DECL_CTOR_COUNTER(nsCSSValue::Image)
00434 
00435   struct Image : public URL {
00436     // Not making the constructor and destructor inline because that would
00437     // force us to include imgIRequest.h, which leads to REQUIRES hell, since
00438     // this header is included all over.
00439     Image(nsIURI* aURI, const PRUnichar* aString, nsIURI* aReferrer,
00440           nsIDocument* aDocument, PRBool aIsBGImage = PR_FALSE) NS_HIDDEN;
00441     ~Image() NS_HIDDEN;
00442 
00443     // Inherit operator== from nsCSSValue::URL
00444 
00445     nsCOMPtr<imgIRequest> mRequest; // null == image load blocked or somehow failed
00446 
00447     // Override AddRef/Release so we delete ourselves via the right pointer.
00448     void AddRef() { ++mRefCnt; }
00449     void Release() { if (--mRefCnt == 0) delete this; }
00450   };
00451 
00452 protected:
00453   nsCSSUnit mUnit;
00454   union {
00455     PRInt32    mInt;
00456     float      mFloat;
00457     PRUnichar* mString;
00458     nscolor    mColor;
00459     Array*     mArray;
00460     URL*       mURL;
00461     Image*     mImage;
00462   }         mValue;
00463 };
00464 
00465 #endif /* nsCSSValue_h___ */
00466