Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / layout / style / nsCSSDataBlock.h
blobb087f65588c09f5eaa5f19e10d2961faff62b541
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
13 * License.
15 * The Original Code is nsCSSDataBlock.h.
17 * The Initial Developer of the Original Code is L. David Baron.
18 * Portions created by the Initial Developer are Copyright (C) 2003
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * L. David Baron <dbaron@dbaron.org> (original author)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * 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 ***** */
39 * compact representation of the property-value pairs within a CSS
40 * declaration, and the code for expanding and compacting it
43 #ifndef nsCSSDataBlock_h__
44 #define nsCSSDataBlock_h__
46 #include "nsCSSStruct.h"
47 #include "nsCSSProps.h"
48 #include "nsCSSPropertySet.h"
50 struct nsRuleData;
51 class nsCSSExpandedDataBlock;
53 namespace mozilla {
54 namespace css {
55 class Declaration;
59 /**
60 * An |nsCSSCompressedDataBlock| holds a usually-immutable chunk of
61 * property-value data for a CSS declaration block (which we misname a
62 * |css::Declaration|). Mutation is accomplished through
63 * |nsCSSExpandedDataBlock| or in some cases via direct slot access.
65 class nsCSSCompressedDataBlock {
66 private:
67 friend class nsCSSExpandedDataBlock;
69 // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock
70 // (in |Compress|) can create compressed data blocks.
71 nsCSSCompressedDataBlock() : mStyleBits(0) {}
73 public:
74 ~nsCSSCompressedDataBlock();
76 /**
77 * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
78 * rule using this block for storage.
80 void MapRuleInfoInto(nsRuleData *aRuleData) const;
82 /**
83 * Return the location at which the *value* for the property is
84 * stored, or null if the block does not contain a value for the
85 * property.
87 * Inefficient (by design).
89 * Must not be called for shorthands.
91 const nsCSSValue* ValueFor(nsCSSProperty aProperty) const;
93 /**
94 * Attempt to replace the value for |aProperty| stored in this block
95 * with the matching value stored in |aFromBlock|.
96 * This method will fail (returning PR_FALSE) if |aProperty| is not
97 * already in this block. It will set |aChanged| to true if it
98 * actually made a change to the block, but regardless, if it
99 * returns PR_TRUE, the value in |aFromBlock| was erased.
101 PRBool TryReplaceValue(nsCSSProperty aProperty,
102 nsCSSExpandedDataBlock& aFromBlock,
103 PRBool* aChanged);
106 * Clone this block, or return null on out-of-memory.
108 nsCSSCompressedDataBlock* Clone() const;
111 * Create a new nsCSSCompressedDataBlock holding no declarations.
113 static nsCSSCompressedDataBlock* CreateEmptyBlock();
115 private:
116 PRInt32 mStyleBits; // the structs for which we have data, according to
117 // |nsCachedStyleData::GetBitForSID|.
119 enum { block_chars = 4 }; // put 4 chars in the definition of the class
120 // to ensure size not inflated by alignment
122 void* operator new(size_t aBaseSize, size_t aDataSize) {
123 // subtract off the extra size to store |mBlock_|
124 return ::operator new(aBaseSize + aDataSize -
125 sizeof(char) * block_chars);
129 * Delete all the data stored in this block, and the block itself.
131 void Destroy();
133 char* mBlockEnd; // the byte after the last valid byte
134 char mBlock_[block_chars]; // must be the last member!
136 char* Block() { return mBlock_; }
137 char* BlockEnd() { return mBlockEnd; }
138 const char* Block() const { return mBlock_; }
139 const char* BlockEnd() const { return mBlockEnd; }
140 ptrdiff_t DataSize() const { return BlockEnd() - Block(); }
143 class nsCSSExpandedDataBlock {
144 friend class nsCSSCompressedDataBlock;
146 public:
147 nsCSSExpandedDataBlock();
148 ~nsCSSExpandedDataBlock();
150 private:
151 /* Property storage may not be accessed directly; use AddLonghandProperty
152 * and friends.
155 nsCSSFont mFont;
156 nsCSSDisplay mDisplay;
157 nsCSSMargin mMargin;
158 nsCSSList mList;
159 nsCSSPosition mPosition;
160 nsCSSTable mTable;
161 nsCSSColor mColor;
162 nsCSSContent mContent;
163 nsCSSText mText;
164 nsCSSUserInterface mUserInterface;
165 nsCSSAural mAural;
166 nsCSSPage mPage;
167 nsCSSBreaks mBreaks;
168 nsCSSXUL mXUL;
169 nsCSSSVG mSVG;
170 nsCSSColumn mColumn;
172 public:
174 * Transfer all of the state from a pair of compressed data blocks
175 * to this expanded block. This expanded block must be clear
176 * beforehand.
178 * This method DELETES both of the compressed data blocks it is
179 * passed. (This is necessary because ownership of sub-objects
180 * is transferred to the expanded block.)
182 void Expand(nsCSSCompressedDataBlock *aNormalBlock,
183 nsCSSCompressedDataBlock *aImportantBlock);
186 * Allocate new compressed blocks and transfer all of the state
187 * from this expanded block to the new blocks, clearing this
188 * expanded block. A normal block will always be allocated, but
189 * an important block will only be allocated if there are
190 * !important properties in the expanded block; otherwise
191 * |*aImportantBlock| will be set to null.
193 void Compress(nsCSSCompressedDataBlock **aNormalBlock,
194 nsCSSCompressedDataBlock **aImportantBlock);
197 * Copy a value into this expanded block. This does NOT destroy
198 * the source value object. |aProperty| cannot be a shorthand.
200 void AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue);
203 * Clear the state of this expanded block.
205 void Clear();
208 * Clear the data for the given property (including the set and
209 * important bits). Can be used with shorthand properties.
211 void ClearProperty(nsCSSProperty aPropID);
214 * Same as ClearProperty, but faster and cannot be used with shorthands.
216 void ClearLonghandProperty(nsCSSProperty aPropID);
219 * Transfer the state for |aPropID| (which may be a shorthand)
220 * from |aFromBlock| to this block. The property being transferred
221 * is !important if |aIsImportant| is true, and should replace an
222 * existing !important property regardless of its own importance
223 * if |aOverrideImportant| is true.
225 * Returns true if something changed, false otherwise. Calls
226 * |ValueAppended| on |aDeclaration| if the property was not
227 * previously set, or in any case if |aMustCallValueAppended| is true.
229 PRBool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
230 nsCSSProperty aPropID,
231 PRBool aIsImportant,
232 PRBool aOverrideImportant,
233 PRBool aMustCallValueAppended,
234 mozilla::css::Declaration* aDeclaration);
236 void AssertInitialState() {
237 #ifdef DEBUG
238 DoAssertInitialState();
239 #endif
242 private:
244 * Compute the size that will be occupied by the result of
245 * |Compress|.
247 struct ComputeSizeResult {
248 PRUint32 normal, important;
250 ComputeSizeResult ComputeSize();
252 void DoExpand(nsCSSCompressedDataBlock *aBlock, PRBool aImportant);
255 * Worker for TransferFromBlock; cannot be used with shorthands.
257 PRBool DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
258 nsCSSProperty aPropID,
259 PRBool aIsImportant,
260 PRBool aOverrideImportant,
261 PRBool aMustCallValueAppended,
262 mozilla::css::Declaration* aDeclaration);
264 #ifdef DEBUG
265 void DoAssertInitialState();
266 #endif
268 // XXX These could probably be pointer-to-member, if the casting can
269 // be done correctly.
270 static const size_t kOffsetTable[];
273 * mPropertiesSet stores a bit for every property that is present,
274 * to optimize compression of blocks with small numbers of
275 * properties (the norm) and to allow quickly checking whether a
276 * property is set in this block.
278 nsCSSPropertySet mPropertiesSet;
280 * mPropertiesImportant indicates which properties are '!important'.
282 nsCSSPropertySet mPropertiesImportant;
285 * Return the storage location within |this| of the value of the
286 * property |aProperty|.
288 nsCSSValue* PropertyAt(nsCSSProperty aProperty) {
289 size_t offset = nsCSSExpandedDataBlock::kOffsetTable[aProperty];
290 return reinterpret_cast<nsCSSValue*>(reinterpret_cast<char*>(this) +
291 offset);
294 void SetPropertyBit(nsCSSProperty aProperty) {
295 mPropertiesSet.AddProperty(aProperty);
298 void ClearPropertyBit(nsCSSProperty aProperty) {
299 mPropertiesSet.RemoveProperty(aProperty);
302 PRBool HasPropertyBit(nsCSSProperty aProperty) {
303 return mPropertiesSet.HasProperty(aProperty);
306 void SetImportantBit(nsCSSProperty aProperty) {
307 mPropertiesImportant.AddProperty(aProperty);
310 void ClearImportantBit(nsCSSProperty aProperty) {
311 mPropertiesImportant.RemoveProperty(aProperty);
314 PRBool HasImportantBit(nsCSSProperty aProperty) {
315 return mPropertiesImportant.HasProperty(aProperty);
318 void ClearSets() {
319 mPropertiesSet.Empty();
320 mPropertiesImportant.Empty();
324 #endif /* !defined(nsCSSDataBlock_h__) */