1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is nsCSSDataBlock.h.
16 * The Initial Developer of the Original Code is L. David Baron.
17 * Portions created by the Initial Developer are Copyright (C) 2003
18 * the Initial Developer. All Rights Reserved.
21 * L. David Baron <dbaron@dbaron.org> (original author)
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * compact representation of the property-value pairs within a CSS
39 * declaration, and the code for expanding and compacting it
42 #ifndef nsCSSDataBlock_h__
43 #define nsCSSDataBlock_h__
45 #include "nsCSSStruct.h"
49 class nsCSSExpandedDataBlock
;
52 * An |nsCSSCompressedDataBlock| holds an immutable chunk of
53 * property-value data for a CSS declaration block (which we misname a
54 * |nsCSSDeclaration|). Mutation is accomplished through
55 * |nsCSSExpandedDataBlock|.
57 class nsCSSCompressedDataBlock
{
59 friend class nsCSSExpandedDataBlock
;
62 * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
63 * rule using this block for storage.
65 nsresult
MapRuleInfoInto(nsRuleData
*aRuleData
) const;
68 * Return the location at which the *value* for the property is
69 * stored, or null if the block does not contain a value for the
70 * property. This is either an |nsCSSValue*|, |nsCSSRect*|, or an
71 * |nsCSSValueList**|, etc.
73 * Inefficient (by design).
75 const void* StorageFor(nsCSSProperty aProperty
) const;
78 * Clone this block, or return null on out-of-memory.
80 nsCSSCompressedDataBlock
* Clone() const;
83 * Delete all the data stored in this block, and the block itself.
88 * Create a new nsCSSCompressedDataBlock holding no declarations.
90 static nsCSSCompressedDataBlock
* CreateEmptyBlock();
93 PRInt32 mStyleBits
; // the structs for which we have data, according to
94 // |nsCachedStyleData::GetBitForSID|.
96 enum { block_chars
= 4 }; // put 4 chars in the definition of the class
97 // to ensure size not inflated by alignment
99 void* operator new(size_t aBaseSize
, size_t aDataSize
) {
100 // subtract off the extra size to store |mBlock_|
101 return ::operator new(aBaseSize
+ aDataSize
-
102 sizeof(char) * block_chars
);
105 nsCSSCompressedDataBlock() : mStyleBits(0) {}
107 // Only this class (through |Destroy|) or nsCSSExpandedDataBlock (in
108 // |Expand|) can delete compressed data blocks.
109 ~nsCSSCompressedDataBlock() { }
111 char* mBlockEnd
; // the byte after the last valid byte
112 char mBlock_
[block_chars
]; // must be the last member!
114 char* Block() { return mBlock_
; }
115 char* BlockEnd() { return mBlockEnd
; }
116 const char* Block() const { return mBlock_
; }
117 const char* BlockEnd() const { return mBlockEnd
; }
118 ptrdiff_t DataSize() const { return BlockEnd() - Block(); }
121 class nsCSSExpandedDataBlock
{
123 nsCSSExpandedDataBlock();
124 ~nsCSSExpandedDataBlock();
126 * When setting properties in an |nsCSSExpandedDataBlock|, callers
127 * must make the appropriate |AddPropertyBit| call.
131 nsCSSDisplay mDisplay
;
134 nsCSSPosition mPosition
;
137 nsCSSContent mContent
;
139 nsCSSUserInterface mUserInterface
;
150 * Transfer all of the state from the compressed block to this
151 * expanded block. The state of this expanded block must be clear
154 * The compressed block passed in IS DESTROYED by this method and
155 * set to null, and thus cannot be used again. (This is necessary
156 * because ownership of sub-objects is transferred to the expanded
159 void Expand(nsCSSCompressedDataBlock
**aNormalBlock
,
160 nsCSSCompressedDataBlock
**aImportantBlock
);
163 * Allocate a new compressed block and transfer all of the state
164 * from this expanded block to the new compressed block, clearing
165 * the state of this expanded block.
167 void Compress(nsCSSCompressedDataBlock
**aNormalBlock
,
168 nsCSSCompressedDataBlock
**aImportantBlock
);
171 * Clear (and thus destroy) the state of this expanded block.
176 * Clear the data for the given property (including the set and
179 void ClearProperty(nsCSSProperty aPropID
);
181 void AssertInitialState() {
183 DoAssertInitialState();
189 * Compute the size that will be occupied by the result of
192 struct ComputeSizeResult
{
193 PRUint32 normal
, important
;
195 ComputeSizeResult
ComputeSize();
197 void DoExpand(nsCSSCompressedDataBlock
*aBlock
, PRBool aImportant
);
200 void DoAssertInitialState();
203 struct PropertyOffsetInfo
{
204 // XXX These could probably be pointer-to-member, if the casting can
205 // be done correctly.
206 size_t block_offset
; // offset of value in nsCSSExpandedDataBlock
207 size_t ruledata_struct_offset
; // offset of nsRuleData* in nsRuleData
208 size_t ruledata_member_offset
; // offset of value in nsRuleData*
211 static const PropertyOffsetInfo kOffsetTable
[];
213 typedef PRUint8 property_set_type
;
214 enum { kPropertiesSetChunkSize
= 8 }; // number of bits in
215 // |property_set_type|.
216 // number of |property_set_type|s in the set
217 enum { kPropertiesSetChunkCount
=
218 (eCSSProperty_COUNT_no_shorthands
+ (kPropertiesSetChunkSize
-1)) /
219 kPropertiesSetChunkSize
};
221 * mPropertiesSet stores a bit for every property that is present,
222 * to optimize compression of blocks with small numbers of
223 * properties (the norm) and to allow quickly checking whether a
224 * property is set in this block.
226 property_set_type mPropertiesSet
[kPropertiesSetChunkCount
];
228 * mPropertiesImportant indicates which properties are '!important'.
230 property_set_type mPropertiesImportant
[kPropertiesSetChunkCount
];
234 * Return the storage location within |this| of the value of the
235 * property (i.e., either an |nsCSSValue*|, |nsCSSRect*|, or
236 * |nsCSSValueList**| (etc.).
238 void* PropertyAt(nsCSSProperty aProperty
) {
239 const PropertyOffsetInfo
& offsets
=
240 nsCSSExpandedDataBlock::kOffsetTable
[aProperty
];
241 return reinterpret_cast<void*>(reinterpret_cast<char*>(this) +
242 offsets
.block_offset
);
246 * Return the storage location within |aRuleData| of the value of
247 * the property (i.e., either an |nsCSSValue*|, |nsCSSRect*|, or
248 * |nsCSSValueList**| (etc.).
250 static void* RuleDataPropertyAt(nsRuleData
*aRuleData
,
251 nsCSSProperty aProperty
) {
252 const PropertyOffsetInfo
& offsets
=
253 nsCSSExpandedDataBlock::kOffsetTable
[aProperty
];
254 NS_ASSERTION(offsets
.ruledata_struct_offset
!= size_t(-1),
255 "property should not use CSS_PROP_BACKENDONLY");
256 char* cssstruct
= *reinterpret_cast<char**>
257 (reinterpret_cast<char*>(aRuleData
) +
258 offsets
.ruledata_struct_offset
);
259 return reinterpret_cast<void*>
260 (cssstruct
+ offsets
.ruledata_member_offset
);
263 void AssertInSetRange(nsCSSProperty aProperty
) {
264 NS_ASSERTION(0 <= aProperty
&&
265 aProperty
< eCSSProperty_COUNT_no_shorthands
,
269 void SetPropertyBit(nsCSSProperty aProperty
) {
270 AssertInSetRange(aProperty
);
271 mPropertiesSet
[aProperty
/ kPropertiesSetChunkSize
] |=
272 property_set_type(1 << (aProperty
% kPropertiesSetChunkSize
));
275 void ClearPropertyBit(nsCSSProperty aProperty
) {
276 AssertInSetRange(aProperty
);
277 mPropertiesSet
[aProperty
/ kPropertiesSetChunkSize
] &=
278 ~property_set_type(1 << (aProperty
% kPropertiesSetChunkSize
));
281 PRBool
HasPropertyBit(nsCSSProperty aProperty
) {
282 AssertInSetRange(aProperty
);
283 return (mPropertiesSet
[aProperty
/ kPropertiesSetChunkSize
] &
284 (1 << (aProperty
% kPropertiesSetChunkSize
))) != 0;
287 void SetImportantBit(nsCSSProperty aProperty
) {
288 AssertInSetRange(aProperty
);
289 mPropertiesImportant
[aProperty
/ kPropertiesSetChunkSize
] |=
290 property_set_type(1 << (aProperty
% kPropertiesSetChunkSize
));
293 void ClearImportantBit(nsCSSProperty aProperty
) {
294 AssertInSetRange(aProperty
);
295 mPropertiesImportant
[aProperty
/ kPropertiesSetChunkSize
] &=
296 ~property_set_type(1 << (aProperty
% kPropertiesSetChunkSize
));
299 PRBool
HasImportantBit(nsCSSProperty aProperty
) {
300 AssertInSetRange(aProperty
);
301 return (mPropertiesImportant
[aProperty
/ kPropertiesSetChunkSize
] &
302 (1 << (aProperty
% kPropertiesSetChunkSize
))) != 0;
306 memset(mPropertiesSet
, 0, sizeof(mPropertiesSet
));
307 memset(mPropertiesImportant
, 0, sizeof(mPropertiesImportant
));
311 #endif /* !defined(nsCSSDataBlock_h__) */