Bumping manifests a=b2g-bump
[gecko.git] / layout / style / nsCSSDataBlock.h
blobe09692d10d550e4b586d8842390356a8a2c3105c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * compact representation of the property-value pairs within a CSS
8 * declaration, and the code for expanding and compacting it
9 */
11 #ifndef nsCSSDataBlock_h__
12 #define nsCSSDataBlock_h__
14 #include "mozilla/MemoryReporting.h"
15 #include "nsCSSProps.h"
16 #include "nsCSSPropertySet.h"
17 #include "nsCSSValue.h"
18 #include "imgRequestProxy.h"
20 struct nsRuleData;
21 class nsCSSExpandedDataBlock;
23 namespace mozilla {
24 namespace css {
25 class Declaration;
29 /**
30 * An |nsCSSCompressedDataBlock| holds a usually-immutable chunk of
31 * property-value data for a CSS declaration block (which we misname a
32 * |css::Declaration|). Mutation is accomplished through
33 * |nsCSSExpandedDataBlock| or in some cases via direct slot access.
35 class nsCSSCompressedDataBlock {
36 private:
37 friend class nsCSSExpandedDataBlock;
39 // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock
40 // (in |Compress|) can create compressed data blocks.
41 explicit nsCSSCompressedDataBlock(uint32_t aNumProps)
42 : mStyleBits(0), mNumProps(aNumProps)
45 public:
46 ~nsCSSCompressedDataBlock();
48 /**
49 * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
50 * rule using this block for storage.
52 void MapRuleInfoInto(nsRuleData *aRuleData) const;
54 /**
55 * Return the location at which the *value* for the property is
56 * stored, or null if the block does not contain a value for the
57 * property.
59 * Inefficient (by design).
61 * Must not be called for shorthands.
63 const nsCSSValue* ValueFor(nsCSSProperty aProperty) const;
65 /**
66 * Attempt to replace the value for |aProperty| stored in this block
67 * with the matching value stored in |aFromBlock|.
68 * This method will fail (returning false) if |aProperty| is not
69 * already in this block. It will set |aChanged| to true if it
70 * actually made a change to the block, but regardless, if it
71 * returns true, the value in |aFromBlock| was erased.
73 bool TryReplaceValue(nsCSSProperty aProperty,
74 nsCSSExpandedDataBlock& aFromBlock,
75 bool* aChanged);
77 /**
78 * Clone this block, or return null on out-of-memory.
80 nsCSSCompressedDataBlock* Clone() const;
82 /**
83 * Create a new nsCSSCompressedDataBlock holding no declarations.
85 static nsCSSCompressedDataBlock* CreateEmptyBlock();
87 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
89 bool HasDefaultBorderImageSlice() const;
90 bool HasDefaultBorderImageWidth() const;
91 bool HasDefaultBorderImageOutset() const;
92 bool HasDefaultBorderImageRepeat() const;
94 private:
95 void* operator new(size_t aBaseSize, uint32_t aNumProps) {
96 NS_ABORT_IF_FALSE(aBaseSize == sizeof(nsCSSCompressedDataBlock),
97 "unexpected size for nsCSSCompressedDataBlock");
98 return ::operator new(aBaseSize + DataSize(aNumProps));
101 public:
102 // Ideally, |nsCSSProperty| would be |enum nsCSSProperty : int16_t|. But
103 // not all of the compilers we use are modern enough to support small
104 // enums. So we manually squeeze nsCSSProperty into 16 bits ourselves.
105 // The static assertion below ensures it fits.
106 typedef int16_t CompressedCSSProperty;
107 static const size_t MaxCompressedCSSProperty = INT16_MAX;
109 private:
110 static size_t DataSize(uint32_t aNumProps) {
111 return size_t(aNumProps) *
112 (sizeof(nsCSSValue) + sizeof(CompressedCSSProperty));
115 int32_t mStyleBits; // the structs for which we have data, according to
116 // |nsCachedStyleData::GetBitForSID|.
117 uint32_t mNumProps;
118 // nsCSSValue elements are stored after these fields, and
119 // nsCSSProperty elements are stored -- each one compressed as a
120 // CompressedCSSProperty -- after the nsCSSValue elements. Space for them
121 // is allocated in |operator new| above. The static assertions following
122 // this class make sure that the value and property elements are aligned
123 // appropriately.
125 nsCSSValue* Values() const {
126 return (nsCSSValue*)(this + 1);
129 CompressedCSSProperty* CompressedProperties() const {
130 return (CompressedCSSProperty*)(Values() + mNumProps);
133 nsCSSValue* ValueAtIndex(uint32_t i) const {
134 NS_ABORT_IF_FALSE(i < mNumProps, "value index out of range");
135 return Values() + i;
138 nsCSSProperty PropertyAtIndex(uint32_t i) const {
139 NS_ABORT_IF_FALSE(i < mNumProps, "property index out of range");
140 nsCSSProperty prop = (nsCSSProperty)CompressedProperties()[i];
141 NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(prop), "out of range");
142 return prop;
145 void CopyValueToIndex(uint32_t i, nsCSSValue* aValue) {
146 new (ValueAtIndex(i)) nsCSSValue(*aValue);
149 void RawCopyValueToIndex(uint32_t i, nsCSSValue* aValue) {
150 memcpy(ValueAtIndex(i), aValue, sizeof(nsCSSValue));
153 void SetPropertyAtIndex(uint32_t i, nsCSSProperty aProperty) {
154 NS_ABORT_IF_FALSE(i < mNumProps, "set property index out of range");
155 CompressedProperties()[i] = (CompressedCSSProperty)aProperty;
158 void SetNumPropsToZero() {
159 mNumProps = 0;
163 // Make sure the values and properties are aligned appropriately. (These
164 // assertions are stronger than necessary to keep them simple.)
165 static_assert(sizeof(nsCSSCompressedDataBlock) == 8,
166 "nsCSSCompressedDataBlock's size has changed");
167 static_assert(NS_ALIGNMENT_OF(nsCSSValue) == 4 || NS_ALIGNMENT_OF(nsCSSValue) == 8,
168 "nsCSSValue doesn't align with nsCSSCompressedDataBlock");
169 static_assert(NS_ALIGNMENT_OF(nsCSSCompressedDataBlock::CompressedCSSProperty) == 2,
170 "CompressedCSSProperty doesn't align with nsCSSValue");
172 // Make sure that sizeof(CompressedCSSProperty) is big enough.
173 static_assert(eCSSProperty_COUNT_no_shorthands <=
174 nsCSSCompressedDataBlock::MaxCompressedCSSProperty,
175 "nsCSSProperty doesn't fit in StoredSizeOfCSSProperty");
177 class nsCSSExpandedDataBlock {
178 friend class nsCSSCompressedDataBlock;
180 public:
181 nsCSSExpandedDataBlock();
182 ~nsCSSExpandedDataBlock();
184 private:
185 /* Property storage may not be accessed directly; use AddLonghandProperty
186 * and friends.
188 nsCSSValue mValues[eCSSProperty_COUNT_no_shorthands];
190 public:
192 * Transfer all of the state from a pair of compressed data blocks
193 * to this expanded block. This expanded block must be clear
194 * beforehand.
196 * This method DELETES both of the compressed data blocks it is
197 * passed. (This is necessary because ownership of sub-objects
198 * is transferred to the expanded block.)
200 void Expand(nsCSSCompressedDataBlock *aNormalBlock,
201 nsCSSCompressedDataBlock *aImportantBlock);
204 * Allocate new compressed blocks and transfer all of the state
205 * from this expanded block to the new blocks, clearing this
206 * expanded block. A normal block will always be allocated, but
207 * an important block will only be allocated if there are
208 * !important properties in the expanded block; otherwise
209 * |*aImportantBlock| will be set to null.
211 * aOrder is an array of nsCSSProperty values specifying the order
212 * to store values in the two data blocks.
214 void Compress(nsCSSCompressedDataBlock **aNormalBlock,
215 nsCSSCompressedDataBlock **aImportantBlock,
216 const nsTArray<uint32_t>& aOrder);
219 * Copy a value into this expanded block. This does NOT destroy
220 * the source value object. |aProperty| cannot be a shorthand.
222 void AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue);
225 * Clear the state of this expanded block.
227 void Clear();
230 * Clear the data for the given property (including the set and
231 * important bits). Can be used with shorthand properties.
233 void ClearProperty(nsCSSProperty aPropID);
236 * Same as ClearProperty, but faster and cannot be used with shorthands.
238 void ClearLonghandProperty(nsCSSProperty aPropID);
241 * Transfer the state for |aPropID| (which may be a shorthand)
242 * from |aFromBlock| to this block. The property being transferred
243 * is !important if |aIsImportant| is true, and should replace an
244 * existing !important property regardless of its own importance
245 * if |aOverrideImportant| is true.
247 * Returns true if something changed, false otherwise. Calls
248 * |ValueAppended| on |aDeclaration| if the property was not
249 * previously set, or in any case if |aMustCallValueAppended| is true.
251 bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
252 nsCSSProperty aPropID,
253 bool aIsImportant,
254 bool aOverrideImportant,
255 bool aMustCallValueAppended,
256 mozilla::css::Declaration* aDeclaration);
259 * Copies the values for aPropID into the specified aRuleData object.
261 * This is used for copying parsed-at-computed-value-time properties
262 * that had variable references. aPropID must be a longhand property.
264 void MapRuleInfoInto(nsCSSProperty aPropID, nsRuleData* aRuleData) const;
266 void AssertInitialState() {
267 #ifdef DEBUG
268 DoAssertInitialState();
269 #endif
272 private:
274 * Compute the number of properties that will be present in the
275 * result of |Compress|.
277 void ComputeNumProps(uint32_t* aNumPropsNormal,
278 uint32_t* aNumPropsImportant);
280 void DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant);
283 * Worker for TransferFromBlock; cannot be used with shorthands.
285 bool DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
286 nsCSSProperty aPropID,
287 bool aIsImportant,
288 bool aOverrideImportant,
289 bool aMustCallValueAppended,
290 mozilla::css::Declaration* aDeclaration);
292 #ifdef DEBUG
293 void DoAssertInitialState();
294 #endif
297 * mPropertiesSet stores a bit for every property that is present,
298 * to optimize compression of blocks with small numbers of
299 * properties (the norm) and to allow quickly checking whether a
300 * property is set in this block.
302 nsCSSPropertySet mPropertiesSet;
304 * mPropertiesImportant indicates which properties are '!important'.
306 nsCSSPropertySet mPropertiesImportant;
309 * Return the storage location within |this| of the value of the
310 * property |aProperty|.
312 nsCSSValue* PropertyAt(nsCSSProperty aProperty) {
313 NS_ABORT_IF_FALSE(0 <= aProperty &&
314 aProperty < eCSSProperty_COUNT_no_shorthands,
315 "property out of range");
316 return &mValues[aProperty];
318 const nsCSSValue* PropertyAt(nsCSSProperty aProperty) const {
319 NS_ABORT_IF_FALSE(0 <= aProperty &&
320 aProperty < eCSSProperty_COUNT_no_shorthands,
321 "property out of range");
322 return &mValues[aProperty];
325 void SetPropertyBit(nsCSSProperty aProperty) {
326 mPropertiesSet.AddProperty(aProperty);
329 void ClearPropertyBit(nsCSSProperty aProperty) {
330 mPropertiesSet.RemoveProperty(aProperty);
333 bool HasPropertyBit(nsCSSProperty aProperty) {
334 return mPropertiesSet.HasProperty(aProperty);
337 void SetImportantBit(nsCSSProperty aProperty) {
338 mPropertiesImportant.AddProperty(aProperty);
341 void ClearImportantBit(nsCSSProperty aProperty) {
342 mPropertiesImportant.RemoveProperty(aProperty);
345 bool HasImportantBit(nsCSSProperty aProperty) {
346 return mPropertiesImportant.HasProperty(aProperty);
349 void ClearSets() {
350 mPropertiesSet.Empty();
351 mPropertiesImportant.Empty();
355 #endif /* !defined(nsCSSDataBlock_h__) */