Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / layout / style / Declaration.h
blob8dcdf46ad04aaebbb9edb0f7d0ca94f9520da85b
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 * representation of a declaration block (or style attribute) in a CSS
8 * stylesheet
9 */
11 #ifndef mozilla_css_Declaration_h
12 #define mozilla_css_Declaration_h
14 // This header is in EXPORTS because it's used in several places in content/,
15 // but it's not really a public interface.
16 #ifndef MOZILLA_INTERNAL_API
17 #error "This file should only be included within libxul"
18 #endif
20 #include "mozilla/Attributes.h"
21 #include "mozilla/MemoryReporting.h"
22 #include "CSSVariableDeclarations.h"
23 #include "nsCSSDataBlock.h"
24 #include "nsCSSProperty.h"
25 #include "nsCSSProps.h"
26 #include "nsStringFwd.h"
27 #include "nsTArray.h"
28 #include <stdio.h>
30 namespace mozilla {
31 namespace css {
33 // Declaration objects have unusual lifetime rules. Every declaration
34 // begins life in an invalid state which ends when InitializeEmpty or
35 // CompressFrom is called upon it. After that, it can be attached to
36 // exactly one style rule, and will be destroyed when that style rule
37 // is destroyed. A declaration becomes immutable when its style rule's
38 // |RuleMatched| method is called; after that, it must be copied before
39 // it can be modified, which is taken care of by |EnsureMutable|.
41 class Declaration {
42 public:
43 /**
44 * Construct an |Declaration| that is in an invalid state (null
45 * |mData|) and cannot be used until its |CompressFrom| method or
46 * |InitializeEmpty| method is called.
48 Declaration();
50 Declaration(const Declaration& aCopy);
52 ~Declaration();
54 /**
55 * |ValueAppended| must be called to maintain this declaration's
56 * |mOrder| whenever a property is parsed into an expanded data block
57 * for this declaration. aProperty must not be a shorthand.
59 void ValueAppended(nsCSSProperty aProperty);
61 void RemoveProperty(nsCSSProperty aProperty);
63 bool HasProperty(nsCSSProperty aProperty) const;
65 void GetValue(nsCSSProperty aProperty, nsAString& aValue) const;
66 void GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const;
68 bool HasImportantData() const {
69 return mImportantData || mImportantVariables;
71 bool GetValueIsImportant(nsCSSProperty aProperty) const;
72 bool GetValueIsImportant(const nsAString& aProperty) const;
74 /**
75 * Adds a custom property declaration to this object.
77 * @param aName The variable name (i.e., without the "--" prefix).
78 * @param aType The type of value the variable has.
79 * @param aValue The value of the variable, if aType is
80 * CSSVariableDeclarations::eTokenStream.
81 * @param aIsImportant Whether the declaration is !important.
82 * @param aOverrideImportant When aIsImportant is false, whether an
83 * existing !important declaration will be overridden.
85 void AddVariableDeclaration(const nsAString& aName,
86 CSSVariableDeclarations::Type aType,
87 const nsString& aValue,
88 bool aIsImportant,
89 bool aOverrideImportant);
91 /**
92 * Removes a custom property declaration from this object.
94 * @param aName The variable name (i.e., without the "--" prefix).
96 void RemoveVariableDeclaration(const nsAString& aName);
98 /**
99 * Returns whether a custom property declaration for a variable with
100 * a given name exists on this object.
102 * @param aName The variable name (i.e., without the "--" prefix).
104 bool HasVariableDeclaration(const nsAString& aName) const;
107 * Gets the string value for a custom property declaration of a variable
108 * with a given name.
110 * @param aName The variable name (i.e., without the "--" prefix).
111 * @param aValue Out parameter into which the variable's value will be
112 * stored. If the value is 'initial' or 'inherit', that exact string
113 * will be stored in aValue.
115 void GetVariableDeclaration(const nsAString& aName, nsAString& aValue) const;
118 * Returns whether the custom property declaration for a variable with
119 * the given name was !important.
121 bool GetVariableValueIsImportant(const nsAString& aName) const;
123 uint32_t Count() const {
124 return mOrder.Length();
127 // Returns whether we actually had a property at aIndex
128 bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const;
130 void ToString(nsAString& aString) const;
132 nsCSSCompressedDataBlock* GetNormalBlock() const { return mData; }
133 nsCSSCompressedDataBlock* GetImportantBlock() const { return mImportantData; }
136 * Initialize this declaration as holding no data. Cannot fail.
138 void InitializeEmpty();
141 * Transfer all of the state from |aExpandedData| into this declaration.
142 * After calling, |aExpandedData| should be in its initial state.
143 * Callers must make sure mOrder is updated as necessary.
145 void CompressFrom(nsCSSExpandedDataBlock *aExpandedData) {
146 NS_ABORT_IF_FALSE(!mData, "oops");
147 NS_ABORT_IF_FALSE(!mImportantData, "oops");
148 aExpandedData->Compress(getter_Transfers(mData),
149 getter_Transfers(mImportantData),
150 mOrder);
151 aExpandedData->AssertInitialState();
155 * Transfer all of the state from this declaration into
156 * |aExpandedData| and put this declaration temporarily into an
157 * invalid state (ended by |CompressFrom| or |InitializeEmpty|) that
158 * should last only during parsing. During this time only
159 * |ValueAppended| should be called.
161 void ExpandTo(nsCSSExpandedDataBlock *aExpandedData) {
162 AssertMutable();
163 aExpandedData->AssertInitialState();
165 NS_ABORT_IF_FALSE(mData, "oops");
166 aExpandedData->Expand(mData.forget(), mImportantData.forget());
170 * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
171 * rule using this declaration for storage.
173 void MapNormalRuleInfoInto(nsRuleData *aRuleData) const {
174 NS_ABORT_IF_FALSE(mData, "called while expanded");
175 mData->MapRuleInfoInto(aRuleData);
176 if (mVariables) {
177 mVariables->MapRuleInfoInto(aRuleData);
180 void MapImportantRuleInfoInto(nsRuleData *aRuleData) const {
181 NS_ABORT_IF_FALSE(mData, "called while expanded");
182 NS_ABORT_IF_FALSE(mImportantData || mImportantVariables,
183 "must have important data or variables");
184 if (mImportantData) {
185 mImportantData->MapRuleInfoInto(aRuleData);
187 if (mImportantVariables) {
188 mImportantVariables->MapRuleInfoInto(aRuleData);
193 * Attempt to replace the value for |aProperty| stored in this
194 * declaration with the matching value from |aFromBlock|.
195 * This method may only be called on a mutable declaration.
196 * It will fail (returning false) if |aProperty| is shorthand,
197 * is not already in this declaration, or does not have the indicated
198 * importance level. If it returns true, it erases the value in
199 * |aFromBlock|. |aChanged| is set to true if the declaration
200 * changed as a result of the call, and to false otherwise.
202 bool TryReplaceValue(nsCSSProperty aProperty, bool aIsImportant,
203 nsCSSExpandedDataBlock& aFromBlock,
204 bool* aChanged)
206 AssertMutable();
207 NS_ABORT_IF_FALSE(mData, "called while expanded");
209 if (nsCSSProps::IsShorthand(aProperty)) {
210 *aChanged = false;
211 return false;
213 nsCSSCompressedDataBlock *block = aIsImportant ? mImportantData : mData;
214 // mImportantData might be null
215 if (!block) {
216 *aChanged = false;
217 return false;
220 #ifdef DEBUG
222 nsCSSCompressedDataBlock *other = aIsImportant ? mData : mImportantData;
223 NS_ABORT_IF_FALSE(!other || !other->ValueFor(aProperty) ||
224 !block->ValueFor(aProperty),
225 "Property both important and not?");
227 #endif
228 return block->TryReplaceValue(aProperty, aFromBlock, aChanged);
231 bool HasNonImportantValueFor(nsCSSProperty aProperty) const {
232 NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty), "must be longhand");
233 return !!mData->ValueFor(aProperty);
237 * Return whether |this| may be modified.
239 bool IsMutable() const {
240 return !mImmutable;
244 * Copy |this|, if necessary to ensure that it can be modified.
246 Declaration* EnsureMutable();
249 * Crash if |this| cannot be modified.
251 void AssertMutable() const {
252 NS_ABORT_IF_FALSE(IsMutable(), "someone forgot to call EnsureMutable");
256 * Mark this declaration as unmodifiable. It's 'const' so it can
257 * be called from ToString.
259 void SetImmutable() const { mImmutable = true; }
262 * Clear the data, in preparation for its replacement with entirely
263 * new data by a call to |CompressFrom|.
265 void ClearData() {
266 AssertMutable();
267 mData = nullptr;
268 mImportantData = nullptr;
269 mVariables = nullptr;
270 mImportantVariables = nullptr;
271 mOrder.Clear();
272 mVariableOrder.Clear();
275 #ifdef DEBUG
276 void List(FILE* out = stdout, int32_t aIndent = 0) const;
277 #endif
279 private:
280 Declaration& operator=(const Declaration& aCopy) = delete;
281 bool operator==(const Declaration& aCopy) const = delete;
283 void GetValue(nsCSSProperty aProperty, nsAString& aValue,
284 nsCSSValue::Serialization aValueSerialization) const;
286 static void AppendImportanceToString(bool aIsImportant, nsAString& aString);
287 // return whether there was a value in |aValue| (i.e., it had a non-null unit)
288 bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const;
289 bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult,
290 nsCSSValue::Serialization aValueSerialization) const;
291 // Helper for ToString with strange semantics regarding aValue.
292 void AppendPropertyAndValueToString(nsCSSProperty aProperty,
293 nsAutoString& aValue,
294 nsAString& aResult) const;
295 // helper for ToString that serializes a custom property declaration for
296 // a variable with the specified name
297 void AppendVariableAndValueToString(const nsAString& aName,
298 nsAString& aResult) const;
300 public:
302 * Returns the property at the given index in the ordered list of
303 * declarations. For custom properties, eCSSPropertyExtra_variable
304 * is returned.
306 nsCSSProperty GetPropertyAt(uint32_t aIndex) const {
307 uint32_t value = mOrder[aIndex];
308 if (value >= eCSSProperty_COUNT) {
309 return eCSSPropertyExtra_variable;
311 return nsCSSProperty(value);
315 * Gets the name of the custom property at the given index in the ordered
316 * list of declarations.
318 void GetCustomPropertyNameAt(uint32_t aIndex, nsAString& aResult) const {
319 MOZ_ASSERT(mOrder[aIndex] >= eCSSProperty_COUNT);
320 uint32_t variableIndex = mOrder[aIndex] - eCSSProperty_COUNT;
321 aResult.Truncate();
322 aResult.AppendLiteral("--");
323 aResult.Append(mVariableOrder[variableIndex]);
326 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
328 private:
329 // The order of properties in this declaration. Longhand properties are
330 // represented by their nsCSSProperty value, and each custom property (--*)
331 // is represented by a value that begins at eCSSProperty_COUNT.
333 // Subtracting eCSSProperty_COUNT from those values that represent custom
334 // properties results in an index into mVariableOrder, which identifies the
335 // specific variable the custom property declaration is for.
336 nsAutoTArray<uint32_t, 8> mOrder;
338 // variable names of custom properties found in mOrder
339 nsTArray<nsString> mVariableOrder;
341 // never null, except while expanded, or before the first call to
342 // InitializeEmpty or CompressFrom.
343 nsAutoPtr<nsCSSCompressedDataBlock> mData;
345 // may be null
346 nsAutoPtr<nsCSSCompressedDataBlock> mImportantData;
348 // may be null
349 nsAutoPtr<CSSVariableDeclarations> mVariables;
351 // may be null
352 nsAutoPtr<CSSVariableDeclarations> mImportantVariables;
354 // set by style rules when |RuleMatched| is called;
355 // also by ToString (hence the 'mutable').
356 mutable bool mImmutable;
359 } // namespace css
360 } // namespace mozilla
362 #endif /* mozilla_css_Declaration_h */