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 /*
7  * methods for dealing with CSS properties and tables of the keyword
8  * values they accept
9  */
10 
11 #ifndef nsCSSProps_h___
12 #define nsCSSProps_h___
13 
14 #include <limits>
15 #include <type_traits>
16 #include "nsIAtom.h"
17 #include "nsString.h"
18 #include "nsCSSPropertyID.h"
19 #include "nsStyleStructFwd.h"
20 #include "nsCSSKeywords.h"
21 #include "mozilla/CSSEnabledState.h"
22 #include "mozilla/UseCounter.h"
23 #include "mozilla/EnumTypeTraits.h"
24 
25 // Length of the "--" prefix on custom names (such as custom property names,
26 // and, in the future, custom media query names).
27 #define CSS_CUSTOM_NAME_PREFIX_LENGTH 2
28 
29 // Flags for ParseVariant method
30 #define VARIANT_KEYWORD         0x000001  // K
31 #define VARIANT_LENGTH          0x000002  // L
32 #define VARIANT_PERCENT         0x000004  // P
33 #define VARIANT_COLOR           0x000008  // C eCSSUnit_*Color, eCSSUnit_Ident (e.g.  "red")
34 #define VARIANT_URL             0x000010  // U
35 #define VARIANT_NUMBER          0x000020  // N
36 #define VARIANT_INTEGER         0x000040  // I
37 #define VARIANT_ANGLE           0x000080  // G
38 #define VARIANT_FREQUENCY       0x000100  // F
39 #define VARIANT_TIME            0x000200  // T
40 #define VARIANT_STRING          0x000400  // S
41 #define VARIANT_COUNTER         0x000800  //
42 #define VARIANT_ATTR            0x001000  //
43 #define VARIANT_IDENTIFIER      0x002000  // D
44 #define VARIANT_IDENTIFIER_NO_INHERIT 0x004000 // like above, but excluding
45 // 'inherit' and 'initial'
46 #define VARIANT_AUTO            0x010000  // A
47 #define VARIANT_INHERIT         0x020000  // H eCSSUnit_Initial, eCSSUnit_Inherit, eCSSUnit_Unset
48 #define VARIANT_NONE            0x040000  // O
49 #define VARIANT_NORMAL          0x080000  // M
50 #define VARIANT_SYSFONT         0x100000  // eCSSUnit_System_Font
51 #define VARIANT_GRADIENT        0x200000  // eCSSUnit_Gradient
52 #define VARIANT_TIMING_FUNCTION 0x400000  // cubic-bezier() and steps()
53 #define VARIANT_ALL             0x800000  //
54 #define VARIANT_IMAGE_RECT    0x01000000  // eCSSUnit_Function
55 // This is an extra bit that says that a VARIANT_ANGLE allows unitless zero:
56 #define VARIANT_ZERO_ANGLE    0x02000000  // unitless zero for angles
57 #define VARIANT_CALC          0x04000000  // eCSSUnit_Calc
58 #define VARIANT_ELEMENT       0x08000000  // eCSSUnit_Element
59 #define VARIANT_NONNEGATIVE_DIMENSION 0x10000000 // Only lengths greater than or equal to 0.0
60 // Keyword used iff gfx.font_rendering.opentype_svg.enabled is true:
61 #define VARIANT_OPENTYPE_SVG_KEYWORD 0x20000000
62 #define VARIANT_ABSOLUTE_DIMENSION 0x40000000 // B Only lengths with absolute length unit
63 
64 // Variants that can consume more than one token
65 #define VARIANT_MULTIPLE_TOKENS \
66   (VARIANT_COLOR |            /* rgb(...), hsl(...), etc. */                  \
67    VARIANT_COUNTER |          /* counter(...), counters(...) */               \
68    VARIANT_ATTR |             /* attr(...) */                                 \
69    VARIANT_GRADIENT |         /* linear-gradient(...), etc. */                \
70    VARIANT_TIMING_FUNCTION |  /* cubic-bezier(...), steps(...) */             \
71    VARIANT_IMAGE_RECT |       /* -moz-image-rect(...) */                      \
72    VARIANT_CALC |             /* calc(...) */                                 \
73    VARIANT_ELEMENT)           /* -moz-element(...) */
74 
75 // Common combinations of variants
76 #define VARIANT_AL   (VARIANT_AUTO | VARIANT_LENGTH)
77 #define VARIANT_LP   (VARIANT_LENGTH | VARIANT_PERCENT)
78 #define VARIANT_LN   (VARIANT_LENGTH | VARIANT_NUMBER)
79 #define VARIANT_AH   (VARIANT_AUTO | VARIANT_INHERIT)
80 #define VARIANT_AHLP (VARIANT_AH | VARIANT_LP)
81 #define VARIANT_AHI  (VARIANT_AH | VARIANT_INTEGER)
82 #define VARIANT_AHK  (VARIANT_AH | VARIANT_KEYWORD)
83 #define VARIANT_AHKLP (VARIANT_AHLP | VARIANT_KEYWORD)
84 #define VARIANT_AHL  (VARIANT_AH | VARIANT_LENGTH)
85 #define VARIANT_AHKL (VARIANT_AHK | VARIANT_LENGTH)
86 #define VARIANT_HK   (VARIANT_INHERIT | VARIANT_KEYWORD)
87 #define VARIANT_HKF  (VARIANT_HK | VARIANT_FREQUENCY)
88 #define VARIANT_HKI  (VARIANT_HK | VARIANT_INTEGER)
89 #define VARIANT_HKL  (VARIANT_HK | VARIANT_LENGTH)
90 #define VARIANT_HKLP (VARIANT_HK | VARIANT_LP)
91 #define VARIANT_HKLPO (VARIANT_HKLP | VARIANT_NONE)
92 #define VARIANT_HL   (VARIANT_INHERIT | VARIANT_LENGTH)
93 #define VARIANT_HI   (VARIANT_INHERIT | VARIANT_INTEGER)
94 #define VARIANT_HLP  (VARIANT_HL | VARIANT_PERCENT)
95 #define VARIANT_HLPN (VARIANT_HLP | VARIANT_NUMBER)
96 #define VARIANT_HLPO (VARIANT_HLP | VARIANT_NONE)
97 #define VARIANT_HTP  (VARIANT_INHERIT | VARIANT_TIME | VARIANT_PERCENT)
98 #define VARIANT_HMK  (VARIANT_HK | VARIANT_NORMAL)
99 #define VARIANT_HC   (VARIANT_INHERIT | VARIANT_COLOR)
100 #define VARIANT_HCK  (VARIANT_HK | VARIANT_COLOR)
101 #define VARIANT_HUK  (VARIANT_HK | VARIANT_URL)
102 #define VARIANT_HUO  (VARIANT_INHERIT | VARIANT_URL | VARIANT_NONE)
103 #define VARIANT_AHUO (VARIANT_AUTO | VARIANT_HUO)
104 #define VARIANT_HPN  (VARIANT_INHERIT | VARIANT_PERCENT | VARIANT_NUMBER)
105 #define VARIANT_PN   (VARIANT_PERCENT | VARIANT_NUMBER)
106 #define VARIANT_ALPN (VARIANT_AL | VARIANT_PN)
107 #define VARIANT_HN   (VARIANT_INHERIT | VARIANT_NUMBER)
108 #define VARIANT_HON  (VARIANT_HN | VARIANT_NONE)
109 #define VARIANT_HOS  (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING)
110 #define VARIANT_LPN  (VARIANT_LP | VARIANT_NUMBER)
111 #define VARIANT_UK   (VARIANT_URL | VARIANT_KEYWORD)
112 #define VARIANT_UO   (VARIANT_URL | VARIANT_NONE)
113 #define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE)
114 #define VARIANT_LB   (VARIANT_LENGTH | VARIANT_ABSOLUTE_DIMENSION)
115 #define VARIANT_LBCALC (VARIANT_LB | VARIANT_CALC)
116 #define VARIANT_LCALC  (VARIANT_LENGTH | VARIANT_CALC)
117 #define VARIANT_LPCALC (VARIANT_LCALC | VARIANT_PERCENT)
118 #define VARIANT_LNCALC (VARIANT_LCALC | VARIANT_NUMBER)
119 #define VARIANT_LPNCALC (VARIANT_LNCALC | VARIANT_PERCENT)
120 #define VARIANT_IMAGE   (VARIANT_URL | VARIANT_NONE | VARIANT_GRADIENT | \
121                         VARIANT_IMAGE_RECT | VARIANT_ELEMENT)
122 
123 // Flags for the kFlagsTable bitfield (flags_ in nsCSSPropList.h)
124 
125 // This property is a logical property (such as padding-inline-start).
126 #define CSS_PROPERTY_LOGICAL                      (1<<0)
127 
128 #define CSS_PROPERTY_VALUE_LIST_USES_COMMAS       (1<<1) /* otherwise spaces */
129 
130 #define CSS_PROPERTY_APPLIES_TO_FIRST_LETTER      (1<<2)
131 #define CSS_PROPERTY_APPLIES_TO_FIRST_LINE        (1<<3)
132 #define CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE \
133   (CSS_PROPERTY_APPLIES_TO_FIRST_LETTER | CSS_PROPERTY_APPLIES_TO_FIRST_LINE)
134 
135 // Note that 'background-color' is ignored differently from the other
136 // properties that have this set, but that's just special-cased.
137 #define CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED (1<<4)
138 
139 // A property that needs to have image loads started when a URL value
140 // for the property is used for an element.  This is supported only
141 // for a few possible value formats: image directly in the value; list
142 // of images; and with CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0, image in slot
143 // 0 of an array, or list of such arrays.
144 #define CSS_PROPERTY_START_IMAGE_LOADS            (1<<5)
145 
146 // Should be set only for properties with START_IMAGE_LOADS.  Indicates
147 // that the property has an array value with a URL/image value at index
148 // 0 in the array, rather than the URL/image being in the value or value
149 // list.
150 #define CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0          (1<<6)
151 
152 // This is a logical property that represents some value associated with
153 // a logical axis rather than a logical box side, and thus has two
154 // corresponding physical properties it could set rather than four.  For
155 // example, the block-size logical property has this flag set, as it
156 // represents the size in either the block or inline axis dimensions, and
157 // has two corresponding physical properties, width and height.  Must not
158 // be used in conjunction with CSS_PROPERTY_LOGICAL_END_EDGE.
159 #define CSS_PROPERTY_LOGICAL_AXIS                 (1<<7)
160 
161 // This property allows calc() between lengths and percentages and
162 // stores such calc() expressions in its style structs (typically in an
163 // nsStyleCoord, although this is not the case for 'background-position'
164 // and 'background-size').
165 #define CSS_PROPERTY_STORES_CALC                  (1<<8)
166 
167 // Define what mechanism the CSS parser uses for parsing the property.
168 // See CSSParserImpl::ParseProperty(nsCSSPropertyID).  Don't use 0 so that
169 // we can verify that every property sets one of the values.
170 //
171 // CSS_PROPERTY_PARSE_FUNCTION must be used for shorthand properties,
172 // since it's the only mechanism that allows appending values for
173 // separate properties.  Longhand properties that require custom parsing
174 // functions should prefer using CSS_PROPERTY_PARSE_VALUE (or
175 // CSS_PROPERTY_PARSE_VALUE_LIST) and
176 // CSS_PROPERTY_VALUE_PARSER_FUNCTION, though a number of existing
177 // longhand properties use CSS_PROPERTY_PARSE_FUNCTION instead.
178 #define CSS_PROPERTY_PARSE_PROPERTY_MASK          (7<<9)
179 #define CSS_PROPERTY_PARSE_INACCESSIBLE           (1<<9)
180 #define CSS_PROPERTY_PARSE_FUNCTION               (2<<9)
181 #define CSS_PROPERTY_PARSE_VALUE                  (3<<9)
182 #define CSS_PROPERTY_PARSE_VALUE_LIST             (4<<9)
183 
184 // See CSSParserImpl::ParseSingleValueProperty and comment above
185 // CSS_PROPERTY_PARSE_FUNCTION (which is different).
186 #define CSS_PROPERTY_VALUE_PARSER_FUNCTION        (1<<12)
187 static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK &
188                CSS_PROPERTY_VALUE_PARSER_FUNCTION) == 0,
189               "didn't leave enough room for the parse property constants");
190 
191 #define CSS_PROPERTY_VALUE_RESTRICTION_MASK       (3<<13)
192 // The parser (in particular, CSSParserImpl::ParseSingleValueProperty)
193 // should enforce that the value of this property must be 0 or larger.
194 #define CSS_PROPERTY_VALUE_NONNEGATIVE            (1<<13)
195 // The parser (in particular, CSSParserImpl::ParseSingleValueProperty)
196 // should enforce that the value of this property must be 1 or larger.
197 #define CSS_PROPERTY_VALUE_AT_LEAST_ONE           (2<<13)
198 
199 // Does this property support the hashless hex color quirk in quirks mode?
200 #define CSS_PROPERTY_HASHLESS_COLOR_QUIRK         (1<<15)
201 
202 // Does this property support the unitless length quirk in quirks mode?
203 #define CSS_PROPERTY_UNITLESS_LENGTH_QUIRK        (1<<16)
204 
205 // Is this property (which must be a shorthand) really an alias?
206 #define CSS_PROPERTY_IS_ALIAS                     (1<<17)
207 
208 // Does the property apply to ::placeholder?
209 #define CSS_PROPERTY_APPLIES_TO_PLACEHOLDER       (1<<18)
210 
211 // This property is allowed in an @page rule.
212 #define CSS_PROPERTY_APPLIES_TO_PAGE_RULE         (1<<19)
213 
214 // This property's getComputedStyle implementation requires layout to be
215 // flushed.
216 #define CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH     (1<<20)
217 
218 // This property requires a stacking context.
219 #define CSS_PROPERTY_CREATES_STACKING_CONTEXT     (1<<21)
220 
221 // The following two flags along with the pref defines where the this
222 // property can be used:
223 // * If none of the two flags is presented, the pref completely controls
224 //   the availability of this property. And in that case, if it has no
225 //   pref, this property is usable everywhere.
226 // * If any of the flags is set, this property is always enabled in the
227 //   specific contexts regardless of the value of the pref. If there is
228 //   no pref for this property at all in this case, it is an internal-
229 //   only property, which cannot be used anywhere else, and should be
230 //   wrapped in "#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL".
231 // Note that, these flags have no effect on the use of aliases of this
232 // property.
233 // Furthermore, for the purposes of animation (including triggering
234 // transitions) these flags are ignored. That is, if the property is disabled
235 // by a pref, we will *not* run animations or transitions on it even in
236 // UA sheets or chrome.
237 #define CSS_PROPERTY_ENABLED_MASK                 (3<<22)
238 #define CSS_PROPERTY_ENABLED_IN_UA_SHEETS         (1<<22)
239 #define CSS_PROPERTY_ENABLED_IN_CHROME            (1<<23)
240 #define CSS_PROPERTY_ENABLED_IN_UA_SHEETS_AND_CHROME \
241   (CSS_PROPERTY_ENABLED_IN_UA_SHEETS | CSS_PROPERTY_ENABLED_IN_CHROME)
242 
243 // This property's unitless values are pixels.
244 #define CSS_PROPERTY_NUMBERS_ARE_PIXELS           (1<<24)
245 
246 // This property is a logical property for one of the two block axis
247 // sides (such as margin-block-start or margin-block-end).  Must only be
248 // set if CSS_PROPERTY_LOGICAL is set.  When not set, the logical
249 // property is for one of the two inline axis sides (such as
250 // margin-inline-start or margin-inline-end).
251 #define CSS_PROPERTY_LOGICAL_BLOCK_AXIS           (1<<25)
252 
253 // This property is a logical property for the "end" edge of the
254 // axis determined by the presence or absence of
255 // CSS_PROPERTY_LOGICAL_BLOCK_AXIS (such as margin-block-end or
256 // margin-inline-end).  Must only be set if CSS_PROPERTY_LOGICAL is set.
257 // When not set, the logical property is for the "start" edge (such as
258 // margin-block-start or margin-inline-start).
259 #define CSS_PROPERTY_LOGICAL_END_EDGE             (1<<26)
260 
261 // This property can be animated on the compositor.
262 #define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR    (1<<27)
263 
264 // This property is an internal property that is not represented
265 // in the DOM.  Properties with this flag must be defined in an #ifndef
266 // CSS_PROP_LIST_EXCLUDE_INTERNAL section of nsCSSPropList.h.
267 #define CSS_PROPERTY_INTERNAL                     (1<<28)
268 
269 // This property has values that can establish a containing block for
270 // fixed positioned and absolutely positioned elements.
271 // This should be set for any properties that can cause an element to be
272 // such a containing block, as implemented in
273 // nsStyleDisplay::IsFixedPosContainingBlock.
274 #define CSS_PROPERTY_FIXPOS_CB                    (1<<29)
275 
276 // This property has values that can establish a containing block for
277 // absolutely positioned elements.
278 // This should be set for any properties that can cause an element to be
279 // such a containing block, as implemented in
280 // nsStyleDisplay::IsAbsPosContainingBlock.
281 // It does not need to be set for properties that also have
282 // CSS_PROPERTY_FIXPOS_CB set.
283 #define CSS_PROPERTY_ABSPOS_CB                    (1<<30)
284 
285 /**
286  * Types of animatable values.
287  */
288 enum nsStyleAnimType {
289   // requires a custom implementation in
290   // StyleAnimationValue::ExtractComputedValue
291   eStyleAnimType_Custom,
292 
293   // nsStyleCoord with animatable values
294   eStyleAnimType_Coord,
295 
296   // same as Coord, except for one side of an nsStyleSides
297   // listed in the same order as the NS_STYLE_* constants
298   eStyleAnimType_Sides_Top,
299   eStyleAnimType_Sides_Right,
300   eStyleAnimType_Sides_Bottom,
301   eStyleAnimType_Sides_Left,
302 
303   // similar, but for the *pair* of coord members of an nsStyleCorners
304   // for the relevant corner
305   eStyleAnimType_Corner_TopLeft,
306   eStyleAnimType_Corner_TopRight,
307   eStyleAnimType_Corner_BottomRight,
308   eStyleAnimType_Corner_BottomLeft,
309 
310   // nscoord values
311   eStyleAnimType_nscoord,
312 
313   // float values
314   eStyleAnimType_float,
315 
316   // nscolor values
317   eStyleAnimType_Color,
318 
319   // StyleComplexColor values
320   eStyleAnimType_ComplexColor,
321 
322   // nsStyleSVGPaint values
323   eStyleAnimType_PaintServer,
324 
325   // RefPtr<nsCSSShadowArray> values
326   eStyleAnimType_Shadow,
327 
328   // discrete values
329   eStyleAnimType_Discrete,
330 
331   // property not animatable
332   eStyleAnimType_None
333 };
334 
335 // Empty class derived from nsIAtom so that function signatures can
336 // require an atom from the atom list.
337 class nsICSSProperty : public nsIAtom {};
338 
339 class nsCSSProps {
340 public:
341   typedef mozilla::CSSEnabledState EnabledState;
342 
343   struct KTableEntry
344   {
345     // KTableEntry objects can be initialized either with an int16_t value
346     // or a value of an enumeration type that can fit within an int16_t.
347 
KTableEntryKTableEntry348     constexpr KTableEntry(nsCSSKeyword aKeyword, int16_t aValue)
349       : mKeyword(aKeyword)
350       , mValue(aValue)
351     {
352     }
353 
354     template<typename T,
355              typename = typename std::enable_if<std::is_enum<T>::value>::type>
KTableEntryKTableEntry356     constexpr KTableEntry(nsCSSKeyword aKeyword, T aValue)
357       : mKeyword(aKeyword)
358       , mValue(static_cast<int16_t>(aValue))
359     {
360       static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
361                     "aValue must be an enum that fits within mValue");
362     }
363 
364     nsCSSKeyword mKeyword;
365     int16_t mValue;
366   };
367 
368   static void AddRefTable(void);
369   static void ReleaseTable(void);
370 
371   // Looks up the property with name aProperty and returns its corresponding
372   // nsCSSPropertyID value.  If aProperty is the name of a custom property,
373   // then eCSSPropertyExtra_variable will be returned.
374   static nsCSSPropertyID LookupProperty(const nsAString& aProperty,
375                                       EnabledState aEnabled);
376   static nsCSSPropertyID LookupProperty(const nsACString& aProperty,
377                                       EnabledState aEnabled);
378   // As above, but looked up using a property's IDL name.
379   // eCSSPropertyExtra_variable won't be returned from these methods.
380   static nsCSSPropertyID LookupPropertyByIDLName(
381       const nsAString& aPropertyIDLName,
382       EnabledState aEnabled);
383   static nsCSSPropertyID LookupPropertyByIDLName(
384       const nsACString& aPropertyIDLName,
385       EnabledState aEnabled);
386 
387   // Returns whether aProperty is a custom property name, i.e. begins with
388   // "--".  This assumes that the CSS Variables pref has been enabled.
389   static bool IsCustomPropertyName(const nsAString& aProperty);
390   static bool IsCustomPropertyName(const nsACString& aProperty);
391 
IsShorthand(nsCSSPropertyID aProperty)392   static inline bool IsShorthand(nsCSSPropertyID aProperty) {
393     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
394                "out of range");
395     return (aProperty >= eCSSProperty_COUNT_no_shorthands);
396   }
397 
398   // Must be given a longhand property.
399   static bool IsInherited(nsCSSPropertyID aProperty);
400 
401   // Same but for @font-face descriptors
402   static nsCSSFontDesc LookupFontDesc(const nsAString& aProperty);
403   static nsCSSFontDesc LookupFontDesc(const nsACString& aProperty);
404 
405   // For @counter-style descriptors
406   static nsCSSCounterDesc LookupCounterDesc(const nsAString& aProperty);
407   static nsCSSCounterDesc LookupCounterDesc(const nsACString& aProperty);
408 
409   // For predefined counter styles which need to be lower-cased during parse
410   static bool IsPredefinedCounterStyle(const nsAString& aStyle);
411   static bool IsPredefinedCounterStyle(const nsACString& aStyle);
412 
413   // Given a property enum, get the string value
414   static const nsAFlatCString& GetStringValue(nsCSSPropertyID aProperty);
415   static const nsAFlatCString& GetStringValue(nsCSSFontDesc aFontDesc);
416   static const nsAFlatCString& GetStringValue(nsCSSCounterDesc aCounterDesc);
417 
418   // Given a CSS Property and a Property Enum Value
419   // Return back a const nsString& representation of the
420   // value. Return back nullstr if no value is found
421   static const nsAFlatCString& LookupPropertyValue(nsCSSPropertyID aProperty, int32_t aValue);
422 
423   // Get a color name for a predefined color value like buttonhighlight or activeborder
424   // Sets the aStr param to the name of the propertyID
425   static bool GetColorName(int32_t aPropID, nsCString &aStr);
426 
427   // Returns the index of |aKeyword| in |aTable|, if it exists there;
428   // otherwise, returns -1.
429   // NOTE: Generally, clients should call FindKeyword() instead of this method.
430   static int32_t FindIndexOfKeyword(nsCSSKeyword aKeyword,
431                                     const KTableEntry aTable[]);
432 
433   // Find |aKeyword| in |aTable|, if found set |aValue| to its corresponding value.
434   // If not found, return false and do not set |aValue|.
435   static bool FindKeyword(nsCSSKeyword aKeyword, const KTableEntry aTable[],
436                           int32_t& aValue);
437   // Return the first keyword in |aTable| that has the corresponding value |aValue|.
438   // Return |eCSSKeyword_UNKNOWN| if not found.
439   static nsCSSKeyword ValueToKeywordEnum(int32_t aValue,
440                                          const KTableEntry aTable[]);
441   template<typename T,
442            typename = typename std::enable_if<std::is_enum<T>::value>::type>
ValueToKeywordEnum(T aValue,const KTableEntry aTable[])443   static nsCSSKeyword ValueToKeywordEnum(T aValue,
444                                          const KTableEntry aTable[])
445   {
446     static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
447                   "aValue must be an enum that fits within KTableEntry::mValue");
448     return ValueToKeywordEnum(static_cast<int16_t>(aValue), aTable);
449   }
450   // Ditto but as a string, return "" when not found.
451   static const nsAFlatCString& ValueToKeyword(int32_t aValue,
452                                               const KTableEntry aTable[]);
453   template<typename T,
454            typename = typename std::enable_if<std::is_enum<T>::value>::type>
ValueToKeyword(T aValue,const KTableEntry aTable[])455   static const nsAFlatCString& ValueToKeyword(T aValue,
456                                               const KTableEntry aTable[])
457   {
458     static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
459                   "aValue must be an enum that fits within KTableEntry::mValue");
460     return ValueToKeyword(static_cast<int16_t>(aValue), aTable);
461   }
462 
463   static const nsStyleStructID kSIDTable[eCSSProperty_COUNT_no_shorthands];
464   static const KTableEntry* const kKeywordTableTable[eCSSProperty_COUNT_no_shorthands];
465   static const nsStyleAnimType kAnimTypeTable[eCSSProperty_COUNT_no_shorthands];
466   static const ptrdiff_t
467     kStyleStructOffsetTable[eCSSProperty_COUNT_no_shorthands];
468 
469 private:
470   static const uint32_t        kFlagsTable[eCSSProperty_COUNT];
471 
472 public:
PropHasFlags(nsCSSPropertyID aProperty,uint32_t aFlags)473   static inline bool PropHasFlags(nsCSSPropertyID aProperty, uint32_t aFlags)
474   {
475     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
476                "out of range");
477     MOZ_ASSERT(!(aFlags & CSS_PROPERTY_PARSE_PROPERTY_MASK),
478                "The CSS_PROPERTY_PARSE_* values are not bitflags; don't pass "
479                "them to PropHasFlags.  You probably want PropertyParseType "
480                "instead.");
481     return (nsCSSProps::kFlagsTable[aProperty] & aFlags) == aFlags;
482   }
483 
PropertyParseType(nsCSSPropertyID aProperty)484   static inline uint32_t PropertyParseType(nsCSSPropertyID aProperty)
485   {
486     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
487                "out of range");
488     return nsCSSProps::kFlagsTable[aProperty] &
489            CSS_PROPERTY_PARSE_PROPERTY_MASK;
490   }
491 
ValueRestrictions(nsCSSPropertyID aProperty)492   static inline uint32_t ValueRestrictions(nsCSSPropertyID aProperty)
493   {
494     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
495                "out of range");
496     return nsCSSProps::kFlagsTable[aProperty] &
497            CSS_PROPERTY_VALUE_RESTRICTION_MASK;
498   }
499 
500 private:
501   // Lives in nsCSSParser.cpp for the macros it depends on.
502   static const uint32_t kParserVariantTable[eCSSProperty_COUNT_no_shorthands];
503 
504 public:
ParserVariant(nsCSSPropertyID aProperty)505   static inline uint32_t ParserVariant(nsCSSPropertyID aProperty) {
506     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
507                "out of range");
508     return nsCSSProps::kParserVariantTable[aProperty];
509   }
510 
511 private:
512   // A table for shorthand properties.  The appropriate index is the
513   // property ID minus eCSSProperty_COUNT_no_shorthands.
514   static const nsCSSPropertyID *const
515     kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands];
516 
517 public:
518   static inline
SubpropertyEntryFor(nsCSSPropertyID aProperty)519   const nsCSSPropertyID * SubpropertyEntryFor(nsCSSPropertyID aProperty) {
520     MOZ_ASSERT(eCSSProperty_COUNT_no_shorthands <= aProperty &&
521                aProperty < eCSSProperty_COUNT,
522                "out of range");
523     return nsCSSProps::kSubpropertyTable[aProperty -
524                                          eCSSProperty_COUNT_no_shorthands];
525   }
526 
527   // Returns an eCSSProperty_UNKNOWN-terminated array of the shorthand
528   // properties containing |aProperty|, sorted from those that contain
529   // the most properties to those that contain the least.
ShorthandsContaining(nsCSSPropertyID aProperty)530   static const nsCSSPropertyID * ShorthandsContaining(nsCSSPropertyID aProperty) {
531     MOZ_ASSERT(gShorthandsContainingPool, "uninitialized");
532     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
533                "out of range");
534     return gShorthandsContainingTable[aProperty];
535   }
536 private:
537   // gShorthandsContainingTable is an array of the return values for
538   // ShorthandsContaining (arrays of nsCSSPropertyID terminated by
539   // eCSSProperty_UNKNOWN) pointing into memory in
540   // gShorthandsContainingPool (which contains all of those arrays in a
541   // single allocation, and is the one pointer that should be |free|d).
542   static nsCSSPropertyID *gShorthandsContainingTable[eCSSProperty_COUNT_no_shorthands];
543   static nsCSSPropertyID* gShorthandsContainingPool;
544   static bool BuildShorthandsContainingTable();
545 
546 private:
547   static const size_t gPropertyCountInStruct[nsStyleStructID_Length];
548   static const size_t gPropertyIndexInStruct[eCSSProperty_COUNT_no_shorthands];
549 public:
550   /**
551    * Return the number of properties that must be cascaded when
552    * nsRuleNode builds the nsStyle* for aSID.
553    */
PropertyCountInStruct(nsStyleStructID aSID)554   static size_t PropertyCountInStruct(nsStyleStructID aSID) {
555     MOZ_ASSERT(0 <= aSID && aSID < nsStyleStructID_Length,
556                "out of range");
557     return gPropertyCountInStruct[aSID];
558   }
559   /**
560    * Return an index for aProperty that is unique within its SID and in
561    * the range 0 <= index < PropertyCountInStruct(aSID).
562    */
PropertyIndexInStruct(nsCSSPropertyID aProperty)563   static size_t PropertyIndexInStruct(nsCSSPropertyID aProperty) {
564     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
565                "out of range");
566     return gPropertyIndexInStruct[aProperty];
567   }
568 
569 private:
570   // A table for logical property groups.  Indexes are
571   // nsCSSPropertyLogicalGroup values.
572   static const nsCSSPropertyID* const
573     kLogicalGroupTable[eCSSPropertyLogicalGroup_COUNT];
574 
575 public:
576   /**
577    * Returns an array of longhand physical properties which can be set by
578    * the argument, which must be a logical longhand property.  The returned
579    * array is terminated by an eCSSProperty_UNKNOWN value.  For example,
580    * given eCSSProperty_margin_block_start, returns an array of the four
581    * properties eCSSProperty_margin_top, eCSSProperty_margin_right,
582    * eCSSProperty_margin_bottom and eCSSProperty_margin_left, followed
583    * by the sentinel.
584    *
585    * When called with a property that has the CSS_PROPERTY_LOGICAL_AXIS
586    * flag, the returned array will have two values preceding the sentinel;
587    * otherwise it will have four.
588    *
589    * (Note that the running time of this function is proportional to the
590    * number of logical longhand properties that exist.  If we start
591    * getting too many of these properties, we should make kLogicalGroupTable
592    * be a simple array of eCSSProperty_COUNT length.)
593    */
594   static const nsCSSPropertyID* LogicalGroup(nsCSSPropertyID aProperty);
595 
596 private:
597   static bool gPropertyEnabled[eCSSProperty_COUNT_with_aliases];
598 
599 private:
600   // Defined in the generated nsCSSPropsGenerated.inc.
601   static const char* const kIDLNameTable[eCSSProperty_COUNT];
602 
603 public:
604   /**
605    * Returns the IDL name of the specified property, which must be a
606    * longhand, logical or shorthand property.  The IDL name is the property
607    * name with any hyphen-lowercase character pairs replaced by an
608    * uppercase character:
609    * https://drafts.csswg.org/cssom/#css-property-to-idl-attribute
610    *
611    * As a special case, the string "cssFloat" is returned for the float
612    * property.  nullptr is returned for internal properties.
613    */
PropertyIDLName(nsCSSPropertyID aProperty)614   static const char* PropertyIDLName(nsCSSPropertyID aProperty)
615   {
616     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
617                "out of range");
618     return kIDLNameTable[aProperty];
619   }
620 
621 private:
622   static const int32_t kIDLNameSortPositionTable[eCSSProperty_COUNT];
623 
624 public:
625   /**
626    * Returns the position of the specified property in a list of all
627    * properties sorted by their IDL name.
628    */
PropertyIDLNameSortPosition(nsCSSPropertyID aProperty)629   static int32_t PropertyIDLNameSortPosition(nsCSSPropertyID aProperty)
630   {
631     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT,
632                "out of range");
633     return kIDLNameSortPositionTable[aProperty];
634   }
635 
IsEnabled(nsCSSPropertyID aProperty)636   static bool IsEnabled(nsCSSPropertyID aProperty) {
637     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_with_aliases,
638                "out of range");
639     return gPropertyEnabled[aProperty];
640   }
641 
642   // A table for the use counter associated with each CSS property.  If a
643   // property does not have a use counter defined in UseCounters.conf, then
644   // its associated entry is |eUseCounter_UNKNOWN|.
645   static const mozilla::UseCounter gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands];
646 
647 public:
648 
UseCounterFor(nsCSSPropertyID aProperty)649   static mozilla::UseCounter UseCounterFor(nsCSSPropertyID aProperty) {
650     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
651                "out of range");
652     return gPropertyUseCounter[aProperty];
653   }
654 
IsEnabled(nsCSSPropertyID aProperty,EnabledState aEnabled)655   static bool IsEnabled(nsCSSPropertyID aProperty, EnabledState aEnabled)
656   {
657     if (IsEnabled(aProperty)) {
658       return true;
659     }
660     if (aEnabled == EnabledState::eIgnoreEnabledState) {
661       return true;
662     }
663     if ((aEnabled & EnabledState::eInUASheets) &&
664         PropHasFlags(aProperty, CSS_PROPERTY_ENABLED_IN_UA_SHEETS))
665     {
666       return true;
667     }
668     if ((aEnabled & EnabledState::eInChrome) &&
669         PropHasFlags(aProperty, CSS_PROPERTY_ENABLED_IN_CHROME))
670     {
671       return true;
672     }
673     return false;
674   }
675 
676 public:
677   static void AddRefAtoms();
AtomForProperty(nsCSSPropertyID aProperty)678   static nsICSSProperty* AtomForProperty(nsCSSPropertyID aProperty)
679   {
680     MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT);
681     return gPropertyAtomTable[aProperty];
682   }
683 
684 #define CSS_PROP(name_, id_, ...) static nsICSSProperty* id_;
685 #define CSS_PROP_SHORTHAND(name_, id_, ...) CSS_PROP(name_, id_, ...)
686 #define CSS_PROP_LIST_INCLUDE_LOGICAL
687 #include "nsCSSPropList.h"
688 #undef CSS_PROP_LIST_INCLUDE_LOGICAL
689 #undef CSS_PROP_SHORTHAND
690 #undef CSS_PROP
691 
692 private:
693   static nsICSSProperty* gPropertyAtomTable[eCSSProperty_COUNT];
694 
695 public:
696 
697 // Storing the enabledstate_ value in an nsCSSPropertyID variable is a small hack
698 // to avoid needing a separate variable declaration for its real type
699 // (CSSEnabledState), which would then require using a block and
700 // therefore a pair of macros by consumers for the start and end of the loop.
701 #define CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(it_, prop_, enabledstate_)   \
702   for (const nsCSSPropertyID *it_ = nsCSSProps::SubpropertyEntryFor(prop_), \
703                             es_ = (nsCSSPropertyID)((enabledstate_) |       \
704                                                   CSSEnabledState(0));    \
705        *it_ != eCSSProperty_UNKNOWN; ++it_)                               \
706     if (nsCSSProps::IsEnabled(*it_, (mozilla::CSSEnabledState) es_))
707 
708   // Keyword/Enum value tables
709   static const KTableEntry kAnimationDirectionKTable[];
710   static const KTableEntry kAnimationFillModeKTable[];
711   static const KTableEntry kAnimationIterationCountKTable[];
712   static const KTableEntry kAnimationPlayStateKTable[];
713   static const KTableEntry kAnimationTimingFunctionKTable[];
714   static const KTableEntry kAppearanceKTable[];
715   static const KTableEntry kAzimuthKTable[];
716   static const KTableEntry kBackfaceVisibilityKTable[];
717   static const KTableEntry kTransformStyleKTable[];
718   static const KTableEntry kImageLayerAttachmentKTable[];
719   static const KTableEntry kImageLayerOriginKTable[];
720   static const KTableEntry kImageLayerPositionKTable[];
721   static const KTableEntry kImageLayerRepeatKTable[];
722   static const KTableEntry kImageLayerRepeatPartKTable[];
723   static const KTableEntry kImageLayerSizeKTable[];
724   static const KTableEntry kImageLayerCompositeKTable[];
725   static const KTableEntry kImageLayerModeKTable[];
726   // Not const because we modify its entries when the pref
727   // "layout.css.background-clip.text" changes:
728   static KTableEntry kBackgroundClipKTable[];
729   static const KTableEntry kBlendModeKTable[];
730   static const KTableEntry kBorderCollapseKTable[];
731   static const KTableEntry kBorderImageRepeatKTable[];
732   static const KTableEntry kBorderImageSliceKTable[];
733   static const KTableEntry kBorderStyleKTable[];
734   static const KTableEntry kBorderWidthKTable[];
735   static const KTableEntry kBoxAlignKTable[];
736   static const KTableEntry kBoxDecorationBreakKTable[];
737   static const KTableEntry kBoxDirectionKTable[];
738   static const KTableEntry kBoxOrientKTable[];
739   static const KTableEntry kBoxPackKTable[];
740   static const KTableEntry kClipPathGeometryBoxKTable[];
741   static const KTableEntry kCounterRangeKTable[];
742   static const KTableEntry kCounterSpeakAsKTable[];
743   static const KTableEntry kCounterSymbolsSystemKTable[];
744   static const KTableEntry kCounterSystemKTable[];
745   static const KTableEntry kDominantBaselineKTable[];
746   static const KTableEntry kShapeRadiusKTable[];
747   static const KTableEntry kFillRuleKTable[];
748   static const KTableEntry kFilterFunctionKTable[];
749   static const KTableEntry kImageRenderingKTable[];
750   static const KTableEntry kShapeOutsideShapeBoxKTable[];
751   static const KTableEntry kShapeRenderingKTable[];
752   static const KTableEntry kStrokeLinecapKTable[];
753   static const KTableEntry kStrokeLinejoinKTable[];
754   static const KTableEntry kStrokeContextValueKTable[];
755   static const KTableEntry kVectorEffectKTable[];
756   static const KTableEntry kTextAnchorKTable[];
757   static const KTableEntry kTextRenderingKTable[];
758   static const KTableEntry kColorAdjustKTable[];
759   static const KTableEntry kColorInterpolationKTable[];
760   static const KTableEntry kColumnFillKTable[];
761   static const KTableEntry kBoxPropSourceKTable[];
762   static const KTableEntry kBoxShadowTypeKTable[];
763   static const KTableEntry kBoxSizingKTable[];
764   static const KTableEntry kCaptionSideKTable[];
765   // Not const because we modify its entries when the pref
766   // "layout.css.float-logical-values.enabled" changes:
767   static KTableEntry kClearKTable[];
768   static const KTableEntry kColorKTable[];
769   static const KTableEntry kContentKTable[];
770   static const KTableEntry kControlCharacterVisibilityKTable[];
771   static const KTableEntry kCursorKTable[];
772   static const KTableEntry kDirectionKTable[];
773   // Not const because we modify its entries when various
774   // "layout.css.*.enabled" prefs changes:
775   static KTableEntry kDisplayKTable[];
776   static const KTableEntry kElevationKTable[];
777   static const KTableEntry kEmptyCellsKTable[];
778   // -- tables for parsing the {align,justify}-{content,items,self} properties --
779   static const KTableEntry kAlignAllKeywords[];
780   static const KTableEntry kAlignOverflowPosition[]; // <overflow-position>
781   static const KTableEntry kAlignSelfPosition[];     // <self-position>
782   static const KTableEntry kAlignLegacy[];           // 'legacy'
783   static const KTableEntry kAlignLegacyPosition[];   // 'left/right/center'
784   static const KTableEntry kAlignAutoNormalStretchBaseline[]; // 'auto/normal/stretch/baseline'
785   static const KTableEntry kAlignNormalStretchBaseline[]; // 'normal/stretch/baseline'
786   static const KTableEntry kAlignNormalBaseline[]; // 'normal/baseline'
787   static const KTableEntry kAlignContentDistribution[]; // <content-distribution>
788   static const KTableEntry kAlignContentPosition[]; // <content-position>
789   // -- tables for auto-completion of the {align,justify}-{content,items,self} properties --
790   static const KTableEntry kAutoCompletionAlignJustifySelf[];
791   static const KTableEntry kAutoCompletionAlignItems[];
792   static const KTableEntry kAutoCompletionAlignJustifyContent[];
793   // ------------------------------------------------------------------
794   static const KTableEntry kFlexDirectionKTable[];
795   static const KTableEntry kFlexWrapKTable[];
796   // Not const because we modify its entries when the pref
797   // "layout.css.float-logical-values.enabled" changes:
798   static KTableEntry kFloatKTable[];
799   static const KTableEntry kFloatEdgeKTable[];
800   static const KTableEntry kFontDisplayKTable[];
801   static const KTableEntry kFontKTable[];
802   static const KTableEntry kFontKerningKTable[];
803   static const KTableEntry kFontSizeKTable[];
804   static const KTableEntry kFontSmoothingKTable[];
805   static const KTableEntry kFontStretchKTable[];
806   static const KTableEntry kFontStyleKTable[];
807   static const KTableEntry kFontSynthesisKTable[];
808   static const KTableEntry kFontVariantKTable[];
809   static const KTableEntry kFontVariantAlternatesKTable[];
810   static const KTableEntry kFontVariantAlternatesFuncsKTable[];
811   static const KTableEntry kFontVariantCapsKTable[];
812   static const KTableEntry kFontVariantEastAsianKTable[];
813   static const KTableEntry kFontVariantLigaturesKTable[];
814   static const KTableEntry kFontVariantNumericKTable[];
815   static const KTableEntry kFontVariantPositionKTable[];
816   static const KTableEntry kFontWeightKTable[];
817   static const KTableEntry kGridAutoFlowKTable[];
818   static const KTableEntry kGridTrackBreadthKTable[];
819   static const KTableEntry kHyphensKTable[];
820   static const KTableEntry kImageOrientationKTable[];
821   static const KTableEntry kImageOrientationFlipKTable[];
822   static const KTableEntry kIsolationKTable[];
823   static const KTableEntry kIMEModeKTable[];
824   static const KTableEntry kLineHeightKTable[];
825   static const KTableEntry kListStylePositionKTable[];
826   static const KTableEntry kListStyleKTable[];
827   static const KTableEntry kMaskTypeKTable[];
828   static const KTableEntry kMathVariantKTable[];
829   static const KTableEntry kMathDisplayKTable[];
830   static const KTableEntry kContainKTable[];
831   static const KTableEntry kContextOpacityKTable[];
832   static const KTableEntry kContextPatternKTable[];
833   static const KTableEntry kObjectFitKTable[];
834   static const KTableEntry kOrientKTable[];
835   static const KTableEntry kOutlineStyleKTable[];
836   static const KTableEntry kOverflowKTable[];
837   static const KTableEntry kOverflowSubKTable[];
838   static const KTableEntry kOverflowClipBoxKTable[];
839   static const KTableEntry kOverflowWrapKTable[];
840   static const KTableEntry kPageBreakKTable[];
841   static const KTableEntry kPageBreakInsideKTable[];
842   static const KTableEntry kPageMarksKTable[];
843   static const KTableEntry kPageSizeKTable[];
844   static const KTableEntry kPitchKTable[];
845   static const KTableEntry kPointerEventsKTable[];
846   static const KTableEntry kPositionKTable[];
847   static const KTableEntry kRadialGradientShapeKTable[];
848   static const KTableEntry kRadialGradientSizeKTable[];
849   static const KTableEntry kRadialGradientLegacySizeKTable[];
850   static const KTableEntry kResizeKTable[];
851   static const KTableEntry kRubyAlignKTable[];
852   static const KTableEntry kRubyPositionKTable[];
853   static const KTableEntry kScrollBehaviorKTable[];
854   static const KTableEntry kScrollSnapTypeKTable[];
855   static const KTableEntry kSpeakKTable[];
856   static const KTableEntry kSpeakHeaderKTable[];
857   static const KTableEntry kSpeakNumeralKTable[];
858   static const KTableEntry kSpeakPunctuationKTable[];
859   static const KTableEntry kSpeechRateKTable[];
860   static const KTableEntry kStackSizingKTable[];
861   static const KTableEntry kTableLayoutKTable[];
862   // Not const because we modify its entries when the pref
863   // "layout.css.text-align-unsafe-value.enabled" changes:
864   static KTableEntry kTextAlignKTable[];
865   static KTableEntry kTextAlignLastKTable[];
866   static const KTableEntry kTextCombineUprightKTable[];
867   static const KTableEntry kTextDecorationLineKTable[];
868   static const KTableEntry kTextDecorationStyleKTable[];
869   static const KTableEntry kTextEmphasisPositionKTable[];
870   static const KTableEntry kTextEmphasisStyleFillKTable[];
871   static const KTableEntry kTextEmphasisStyleShapeKTable[];
872   static const KTableEntry kTextOrientationKTable[];
873   static const KTableEntry kTextOverflowKTable[];
874   static const KTableEntry kTextTransformKTable[];
875   static const KTableEntry kTouchActionKTable[];
876   static const KTableEntry kTopLayerKTable[];
877   static const KTableEntry kTransformBoxKTable[];
878   static const KTableEntry kTransitionTimingFunctionKTable[];
879   static const KTableEntry kUnicodeBidiKTable[];
880   static const KTableEntry kUserFocusKTable[];
881   static const KTableEntry kUserInputKTable[];
882   static const KTableEntry kUserModifyKTable[];
883   static const KTableEntry kUserSelectKTable[];
884   static const KTableEntry kVerticalAlignKTable[];
885   static const KTableEntry kVisibilityKTable[];
886   static const KTableEntry kVolumeKTable[];
887   static const KTableEntry kWhitespaceKTable[];
888   static const KTableEntry kWidthKTable[]; // also min-width, max-width
889   static const KTableEntry kWindowDraggingKTable[];
890   static const KTableEntry kWindowShadowKTable[];
891   static const KTableEntry kWordBreakKTable[];
892   static const KTableEntry kWritingModeKTable[];
893 };
894 
895 #endif /* nsCSSProps_h___ */
896