/src/mozilla-central/layout/style/nsCSSProps.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* |
8 | | * methods for dealing with CSS properties and tables of the keyword |
9 | | * values they accept |
10 | | */ |
11 | | |
12 | | #ifndef nsCSSProps_h___ |
13 | | #define nsCSSProps_h___ |
14 | | |
15 | | #include <limits> |
16 | | #include <type_traits> |
17 | | #include "nsString.h" |
18 | | #include "nsCSSPropertyID.h" |
19 | | #include "nsStyleStructFwd.h" |
20 | | #include "nsCSSKeywords.h" |
21 | | #include "mozilla/CSSEnabledState.h" |
22 | | #include "mozilla/CSSPropFlags.h" |
23 | | #include "mozilla/UseCounter.h" |
24 | | #include "mozilla/EnumTypeTraits.h" |
25 | | #include "mozilla/Preferences.h" |
26 | | #include "nsXULAppAPI.h" |
27 | | |
28 | | // Length of the "--" prefix on custom names (such as custom property names, |
29 | | // and, in the future, custom media query names). |
30 | 0 | #define CSS_CUSTOM_NAME_PREFIX_LENGTH 2 |
31 | | |
32 | | namespace mozilla { |
33 | | class ComputedStyle; |
34 | | } |
35 | | |
36 | | extern "C" { |
37 | | nsCSSPropertyID Servo_ResolveLogicalProperty(nsCSSPropertyID, |
38 | | const mozilla::ComputedStyle*); |
39 | | nsCSSPropertyID Servo_Property_LookupEnabledForAllContent(const nsACString*); |
40 | | const uint8_t* Servo_Property_GetName(nsCSSPropertyID, uint32_t* aLength); |
41 | | } |
42 | | |
43 | | struct nsCSSKTableEntry |
44 | | { |
45 | | // nsCSSKTableEntry objects can be initialized either with an int16_t value |
46 | | // or a value of an enumeration type that can fit within an int16_t. |
47 | | |
48 | | constexpr nsCSSKTableEntry(nsCSSKeyword aKeyword, int16_t aValue) |
49 | | : mKeyword(aKeyword) |
50 | | , mValue(aValue) |
51 | 0 | { |
52 | 0 | } |
53 | | |
54 | | template<typename T, |
55 | | typename = typename std::enable_if<std::is_enum<T>::value>::type> |
56 | | constexpr nsCSSKTableEntry(nsCSSKeyword aKeyword, T aValue) |
57 | | : mKeyword(aKeyword) |
58 | | , mValue(static_cast<int16_t>(aValue)) |
59 | | { |
60 | | static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value, |
61 | | "aValue must be an enum that fits within mValue"); |
62 | | } |
63 | | |
64 | | bool IsSentinel() const |
65 | 0 | { |
66 | 0 | return mKeyword == eCSSKeyword_UNKNOWN && mValue == -1; |
67 | 0 | } |
68 | | |
69 | | nsCSSKeyword mKeyword; |
70 | | int16_t mValue; |
71 | | }; |
72 | | |
73 | | class nsCSSProps { |
74 | | public: |
75 | | typedef mozilla::CSSEnabledState EnabledState; |
76 | | typedef mozilla::CSSPropFlags Flags; |
77 | | typedef nsCSSKTableEntry KTableEntry; |
78 | | |
79 | | static void AddRefTable(void); |
80 | | static void ReleaseTable(void); |
81 | | |
82 | | // Looks up the property with name aProperty and returns its corresponding |
83 | | // nsCSSPropertyID value. If aProperty is the name of a custom property, |
84 | | // then eCSSPropertyExtra_variable will be returned. |
85 | | // |
86 | | // This only returns properties enabled for all content, and resolves aliases |
87 | | // to return the aliased property. |
88 | | static nsCSSPropertyID LookupProperty(const nsACString& aProperty) |
89 | 0 | { |
90 | 0 | return Servo_Property_LookupEnabledForAllContent(&aProperty); |
91 | 0 | } |
92 | | |
93 | | static nsCSSPropertyID LookupProperty(const nsAString& aProperty) |
94 | 0 | { |
95 | 0 | NS_ConvertUTF16toUTF8 utf8(aProperty); |
96 | 0 | return LookupProperty(utf8); |
97 | 0 | } |
98 | | |
99 | | // As above, but looked up using a property's IDL name. |
100 | | // eCSSPropertyExtra_variable won't be returned from these methods. |
101 | | static nsCSSPropertyID LookupPropertyByIDLName( |
102 | | const nsAString& aPropertyIDLName, |
103 | | EnabledState aEnabled); |
104 | | static nsCSSPropertyID LookupPropertyByIDLName( |
105 | | const nsACString& aPropertyIDLName, |
106 | | EnabledState aEnabled); |
107 | | |
108 | | // Returns whether aProperty is a custom property name, i.e. begins with |
109 | | // "--". This assumes that the CSS Variables pref has been enabled. |
110 | | static bool IsCustomPropertyName(const nsAString& aProperty); |
111 | | |
112 | | static bool IsShorthand(nsCSSPropertyID aProperty) |
113 | 0 | { |
114 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, |
115 | 0 | "out of range"); |
116 | 0 | return (aProperty >= eCSSProperty_COUNT_no_shorthands); |
117 | 0 | } |
118 | | |
119 | | // Same but for @font-face descriptors |
120 | | static nsCSSFontDesc LookupFontDesc(const nsAString& aProperty); |
121 | | |
122 | | // Given a property enum, get the string value |
123 | | // |
124 | | // This string is static. |
125 | | static const nsDependentCSubstring GetStringValue(nsCSSPropertyID aProperty) |
126 | 0 | { |
127 | 0 | uint32_t len; |
128 | 0 | const uint8_t* chars = Servo_Property_GetName(aProperty, &len); |
129 | 0 | return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len); |
130 | 0 | } |
131 | | |
132 | | static const nsCString& GetStringValue(nsCSSFontDesc aFontDesc); |
133 | | static const nsCString& GetStringValue(nsCSSCounterDesc aCounterDesc); |
134 | | |
135 | | // Returns the index of |aKeyword| in |aTable|, if it exists there; |
136 | | // otherwise, returns -1. |
137 | | // NOTE: Generally, clients should call FindKeyword() instead of this method. |
138 | | static int32_t FindIndexOfKeyword(nsCSSKeyword aKeyword, |
139 | | const KTableEntry aTable[]); |
140 | | |
141 | | // Find |aKeyword| in |aTable|, if found set |aValue| to its corresponding value. |
142 | | // If not found, return false and do not set |aValue|. |
143 | | static bool FindKeyword(nsCSSKeyword aKeyword, const KTableEntry aTable[], |
144 | | int32_t& aValue); |
145 | | // Return the first keyword in |aTable| that has the corresponding value |aValue|. |
146 | | // Return |eCSSKeyword_UNKNOWN| if not found. |
147 | | static nsCSSKeyword ValueToKeywordEnum(int32_t aValue, |
148 | | const KTableEntry aTable[]); |
149 | | template<typename T, |
150 | | typename = typename std::enable_if<std::is_enum<T>::value>::type> |
151 | | static nsCSSKeyword ValueToKeywordEnum(T aValue, |
152 | | const KTableEntry aTable[]) |
153 | 0 | { |
154 | 0 | static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value, |
155 | 0 | "aValue must be an enum that fits within KTableEntry::mValue"); |
156 | 0 | return ValueToKeywordEnum(static_cast<int16_t>(aValue), aTable); |
157 | 0 | } Unexecuted instantiation: nsCSSKeyword nsCSSProps::ValueToKeywordEnum<mozilla::StyleImageLayerRepeat, void>(mozilla::StyleImageLayerRepeat, nsCSSKTableEntry const*) Unexecuted instantiation: nsCSSKeyword nsCSSProps::ValueToKeywordEnum<mozilla::StyleOverscrollBehavior, void>(mozilla::StyleOverscrollBehavior, nsCSSKTableEntry const*) Unexecuted instantiation: nsCSSKeyword nsCSSProps::ValueToKeywordEnum<mozilla::StyleBorderImageRepeat, void>(mozilla::StyleBorderImageRepeat, nsCSSKTableEntry const*) Unexecuted instantiation: nsCSSKeyword nsCSSProps::ValueToKeywordEnum<mozilla::StyleDisplay, void>(mozilla::StyleDisplay, nsCSSKTableEntry const*) |
158 | | // Ditto but as a string, return "" when not found. |
159 | | static const nsCString& ValueToKeyword(int32_t aValue, |
160 | | const KTableEntry aTable[]); |
161 | | template<typename T, |
162 | | typename = typename std::enable_if<std::is_enum<T>::value>::type> |
163 | | static const nsCString& ValueToKeyword(T aValue, const KTableEntry aTable[]) |
164 | 0 | { |
165 | 0 | static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value, |
166 | 0 | "aValue must be an enum that fits within KTableEntry::mValue"); |
167 | 0 | return ValueToKeyword(static_cast<int16_t>(aValue), aTable); |
168 | 0 | } |
169 | | |
170 | | private: |
171 | | static const Flags kFlagsTable[eCSSProperty_COUNT]; |
172 | | |
173 | | public: |
174 | | static bool PropHasFlags(nsCSSPropertyID aProperty, Flags aFlags) |
175 | 0 | { |
176 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, |
177 | 0 | "out of range"); |
178 | 0 | return (nsCSSProps::kFlagsTable[aProperty] & aFlags) == aFlags; |
179 | 0 | } |
180 | | |
181 | | static nsCSSPropertyID Physicalize(nsCSSPropertyID aProperty, |
182 | | const mozilla::ComputedStyle& aStyle) |
183 | 0 | { |
184 | 0 | if (PropHasFlags(aProperty, Flags::IsLogical)) { |
185 | 0 | return Servo_ResolveLogicalProperty(aProperty, &aStyle); |
186 | 0 | } |
187 | 0 | return aProperty; |
188 | 0 | } |
189 | | |
190 | | private: |
191 | | // A table for shorthand properties. The appropriate index is the |
192 | | // property ID minus eCSSProperty_COUNT_no_shorthands. |
193 | | static const nsCSSPropertyID* const |
194 | | kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands]; |
195 | | |
196 | | public: |
197 | | static const nsCSSPropertyID* SubpropertyEntryFor(nsCSSPropertyID aProperty) |
198 | 0 | { |
199 | 0 | MOZ_ASSERT(eCSSProperty_COUNT_no_shorthands <= aProperty && |
200 | 0 | aProperty < eCSSProperty_COUNT, |
201 | 0 | "out of range"); |
202 | 0 | return nsCSSProps::kSubpropertyTable[aProperty - |
203 | 0 | eCSSProperty_COUNT_no_shorthands]; |
204 | 0 | } |
205 | | |
206 | | private: |
207 | | static bool gPropertyEnabled[eCSSProperty_COUNT_with_aliases]; |
208 | | |
209 | | private: |
210 | | // Defined in the generated nsCSSPropsGenerated.inc. |
211 | | static const char* const kIDLNameTable[eCSSProperty_COUNT]; |
212 | | |
213 | | public: |
214 | | /** |
215 | | * Returns the IDL name of the specified property, which must be a |
216 | | * longhand, logical or shorthand property. The IDL name is the property |
217 | | * name with any hyphen-lowercase character pairs replaced by an |
218 | | * uppercase character: |
219 | | * https://drafts.csswg.org/cssom/#css-property-to-idl-attribute |
220 | | * |
221 | | * As a special case, the string "cssFloat" is returned for the float |
222 | | * property. nullptr is returned for internal properties. |
223 | | */ |
224 | | static const char* PropertyIDLName(nsCSSPropertyID aProperty) |
225 | 0 | { |
226 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, |
227 | 0 | "out of range"); |
228 | 0 | return kIDLNameTable[aProperty]; |
229 | 0 | } |
230 | | |
231 | | private: |
232 | | static const int32_t kIDLNameSortPositionTable[eCSSProperty_COUNT]; |
233 | | |
234 | | public: |
235 | | /** |
236 | | * Returns the position of the specified property in a list of all |
237 | | * properties sorted by their IDL name. |
238 | | */ |
239 | | static int32_t PropertyIDLNameSortPosition(nsCSSPropertyID aProperty) |
240 | 0 | { |
241 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, |
242 | 0 | "out of range"); |
243 | 0 | return kIDLNameSortPositionTable[aProperty]; |
244 | 0 | } |
245 | | |
246 | 0 | static bool IsEnabled(nsCSSPropertyID aProperty) { |
247 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_with_aliases, |
248 | 0 | "out of range"); |
249 | 0 | // In the child process, assert that we're not trying to parse stylesheets |
250 | 0 | // before we've gotten all our prefs. |
251 | 0 | MOZ_ASSERT_IF(!XRE_IsParentProcess(), |
252 | 0 | mozilla::Preferences::ArePrefsInitedInContentProcess()); |
253 | 0 | return gPropertyEnabled[aProperty]; |
254 | 0 | } |
255 | | |
256 | | // A table for the use counter associated with each CSS property. If a |
257 | | // property does not have a use counter defined in UseCounters.conf, then |
258 | | // its associated entry is |eUseCounter_UNKNOWN|. |
259 | | static const mozilla::UseCounter gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands]; |
260 | | |
261 | | public: |
262 | | |
263 | 0 | static mozilla::UseCounter UseCounterFor(nsCSSPropertyID aProperty) { |
264 | 0 | MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands, |
265 | 0 | "out of range"); |
266 | 0 | return gPropertyUseCounter[aProperty]; |
267 | 0 | } |
268 | | |
269 | | static bool IsEnabled(nsCSSPropertyID aProperty, EnabledState aEnabled) |
270 | 0 | { |
271 | 0 | if (IsEnabled(aProperty)) { |
272 | 0 | return true; |
273 | 0 | } |
274 | 0 | if (aEnabled == EnabledState::eIgnoreEnabledState) { |
275 | 0 | return true; |
276 | 0 | } |
277 | 0 | if ((aEnabled & EnabledState::eInUASheets) && |
278 | 0 | PropHasFlags(aProperty, Flags::EnabledInUASheets)) |
279 | 0 | { |
280 | 0 | return true; |
281 | 0 | } |
282 | 0 | if ((aEnabled & EnabledState::eInChrome) && |
283 | 0 | PropHasFlags(aProperty, Flags::EnabledInChrome)) |
284 | 0 | { |
285 | 0 | return true; |
286 | 0 | } |
287 | 0 | return false; |
288 | 0 | } |
289 | | |
290 | | public: |
291 | | struct PropertyPref |
292 | | { |
293 | | nsCSSPropertyID mPropID; |
294 | | const char* mPref; |
295 | | }; |
296 | | static const PropertyPref kPropertyPrefTable[]; |
297 | | |
298 | | // Storing the enabledstate_ value in an nsCSSPropertyID variable is a small hack |
299 | | // to avoid needing a separate variable declaration for its real type |
300 | | // (CSSEnabledState), which would then require using a block and |
301 | | // therefore a pair of macros by consumers for the start and end of the loop. |
302 | | #define CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(it_, prop_, enabledstate_) \ |
303 | 0 | for (const nsCSSPropertyID *it_ = nsCSSProps::SubpropertyEntryFor(prop_), \ |
304 | 0 | es_ = (nsCSSPropertyID)((enabledstate_) | \ |
305 | 0 | CSSEnabledState(0)); \ |
306 | 0 | *it_ != eCSSProperty_UNKNOWN; ++it_) \ |
307 | 0 | if (nsCSSProps::IsEnabled(*it_, (mozilla::CSSEnabledState) es_)) |
308 | | |
309 | | // Keyword/Enum value tables |
310 | | static const KTableEntry kTransformStyleKTable[]; |
311 | | static const KTableEntry kImageLayerRepeatKTable[]; |
312 | | // Not const because we modify its entries when the pref |
313 | | // "layout.css.background-clip.text" changes: |
314 | | static const KTableEntry kBorderImageRepeatKTable[]; |
315 | | static const KTableEntry kBorderStyleKTable[]; |
316 | | static const KTableEntry kShapeRadiusKTable[]; |
317 | | static const KTableEntry kFilterFunctionKTable[]; |
318 | | static const KTableEntry kBoxShadowTypeKTable[]; |
319 | | static const KTableEntry kCursorKTable[]; |
320 | | // Not const because we modify its entries when various |
321 | | // "layout.css.*.enabled" prefs changes: |
322 | | static KTableEntry kDisplayKTable[]; |
323 | | // -- tables for parsing the {align,justify}-{content,items,self} properties -- |
324 | | static const KTableEntry kAlignAllKeywords[]; |
325 | | static const KTableEntry kAlignOverflowPosition[]; // <overflow-position> |
326 | | static const KTableEntry kAlignSelfPosition[]; // <self-position> |
327 | | static const KTableEntry kAlignLegacy[]; // 'legacy' |
328 | | static const KTableEntry kAlignLegacyPosition[]; // 'left/right/center' |
329 | | static const KTableEntry kAlignAutoNormalStretchBaseline[]; // 'auto/normal/stretch/baseline' |
330 | | static const KTableEntry kAlignNormalStretchBaseline[]; // 'normal/stretch/baseline' |
331 | | static const KTableEntry kAlignNormalBaseline[]; // 'normal/baseline' |
332 | | static const KTableEntry kAlignContentDistribution[]; // <content-distribution> |
333 | | static const KTableEntry kAlignContentPosition[]; // <content-position> |
334 | | // -- tables for auto-completion of the {align,justify}-{content,items,self} properties -- |
335 | | static const KTableEntry kAutoCompletionAlignJustifySelf[]; |
336 | | static const KTableEntry kAutoCompletionAlignItems[]; |
337 | | static const KTableEntry kAutoCompletionAlignJustifyContent[]; |
338 | | // ------------------------------------------------------------------ |
339 | | static const KTableEntry kFontSmoothingKTable[]; |
340 | | static const KTableEntry kGridAutoFlowKTable[]; |
341 | | static const KTableEntry kGridTrackBreadthKTable[]; |
342 | | static const KTableEntry kLineHeightKTable[]; |
343 | | static const KTableEntry kContainKTable[]; |
344 | | static const KTableEntry kOutlineStyleKTable[]; |
345 | | static const KTableEntry kOverflowKTable[]; |
346 | | static const KTableEntry kOverflowSubKTable[]; |
347 | | static const KTableEntry kOverflowClipBoxKTable[]; |
348 | | static const KTableEntry kRadialGradientSizeKTable[]; |
349 | | static const KTableEntry kOverscrollBehaviorKTable[]; |
350 | | static const KTableEntry kScrollSnapTypeKTable[]; |
351 | | // Not const because we modify its entries when the pref |
352 | | // "layout.css.text-align-unsafe-value.enabled" changes: |
353 | | static KTableEntry kTextAlignKTable[]; |
354 | | static const KTableEntry kTextDecorationLineKTable[]; |
355 | | static const KTableEntry kTextDecorationStyleKTable[]; |
356 | | static const KTableEntry kTextEmphasisStyleShapeKTable[]; |
357 | | static const KTableEntry kTextOverflowKTable[]; |
358 | | static const KTableEntry kTouchActionKTable[]; |
359 | | static const KTableEntry kTransitionTimingFunctionKTable[]; |
360 | | static const KTableEntry kVerticalAlignKTable[]; |
361 | | static const KTableEntry kWidthKTable[]; // also min-width, max-width |
362 | | static const KTableEntry kFlexBasisKTable[]; |
363 | | }; |
364 | | |
365 | | #endif /* nsCSSProps_h___ */ |