|
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/. */ |
|
5 |
|
6 /* CSS Custom Property assignments for a Declaration at a given priority */ |
|
7 |
|
8 #include "CSSVariableDeclarations.h" |
|
9 |
|
10 #include "CSSVariableResolver.h" |
|
11 #include "nsCSSScanner.h" |
|
12 #include "nsRuleData.h" |
|
13 |
|
14 // These three special string values are used to represent specified values of |
|
15 // 'initial', 'inherit' and 'unset'. (Note that none of these are valid |
|
16 // variable values.) |
|
17 #define INITIAL_VALUE "!" |
|
18 #define INHERIT_VALUE ";" |
|
19 #define UNSET_VALUE ")" |
|
20 |
|
21 namespace mozilla { |
|
22 |
|
23 CSSVariableDeclarations::CSSVariableDeclarations() |
|
24 { |
|
25 MOZ_COUNT_CTOR(CSSVariableDeclarations); |
|
26 } |
|
27 |
|
28 CSSVariableDeclarations::CSSVariableDeclarations(const CSSVariableDeclarations& aOther) |
|
29 { |
|
30 MOZ_COUNT_CTOR(CSSVariableDeclarations); |
|
31 CopyVariablesFrom(aOther); |
|
32 } |
|
33 |
|
34 #ifdef DEBUG |
|
35 CSSVariableDeclarations::~CSSVariableDeclarations() |
|
36 { |
|
37 MOZ_COUNT_DTOR(CSSVariableDeclarations); |
|
38 } |
|
39 #endif |
|
40 |
|
41 CSSVariableDeclarations& |
|
42 CSSVariableDeclarations::operator=(const CSSVariableDeclarations& aOther) |
|
43 { |
|
44 if (this == &aOther) { |
|
45 return *this; |
|
46 } |
|
47 |
|
48 mVariables.Clear(); |
|
49 CopyVariablesFrom(aOther); |
|
50 return *this; |
|
51 } |
|
52 |
|
53 /* static */ PLDHashOperator |
|
54 CSSVariableDeclarations::EnumerateVariableForCopy(const nsAString& aName, |
|
55 nsString aValue, |
|
56 void* aData) |
|
57 { |
|
58 CSSVariableDeclarations* variables = static_cast<CSSVariableDeclarations*>(aData); |
|
59 variables->mVariables.Put(aName, aValue); |
|
60 return PL_DHASH_NEXT; |
|
61 } |
|
62 |
|
63 void |
|
64 CSSVariableDeclarations::CopyVariablesFrom(const CSSVariableDeclarations& aOther) |
|
65 { |
|
66 aOther.mVariables.EnumerateRead(EnumerateVariableForCopy, this); |
|
67 } |
|
68 |
|
69 bool |
|
70 CSSVariableDeclarations::Has(const nsAString& aName) const |
|
71 { |
|
72 nsString value; |
|
73 return mVariables.Get(aName, &value); |
|
74 } |
|
75 |
|
76 bool |
|
77 CSSVariableDeclarations::Get(const nsAString& aName, |
|
78 Type& aType, |
|
79 nsString& aTokenStream) const |
|
80 { |
|
81 nsString value; |
|
82 if (!mVariables.Get(aName, &value)) { |
|
83 return false; |
|
84 } |
|
85 if (value.EqualsLiteral(INITIAL_VALUE)) { |
|
86 aType = eInitial; |
|
87 aTokenStream.Truncate(); |
|
88 } else if (value.EqualsLiteral(INHERIT_VALUE)) { |
|
89 aType = eInitial; |
|
90 aTokenStream.Truncate(); |
|
91 } else if (value.EqualsLiteral(UNSET_VALUE)) { |
|
92 aType = eUnset; |
|
93 aTokenStream.Truncate(); |
|
94 } else { |
|
95 aType = eTokenStream; |
|
96 aTokenStream = value; |
|
97 } |
|
98 return true; |
|
99 } |
|
100 |
|
101 void |
|
102 CSSVariableDeclarations::PutTokenStream(const nsAString& aName, |
|
103 const nsString& aTokenStream) |
|
104 { |
|
105 MOZ_ASSERT(!aTokenStream.EqualsLiteral(INITIAL_VALUE) && |
|
106 !aTokenStream.EqualsLiteral(INHERIT_VALUE) && |
|
107 !aTokenStream.EqualsLiteral(UNSET_VALUE)); |
|
108 mVariables.Put(aName, aTokenStream); |
|
109 } |
|
110 |
|
111 void |
|
112 CSSVariableDeclarations::PutInitial(const nsAString& aName) |
|
113 { |
|
114 mVariables.Put(aName, NS_LITERAL_STRING(INITIAL_VALUE)); |
|
115 } |
|
116 |
|
117 void |
|
118 CSSVariableDeclarations::PutInherit(const nsAString& aName) |
|
119 { |
|
120 mVariables.Put(aName, NS_LITERAL_STRING(INHERIT_VALUE)); |
|
121 } |
|
122 |
|
123 void |
|
124 CSSVariableDeclarations::PutUnset(const nsAString& aName) |
|
125 { |
|
126 mVariables.Put(aName, NS_LITERAL_STRING(UNSET_VALUE)); |
|
127 } |
|
128 |
|
129 void |
|
130 CSSVariableDeclarations::Remove(const nsAString& aName) |
|
131 { |
|
132 mVariables.Remove(aName); |
|
133 } |
|
134 |
|
135 /* static */ PLDHashOperator |
|
136 CSSVariableDeclarations::EnumerateVariableForMapRuleInfoInto( |
|
137 const nsAString& aName, |
|
138 nsString aValue, |
|
139 void* aData) |
|
140 { |
|
141 nsDataHashtable<nsStringHashKey, nsString>* variables = |
|
142 static_cast<nsDataHashtable<nsStringHashKey, nsString>*>(aData); |
|
143 if (!variables->Contains(aName)) { |
|
144 variables->Put(aName, aValue); |
|
145 } |
|
146 return PL_DHASH_NEXT; |
|
147 } |
|
148 |
|
149 void |
|
150 CSSVariableDeclarations::MapRuleInfoInto(nsRuleData* aRuleData) |
|
151 { |
|
152 if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Variables))) { |
|
153 return; |
|
154 } |
|
155 |
|
156 if (!aRuleData->mVariables) { |
|
157 aRuleData->mVariables = new CSSVariableDeclarations(*this); |
|
158 } else { |
|
159 mVariables.EnumerateRead(EnumerateVariableForMapRuleInfoInto, |
|
160 aRuleData->mVariables.get()); |
|
161 } |
|
162 } |
|
163 |
|
164 /* static */ PLDHashOperator |
|
165 CSSVariableDeclarations::EnumerateVariableForAddVariablesToResolver( |
|
166 const nsAString& aName, |
|
167 nsString aValue, |
|
168 void* aData) |
|
169 { |
|
170 CSSVariableResolver* resolver = static_cast<CSSVariableResolver*>(aData); |
|
171 if (aValue.EqualsLiteral(INITIAL_VALUE)) { |
|
172 // Values of 'initial' are treated the same as an invalid value in the |
|
173 // variable resolver. |
|
174 resolver->Put(aName, EmptyString(), |
|
175 eCSSTokenSerialization_Nothing, |
|
176 eCSSTokenSerialization_Nothing, |
|
177 false); |
|
178 } else if (aValue.EqualsLiteral(INHERIT_VALUE) || |
|
179 aValue.EqualsLiteral(UNSET_VALUE)) { |
|
180 // Values of 'inherit' and 'unset' don't need any handling, since it means |
|
181 // we just need to keep whatever value is currently in the resolver. |
|
182 // Values of 'inherit' and 'unset' don't need any handling, since it means |
|
183 // we just need to keep whatever value is currently in the resolver. This |
|
184 // is because the specified variable declarations already have only the |
|
185 // winning declaration for the variable and no longer have any of the |
|
186 // others. |
|
187 } else { |
|
188 // At this point, we don't know what token types are at the start and end |
|
189 // of the specified variable value. These will be determined later during |
|
190 // the resolving process. |
|
191 resolver->Put(aName, aValue, |
|
192 eCSSTokenSerialization_Nothing, |
|
193 eCSSTokenSerialization_Nothing, |
|
194 false); |
|
195 } |
|
196 return PL_DHASH_NEXT; |
|
197 } |
|
198 |
|
199 void |
|
200 CSSVariableDeclarations::AddVariablesToResolver( |
|
201 CSSVariableResolver* aResolver) const |
|
202 { |
|
203 mVariables.EnumerateRead(EnumerateVariableForAddVariablesToResolver, |
|
204 aResolver); |
|
205 } |
|
206 |
|
207 static size_t |
|
208 SizeOfTableEntry(const nsAString& aKey, |
|
209 const nsString& aValue, |
|
210 MallocSizeOf aMallocSizeOf, |
|
211 void* aUserArg) |
|
212 { |
|
213 size_t n = 0; |
|
214 n += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); |
|
215 n += aValue.SizeOfExcludingThisIfUnshared(aMallocSizeOf); |
|
216 return n; |
|
217 } |
|
218 |
|
219 size_t |
|
220 CSSVariableDeclarations::SizeOfIncludingThis( |
|
221 mozilla::MallocSizeOf aMallocSizeOf) const |
|
222 { |
|
223 size_t n = aMallocSizeOf(this); |
|
224 n += mVariables.SizeOfExcludingThis(SizeOfTableEntry, aMallocSizeOf); |
|
225 return n; |
|
226 } |
|
227 |
|
228 } // namespace mozilla |