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 <ostream> 17 #include <type_traits> 18 19 #include "nsString.h" 20 #include "nsCSSPropertyID.h" 21 #include "nsStyleStructFwd.h" 22 #include "mozilla/UseCounter.h" 23 #include "mozilla/CSSEnabledState.h" 24 #include "mozilla/CSSPropFlags.h" 25 #include "mozilla/EnumTypeTraits.h" 26 #include "mozilla/Preferences.h" 27 #include "mozilla/gfx/gfxVarReceiver.h" 28 #include "nsXULAppAPI.h" 29 30 // Length of the "--" prefix on custom names (such as custom property names, 31 // and, in the future, custom media query names). 32 #define CSS_CUSTOM_NAME_PREFIX_LENGTH 2 33 34 namespace mozilla { 35 class ComputedStyle; 36 } 37 38 extern "C" { 39 nsCSSPropertyID Servo_ResolveLogicalProperty(nsCSSPropertyID, 40 const mozilla::ComputedStyle*); 41 nsCSSPropertyID Servo_Property_LookupEnabledForAllContent(const nsACString*); 42 const uint8_t* Servo_Property_GetName(nsCSSPropertyID, uint32_t* aLength); 43 } 44 45 class nsCSSProps { 46 public: 47 typedef mozilla::CSSEnabledState EnabledState; 48 typedef mozilla::CSSPropFlags Flags; 49 50 static void AddRefTable(void); 51 static void ReleaseTable(void); 52 53 // Looks up the property with name aProperty and returns its corresponding 54 // nsCSSPropertyID value. If aProperty is the name of a custom property, 55 // then eCSSPropertyExtra_variable will be returned. 56 // 57 // This only returns properties enabled for all content, and resolves aliases 58 // to return the aliased property. LookupProperty(const nsACString & aProperty)59 static nsCSSPropertyID LookupProperty(const nsACString& aProperty) { 60 return Servo_Property_LookupEnabledForAllContent(&aProperty); 61 } 62 63 // As above, but looked up using a property's IDL name. 64 // eCSSPropertyExtra_variable won't be returned from this method. 65 static nsCSSPropertyID LookupPropertyByIDLName( 66 const nsACString& aPropertyIDLName, EnabledState aEnabled); 67 68 // Returns whether aProperty is a custom property name, i.e. begins with 69 // "--". This assumes that the CSS Variables pref has been enabled. 70 static bool IsCustomPropertyName(const nsACString& aProperty); 71 IsShorthand(nsCSSPropertyID aProperty)72 static bool IsShorthand(nsCSSPropertyID aProperty) { 73 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, 74 "out of range"); 75 return (aProperty >= eCSSProperty_COUNT_no_shorthands); 76 } 77 78 // Same but for @font-face descriptors 79 static nsCSSFontDesc LookupFontDesc(const nsACString& aProperty); 80 81 // The relevant invariants are asserted in Document.cpp UseCounterFor(nsCSSPropertyID aProperty)82 static mozilla::UseCounter UseCounterFor(nsCSSPropertyID aProperty) { 83 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_with_aliases, 84 "out of range"); 85 return mozilla::UseCounter(size_t(mozilla::eUseCounter_FirstCSSProperty) + 86 size_t(aProperty)); 87 } 88 89 // Given a property enum, get the string value 90 // 91 // This string is static. GetStringValue(nsCSSPropertyID aProperty)92 static const nsDependentCSubstring GetStringValue(nsCSSPropertyID aProperty) { 93 uint32_t len; 94 const uint8_t* chars = Servo_Property_GetName(aProperty, &len); 95 return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len); 96 } 97 98 static const nsCString& GetStringValue(nsCSSFontDesc aFontDesc); 99 static const nsCString& GetStringValue(nsCSSCounterDesc aCounterDesc); 100 101 private: 102 static const Flags kFlagsTable[eCSSProperty_COUNT]; 103 104 public: PropHasFlags(nsCSSPropertyID aProperty,Flags aFlags)105 static bool PropHasFlags(nsCSSPropertyID aProperty, Flags aFlags) { 106 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, 107 "out of range"); 108 return (nsCSSProps::kFlagsTable[aProperty] & aFlags) == aFlags; 109 } 110 Physicalize(nsCSSPropertyID aProperty,const mozilla::ComputedStyle & aStyle)111 static nsCSSPropertyID Physicalize(nsCSSPropertyID aProperty, 112 const mozilla::ComputedStyle& aStyle) { 113 MOZ_ASSERT(!IsShorthand(aProperty)); 114 if (PropHasFlags(aProperty, Flags::IsLogical)) { 115 return Servo_ResolveLogicalProperty(aProperty, &aStyle); 116 } 117 return aProperty; 118 } 119 120 private: 121 // A table for shorthand properties. The appropriate index is the 122 // property ID minus eCSSProperty_COUNT_no_shorthands. 123 static const nsCSSPropertyID* const 124 kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands]; 125 126 public: 127 /** 128 * Recoumputes the enabled state of a pref. If aPrefName is nullptr, 129 * recomputes the state of all prefs in gPropertyEnabled. 130 * aClosure is the pref callback closure data, which is not used. 131 */ 132 static void RecomputeEnabledState(const char* aPrefName, 133 void* aClosure = nullptr); 134 135 /** 136 * Retrieve a singleton receiver to register with gfxVars 137 */ 138 static mozilla::gfx::gfxVarReceiver& GfxVarReceiver(); 139 SubpropertyEntryFor(nsCSSPropertyID aProperty)140 static const nsCSSPropertyID* SubpropertyEntryFor(nsCSSPropertyID aProperty) { 141 MOZ_ASSERT(eCSSProperty_COUNT_no_shorthands <= aProperty && 142 aProperty < eCSSProperty_COUNT, 143 "out of range"); 144 return nsCSSProps::kSubpropertyTable[aProperty - 145 eCSSProperty_COUNT_no_shorthands]; 146 } 147 148 private: 149 static bool gPropertyEnabled[eCSSProperty_COUNT_with_aliases]; 150 151 private: 152 // Defined in the generated nsCSSPropsGenerated.inc. 153 static const char* const kIDLNameTable[eCSSProperty_COUNT]; 154 155 public: 156 /** 157 * Returns the IDL name of the specified property, which must be a 158 * longhand, logical or shorthand property. The IDL name is the property 159 * name with any hyphen-lowercase character pairs replaced by an 160 * uppercase character: 161 * https://drafts.csswg.org/cssom/#css-property-to-idl-attribute 162 * 163 * As a special case, the string "cssFloat" is returned for the float 164 * property. nullptr is returned for internal properties. 165 */ PropertyIDLName(nsCSSPropertyID aProperty)166 static const char* PropertyIDLName(nsCSSPropertyID aProperty) { 167 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, 168 "out of range"); 169 return kIDLNameTable[aProperty]; 170 } 171 172 private: 173 static const int32_t kIDLNameSortPositionTable[eCSSProperty_COUNT]; 174 175 public: 176 /** 177 * Returns the position of the specified property in a list of all 178 * properties sorted by their IDL name. 179 */ PropertyIDLNameSortPosition(nsCSSPropertyID aProperty)180 static int32_t PropertyIDLNameSortPosition(nsCSSPropertyID aProperty) { 181 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT, 182 "out of range"); 183 return kIDLNameSortPositionTable[aProperty]; 184 } 185 IsEnabled(nsCSSPropertyID aProperty)186 static bool IsEnabled(nsCSSPropertyID aProperty) { 187 MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_with_aliases, 188 "out of range"); 189 // In the child process, assert that we're not trying to parse stylesheets 190 // before we've gotten all our prefs. 191 MOZ_ASSERT_IF(!XRE_IsParentProcess(), 192 mozilla::Preferences::ArePrefsInitedInContentProcess()); 193 return gPropertyEnabled[aProperty]; 194 } 195 196 public: IsEnabled(nsCSSPropertyID aProperty,EnabledState aEnabled)197 static bool IsEnabled(nsCSSPropertyID aProperty, EnabledState aEnabled) { 198 if (IsEnabled(aProperty)) { 199 return true; 200 } 201 if (aEnabled == EnabledState::IgnoreEnabledState) { 202 return true; 203 } 204 if ((aEnabled & EnabledState::InUASheets) && 205 PropHasFlags(aProperty, Flags::EnabledInUASheets)) { 206 return true; 207 } 208 if ((aEnabled & EnabledState::InChrome) && 209 PropHasFlags(aProperty, Flags::EnabledInChrome)) { 210 return true; 211 } 212 return false; 213 } 214 215 public: 216 struct PropertyPref { 217 nsCSSPropertyID mPropID; 218 const char* mPref; 219 }; 220 static const PropertyPref kPropertyPrefTable[]; 221 222 // Storing the enabledstate_ value in an nsCSSPropertyID variable is a small 223 // hack to avoid needing a separate variable declaration for its real type 224 // (CSSEnabledState), which would then require using a block and 225 // therefore a pair of macros by consumers for the start and end of the loop. 226 #define CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(it_, prop_, enabledstate_) \ 227 for (const nsCSSPropertyID * \ 228 it_ = nsCSSProps::SubpropertyEntryFor(prop_), \ 229 es_ = (nsCSSPropertyID)((enabledstate_) | CSSEnabledState(0)); \ 230 *it_ != eCSSProperty_UNKNOWN; ++it_) \ 231 if (nsCSSProps::IsEnabled(*it_, (mozilla::CSSEnabledState)es_)) 232 }; 233 234 // MOZ_DBG support for nsCSSPropertyID 235 236 inline std::ostream& operator<<(std::ostream& aOut, nsCSSPropertyID aProperty) { 237 return aOut << nsCSSProps::GetStringValue(aProperty); 238 } 239 240 #endif /* nsCSSProps_h___ */ 241