Back to index

lightning-sunbird  0.9+nobinonly
nsCSSDataBlock.h
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is nsCSSDataBlock.h.
00015  *
00016  * The Initial Developer of the Original Code is L. David Baron.
00017  * Portions created by the Initial Developer are Copyright (C) 2003
00018  * the Initial Developer. All Rights Reserved.
00019  *
00020  * Contributor(s):
00021  *   L. David Baron <dbaron@dbaron.org> (original author)
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 #ifndef nsCSSDataBlock_h__
00037 #define nsCSSDataBlock_h__
00038 
00039 #include "nsCSSStruct.h"
00040 
00041 struct nsRuleData;
00042 
00043 class nsCSSExpandedDataBlock;
00044 
00051 class nsCSSCompressedDataBlock {
00052 public:
00053     friend class nsCSSExpandedDataBlock;
00054 
00059     nsresult MapRuleInfoInto(nsRuleData *aRuleData) const;
00060 
00069     const void* StorageFor(nsCSSProperty aProperty) const;
00070 
00074     nsCSSCompressedDataBlock* Clone() const;
00075 
00079     void Destroy();
00080 
00084     static nsCSSCompressedDataBlock* CreateEmptyBlock();
00085 
00086 private:
00087     PRInt32 mStyleBits; // the structs for which we have data, according to
00088                         // |nsCachedStyleData::GetBitForSID|.
00089 
00090     enum { block_chars = 4 }; // put 4 chars in the definition of the class
00091                               // to ensure size not inflated by alignment
00092 
00093     void* operator new(size_t aBaseSize, size_t aDataSize) {
00094         // subtract off the extra size to store |mBlock_|
00095         return ::operator new(aBaseSize + aDataSize -
00096                               sizeof(char) * block_chars);
00097     }
00098 
00099     nsCSSCompressedDataBlock() : mStyleBits(0) {}
00100 
00101     // Only this class (through |Destroy|) or nsCSSExpandedDataBlock (in
00102     // |Expand|) can delete compressed data blocks.
00103     ~nsCSSCompressedDataBlock() { }
00104 
00105     char* mBlockEnd; // the byte after the last valid byte
00106     char mBlock_[block_chars]; // must be the last member!
00107 
00108     char* Block() { return mBlock_; }
00109     char* BlockEnd() { return mBlockEnd; }
00110     const char* Block() const { return mBlock_; }
00111     const char* BlockEnd() const { return mBlockEnd; }
00112     ptrdiff_t DataSize() const { return BlockEnd() - Block(); }
00113 };
00114 
00115 class nsCSSExpandedDataBlock {
00116 public:
00117     nsCSSExpandedDataBlock();
00118     ~nsCSSExpandedDataBlock();
00119     /*
00120      * When setting properties in an |nsCSSExpandedDataBlock|, callers
00121      * must make the appropriate |AddPropertyBit| call.
00122      */
00123 
00124     nsCSSFont mFont;
00125     nsCSSDisplay mDisplay;
00126     nsCSSMargin mMargin;
00127     nsCSSList mList;
00128     nsCSSPosition mPosition;
00129     nsCSSTable mTable;
00130     nsCSSColor mColor;
00131     nsCSSContent mContent;
00132     nsCSSText mText;
00133     nsCSSUserInterface mUserInterface;
00134     nsCSSAural mAural;
00135     nsCSSPage mPage;
00136     nsCSSBreaks mBreaks;
00137     nsCSSXUL mXUL;
00138 #ifdef MOZ_SVG
00139     nsCSSSVG mSVG;
00140 #endif
00141     nsCSSColumn mColumn;
00142 
00153     void Expand(nsCSSCompressedDataBlock **aNormalBlock,
00154                 nsCSSCompressedDataBlock **aImportantBlock);
00155 
00161     void Compress(nsCSSCompressedDataBlock **aNormalBlock,
00162                   nsCSSCompressedDataBlock **aImportantBlock);
00163 
00167     void Clear();
00168 
00173     void ClearProperty(nsCSSProperty aPropID);
00174 
00175     void AssertInitialState() {
00176 #ifdef DEBUG
00177         DoAssertInitialState();
00178 #endif
00179     }
00180 
00181 private:
00186     struct ComputeSizeResult {
00187         PRUint32 normal, important;
00188     };
00189     ComputeSizeResult ComputeSize();
00190 
00191     void DoExpand(nsCSSCompressedDataBlock *aBlock, PRBool aImportant);
00192 
00193 #ifdef DEBUG
00194     void DoAssertInitialState();
00195 #endif
00196 
00197     struct PropertyOffsetInfo {
00198         // XXX These could probably be pointer-to-member, if the casting can
00199         // be done correctly.
00200         size_t block_offset; // offset of value in nsCSSExpandedDataBlock
00201         size_t ruledata_struct_offset; // offset of nsRuleData* in nsRuleData
00202         size_t ruledata_member_offset; // offset of value in nsRuleData*
00203     };
00204 
00205     static const PropertyOffsetInfo kOffsetTable[];
00206 
00207     typedef PRUint8 property_set_type;
00208     enum { kPropertiesSetChunkSize = 8 }; // number of bits in
00209                                           // |property_set_type|.
00210     // number of |property_set_type|s in the set
00211     enum { kPropertiesSetChunkCount =
00212              (eCSSProperty_COUNT_no_shorthands + (kPropertiesSetChunkSize-1)) /
00213              kPropertiesSetChunkSize };
00214     /*
00215      * mPropertiesSet stores a bit for every property that is present,
00216      * to optimize compression of blocks with small numbers of
00217      * properties (the norm) and to allow quickly checking whether a
00218      * property is set in this block.
00219      */
00220     property_set_type mPropertiesSet[kPropertiesSetChunkCount];
00221     /*
00222      * mPropertiesImportant indicates which properties are '!important'.
00223      */
00224     property_set_type mPropertiesImportant[kPropertiesSetChunkCount];
00225 
00226 public:
00227     /*
00228      * Return the storage location within |this| of the value of the
00229      * property (i.e., either an |nsCSSValue*|, |nsCSSRect*|, or
00230      * |nsCSSValueList**| (etc.).
00231      */
00232     void* PropertyAt(nsCSSProperty aProperty) {
00233         const PropertyOffsetInfo& offsets =
00234             nsCSSExpandedDataBlock::kOffsetTable[aProperty];
00235         return NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(char*, this) +
00236                                           offsets.block_offset);
00237     }
00238 
00239     /*
00240      * Return the storage location within |aRuleData| of the value of
00241      * the property (i.e., either an |nsCSSValue*|, |nsCSSRect*|, or
00242      * |nsCSSValueList**| (etc.).
00243      */
00244     static void* RuleDataPropertyAt(nsRuleData *aRuleData,
00245                                     nsCSSProperty aProperty) {
00246         const PropertyOffsetInfo& offsets =
00247             nsCSSExpandedDataBlock::kOffsetTable[aProperty];
00248         NS_ASSERTION(offsets.ruledata_struct_offset != size_t(-1),
00249                      "property should not use CSS_PROP_BACKENDONLY");
00250         char* cssstruct = *NS_REINTERPRET_CAST(char**,
00251                               NS_REINTERPRET_CAST(char*, aRuleData) +
00252                               offsets.ruledata_struct_offset);
00253         return NS_REINTERPRET_CAST(void*,
00254                                    cssstruct + offsets.ruledata_member_offset);
00255     }
00256 
00257     void AssertInSetRange(nsCSSProperty aProperty) {
00258         NS_ASSERTION(0 <= aProperty &&
00259                      aProperty < eCSSProperty_COUNT_no_shorthands,
00260                      "out of bounds");
00261     }
00262 
00263     void SetPropertyBit(nsCSSProperty aProperty) {
00264         AssertInSetRange(aProperty);
00265         mPropertiesSet[aProperty / kPropertiesSetChunkSize] |=
00266             property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
00267     }
00268 
00269     void ClearPropertyBit(nsCSSProperty aProperty) {
00270         AssertInSetRange(aProperty);
00271         mPropertiesSet[aProperty / kPropertiesSetChunkSize] &=
00272             ~property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
00273     }
00274 
00275     PRBool HasPropertyBit(nsCSSProperty aProperty) {
00276         AssertInSetRange(aProperty);
00277         return (mPropertiesSet[aProperty / kPropertiesSetChunkSize] &
00278                 (1 << (aProperty % kPropertiesSetChunkSize))) != 0;
00279     }
00280 
00281     void SetImportantBit(nsCSSProperty aProperty) {
00282         AssertInSetRange(aProperty);
00283         mPropertiesImportant[aProperty / kPropertiesSetChunkSize] |=
00284             property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
00285     }
00286 
00287     void ClearImportantBit(nsCSSProperty aProperty) {
00288         AssertInSetRange(aProperty);
00289         mPropertiesImportant[aProperty / kPropertiesSetChunkSize] &=
00290             ~property_set_type(1 << (aProperty % kPropertiesSetChunkSize));
00291     }
00292 
00293     PRBool HasImportantBit(nsCSSProperty aProperty) {
00294         AssertInSetRange(aProperty);
00295         return (mPropertiesImportant[aProperty / kPropertiesSetChunkSize] &
00296                 (1 << (aProperty % kPropertiesSetChunkSize))) != 0;
00297     }
00298 
00299     void ClearSets() {
00300         memset(mPropertiesSet, 0, sizeof(mPropertiesSet));
00301         memset(mPropertiesImportant, 0, sizeof(mPropertiesImportant));
00302     }
00303 };
00304 
00305 #endif /* !defined(nsCSSDataBlock_h__) */