Bug 1550804 - Add color scheme simulation to the inspector. r=pbro
[gecko.git] / layout / style / nsCSSProps.cpp
blob2412ccef10da71f214a2fe7b178c201019bb725c
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/. */
7 /*
8 * methods for dealing with CSS properties and tables of the keyword
9 * values they accept
12 #include "nsCSSProps.h"
14 #include "mozilla/ArrayUtils.h"
15 #include "mozilla/Casting.h"
17 #include "nsCSSKeywords.h"
18 #include "nsLayoutUtils.h"
19 #include "nsIWidget.h"
20 #include "nsStyleConsts.h" // For system widget appearance types
22 #include "mozilla/dom/Animation.h"
23 #include "mozilla/dom/AnimationEffectBinding.h" // for PlaybackDirection
24 #include "mozilla/LookAndFeel.h" // for system colors
26 #include "nsString.h"
27 #include "nsStaticNameTable.h"
29 #include "mozilla/Preferences.h"
30 #include "mozilla/StaticPrefs_layout.h"
32 using namespace mozilla;
34 typedef nsCSSProps::KTableEntry KTableEntry;
36 static int32_t gPropertyTableRefCount;
37 static nsStaticCaseInsensitiveNameTable* gFontDescTable;
38 static nsStaticCaseInsensitiveNameTable* gCounterDescTable;
39 static nsDataHashtable<nsCStringHashKey, nsCSSPropertyID>*
40 gPropertyIDLNameTable;
42 static const char* const kCSSRawFontDescs[] = {
43 #define CSS_FONT_DESC(name_, method_) #name_,
44 #include "nsCSSFontDescList.h"
45 #undef CSS_FONT_DESC
48 static const char* const kCSSRawCounterDescs[] = {
49 #define CSS_COUNTER_DESC(name_, method_) #name_,
50 #include "nsCSSCounterDescList.h"
51 #undef CSS_COUNTER_DESC
54 static nsStaticCaseInsensitiveNameTable* CreateStaticTable(
55 const char* const aRawTable[], int32_t aLength) {
56 auto table = new nsStaticCaseInsensitiveNameTable(aRawTable, aLength);
57 #ifdef DEBUG
58 // Partially verify the entries.
59 for (int32_t index = 0; index < aLength; ++index) {
60 nsAutoCString temp(aRawTable[index]);
61 MOZ_ASSERT(-1 == temp.FindChar('_'),
62 "underscore char in case insensitive name table");
64 #endif
65 return table;
68 void nsCSSProps::AddRefTable(void) {
69 if (0 == gPropertyTableRefCount++) {
70 MOZ_ASSERT(!gFontDescTable, "pre existing array!");
71 MOZ_ASSERT(!gCounterDescTable, "pre existing array!");
72 MOZ_ASSERT(!gPropertyIDLNameTable, "pre existing array!");
74 gFontDescTable = CreateStaticTable(kCSSRawFontDescs, eCSSFontDesc_COUNT);
75 gCounterDescTable =
76 CreateStaticTable(kCSSRawCounterDescs, eCSSCounterDesc_COUNT);
78 gPropertyIDLNameTable =
79 new nsDataHashtable<nsCStringHashKey, nsCSSPropertyID>;
80 for (nsCSSPropertyID p = nsCSSPropertyID(0);
81 size_t(p) < ArrayLength(kIDLNameTable); p = nsCSSPropertyID(p + 1)) {
82 if (kIDLNameTable[p]) {
83 gPropertyIDLNameTable->Put(nsDependentCString(kIDLNameTable[p]), p);
87 static bool prefObserversInited = false;
88 if (!prefObserversInited) {
89 prefObserversInited = true;
90 for (const PropertyPref* pref = kPropertyPrefTable;
91 pref->mPropID != eCSSProperty_UNKNOWN; pref++) {
92 nsCString prefName;
93 prefName.AssignLiteral(pref->mPref, strlen(pref->mPref));
94 bool* enabled = &gPropertyEnabled[pref->mPropID];
95 Preferences::AddBoolVarCache(enabled, prefName);
101 #undef DEBUG_SHORTHANDS_CONTAINING
103 void nsCSSProps::ReleaseTable(void) {
104 if (0 == --gPropertyTableRefCount) {
105 delete gFontDescTable;
106 gFontDescTable = nullptr;
108 delete gCounterDescTable;
109 gCounterDescTable = nullptr;
111 delete gPropertyIDLNameTable;
112 gPropertyIDLNameTable = nullptr;
116 /* static */
117 bool nsCSSProps::IsCustomPropertyName(const nsAString& aProperty) {
118 return aProperty.Length() >= CSS_CUSTOM_NAME_PREFIX_LENGTH &&
119 StringBeginsWith(aProperty, NS_LITERAL_STRING("--"));
122 nsCSSPropertyID nsCSSProps::LookupPropertyByIDLName(
123 const nsACString& aPropertyIDLName, EnabledState aEnabled) {
124 nsCSSPropertyID res;
125 if (!gPropertyIDLNameTable->Get(aPropertyIDLName, &res)) {
126 return eCSSProperty_UNKNOWN;
128 MOZ_ASSERT(res < eCSSProperty_COUNT);
129 if (!IsEnabled(res, aEnabled)) {
130 return eCSSProperty_UNKNOWN;
132 return res;
135 nsCSSPropertyID nsCSSProps::LookupPropertyByIDLName(
136 const nsAString& aPropertyIDLName, EnabledState aEnabled) {
137 MOZ_ASSERT(gPropertyIDLNameTable, "no lookup table, needs addref");
138 return LookupPropertyByIDLName(NS_ConvertUTF16toUTF8(aPropertyIDLName),
139 aEnabled);
142 nsCSSFontDesc nsCSSProps::LookupFontDesc(const nsAString& aFontDesc) {
143 MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref");
144 nsCSSFontDesc which = nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc));
146 if (which == eCSSFontDesc_Display &&
147 !StaticPrefs::layout_css_font_display_enabled()) {
148 which = eCSSFontDesc_UNKNOWN;
150 return which;
153 const nsCString& nsCSSProps::GetStringValue(nsCSSFontDesc aFontDescID) {
154 MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref");
155 if (gFontDescTable) {
156 return gFontDescTable->GetStringValue(int32_t(aFontDescID));
157 } else {
158 static nsDependentCString sNullStr("");
159 return sNullStr;
163 const nsCString& nsCSSProps::GetStringValue(nsCSSCounterDesc aCounterDesc) {
164 MOZ_ASSERT(gCounterDescTable, "no lookup table, needs addref");
165 if (gCounterDescTable) {
166 return gCounterDescTable->GetStringValue(int32_t(aCounterDesc));
167 } else {
168 static nsDependentCString sNullStr("");
169 return sNullStr;
173 /***************************************************************************/
175 const KTableEntry nsCSSProps::kCursorKTable[] = {
176 // CSS 2.0
177 {eCSSKeyword_auto, StyleCursorKind::Auto},
178 {eCSSKeyword_crosshair, StyleCursorKind::Crosshair},
179 {eCSSKeyword_default, StyleCursorKind::Default},
180 {eCSSKeyword_pointer, StyleCursorKind::Pointer},
181 {eCSSKeyword_move, StyleCursorKind::Move},
182 {eCSSKeyword_e_resize, StyleCursorKind::EResize},
183 {eCSSKeyword_ne_resize, StyleCursorKind::NeResize},
184 {eCSSKeyword_nw_resize, StyleCursorKind::NwResize},
185 {eCSSKeyword_n_resize, StyleCursorKind::NResize},
186 {eCSSKeyword_se_resize, StyleCursorKind::SeResize},
187 {eCSSKeyword_sw_resize, StyleCursorKind::SwResize},
188 {eCSSKeyword_s_resize, StyleCursorKind::SResize},
189 {eCSSKeyword_w_resize, StyleCursorKind::WResize},
190 {eCSSKeyword_text, StyleCursorKind::Text},
191 {eCSSKeyword_wait, StyleCursorKind::Wait},
192 {eCSSKeyword_help, StyleCursorKind::Help},
193 // CSS 2.1
194 {eCSSKeyword_progress, StyleCursorKind::Progress},
195 // CSS3 basic user interface module
196 {eCSSKeyword_copy, StyleCursorKind::Copy},
197 {eCSSKeyword_alias, StyleCursorKind::Alias},
198 {eCSSKeyword_context_menu, StyleCursorKind::ContextMenu},
199 {eCSSKeyword_cell, StyleCursorKind::Cell},
200 {eCSSKeyword_not_allowed, StyleCursorKind::NotAllowed},
201 {eCSSKeyword_col_resize, StyleCursorKind::ColResize},
202 {eCSSKeyword_row_resize, StyleCursorKind::RowResize},
203 {eCSSKeyword_no_drop, StyleCursorKind::NoDrop},
204 {eCSSKeyword_vertical_text, StyleCursorKind::VerticalText},
205 {eCSSKeyword_all_scroll, StyleCursorKind::AllScroll},
206 {eCSSKeyword_nesw_resize, StyleCursorKind::NeswResize},
207 {eCSSKeyword_nwse_resize, StyleCursorKind::NwseResize},
208 {eCSSKeyword_ns_resize, StyleCursorKind::NsResize},
209 {eCSSKeyword_ew_resize, StyleCursorKind::EwResize},
210 {eCSSKeyword_none, StyleCursorKind::None},
211 {eCSSKeyword_grab, StyleCursorKind::Grab},
212 {eCSSKeyword_grabbing, StyleCursorKind::Grabbing},
213 {eCSSKeyword_zoom_in, StyleCursorKind::ZoomIn},
214 {eCSSKeyword_zoom_out, StyleCursorKind::ZoomOut},
215 // -moz- prefixed vendor specific
216 {eCSSKeyword__moz_grab, StyleCursorKind::Grab},
217 {eCSSKeyword__moz_grabbing, StyleCursorKind::Grabbing},
218 {eCSSKeyword__moz_zoom_in, StyleCursorKind::ZoomIn},
219 {eCSSKeyword__moz_zoom_out, StyleCursorKind::ZoomOut},
220 {eCSSKeyword_UNKNOWN, nsCSSKTableEntry::SENTINEL_VALUE}};
222 const KTableEntry nsCSSProps::kFontSmoothingKTable[] = {
223 {eCSSKeyword_auto, NS_FONT_SMOOTHING_AUTO},
224 {eCSSKeyword_grayscale, NS_FONT_SMOOTHING_GRAYSCALE},
225 {eCSSKeyword_UNKNOWN, nsCSSKTableEntry::SENTINEL_VALUE}};
227 const KTableEntry nsCSSProps::kTextAlignKTable[] = {
228 {eCSSKeyword_left, NS_STYLE_TEXT_ALIGN_LEFT},
229 {eCSSKeyword_right, NS_STYLE_TEXT_ALIGN_RIGHT},
230 {eCSSKeyword_center, NS_STYLE_TEXT_ALIGN_CENTER},
231 {eCSSKeyword_justify, NS_STYLE_TEXT_ALIGN_JUSTIFY},
232 {eCSSKeyword__moz_center, NS_STYLE_TEXT_ALIGN_MOZ_CENTER},
233 {eCSSKeyword__moz_right, NS_STYLE_TEXT_ALIGN_MOZ_RIGHT},
234 {eCSSKeyword__moz_left, NS_STYLE_TEXT_ALIGN_MOZ_LEFT},
235 {eCSSKeyword_start, NS_STYLE_TEXT_ALIGN_START},
236 {eCSSKeyword_end, NS_STYLE_TEXT_ALIGN_END},
237 {eCSSKeyword_UNKNOWN, nsCSSKTableEntry::SENTINEL_VALUE}};
239 const KTableEntry nsCSSProps::kTextDecorationStyleKTable[] = {
240 {eCSSKeyword__moz_none, NS_STYLE_TEXT_DECORATION_STYLE_NONE},
241 {eCSSKeyword_solid, NS_STYLE_TEXT_DECORATION_STYLE_SOLID},
242 {eCSSKeyword_double, NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE},
243 {eCSSKeyword_dotted, NS_STYLE_TEXT_DECORATION_STYLE_DOTTED},
244 {eCSSKeyword_dashed, NS_STYLE_TEXT_DECORATION_STYLE_DASHED},
245 {eCSSKeyword_wavy, NS_STYLE_TEXT_DECORATION_STYLE_WAVY},
246 {eCSSKeyword_UNKNOWN, nsCSSKTableEntry::SENTINEL_VALUE}};
248 int32_t nsCSSProps::FindIndexOfKeyword(nsCSSKeyword aKeyword,
249 const KTableEntry aTable[]) {
250 if (eCSSKeyword_UNKNOWN == aKeyword) {
251 // NOTE: we can have keyword tables where eCSSKeyword_UNKNOWN is used
252 // not only for the sentinel, but also in the middle of the table to
253 // knock out values that have been disabled by prefs, e.g. kDisplayKTable.
254 // So we deal with eCSSKeyword_UNKNOWN up front to avoid returning a valid
255 // index in the loop below.
256 return -1;
258 for (int32_t i = 0;; ++i) {
259 const KTableEntry& entry = aTable[i];
260 if (entry.IsSentinel()) {
261 break;
263 if (aKeyword == entry.mKeyword) {
264 return i;
267 return -1;
270 bool nsCSSProps::FindKeyword(nsCSSKeyword aKeyword, const KTableEntry aTable[],
271 int32_t& aResult) {
272 int32_t index = FindIndexOfKeyword(aKeyword, aTable);
273 if (index >= 0) {
274 aResult = aTable[index].mValue;
275 return true;
277 return false;
280 nsCSSKeyword nsCSSProps::ValueToKeywordEnum(int32_t aValue,
281 const KTableEntry aTable[]) {
282 #ifdef DEBUG
283 typedef decltype(aTable[0].mValue) table_value_type;
284 NS_ASSERTION(table_value_type(aValue) == aValue, "Value out of range");
285 #endif
286 for (int32_t i = 0;; ++i) {
287 const KTableEntry& entry = aTable[i];
288 if (entry.IsSentinel()) {
289 break;
291 if (aValue == entry.mValue) {
292 return entry.mKeyword;
295 return eCSSKeyword_UNKNOWN;
298 const nsCString& nsCSSProps::ValueToKeyword(int32_t aValue,
299 const KTableEntry aTable[]) {
300 nsCSSKeyword keyword = ValueToKeywordEnum(aValue, aTable);
301 if (keyword == eCSSKeyword_UNKNOWN) {
302 static nsDependentCString sNullStr("");
303 return sNullStr;
304 } else {
305 return nsCSSKeywords::GetStringValue(keyword);
309 const CSSPropFlags nsCSSProps::kFlagsTable[eCSSProperty_COUNT] = {
310 #define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) flags_,
311 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) flags_,
312 #include "mozilla/ServoCSSPropList.h"
313 #undef CSS_PROP_SHORTHAND
314 #undef CSS_PROP_LONGHAND
317 /* static */
318 bool nsCSSProps::gPropertyEnabled[eCSSProperty_COUNT_with_aliases] = {
319 // If the property has any "ENABLED_IN" flag set, it is disabled by
320 // default. Note that, if a property has pref, whatever its default
321 // value is, it will later be changed in nsCSSProps::AddRefTable().
322 // If the property has "ENABLED_IN" flags but doesn't have a pref,
323 // it is an internal property which is disabled elsewhere.
324 #define IS_ENABLED_BY_DEFAULT(flags_) \
325 (!((flags_) & (CSSPropFlags::EnabledMask | CSSPropFlags::Inaccessible)))
327 #define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) \
328 IS_ENABLED_BY_DEFAULT(flags_),
329 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) \
330 IS_ENABLED_BY_DEFAULT(flags_),
331 #define CSS_PROP_ALIAS(...) true,
332 #include "mozilla/ServoCSSPropList.h"
333 #undef CSS_PROP_ALIAS
334 #undef CSS_PROP_SHORTHAND
335 #undef CSS_PROP_LONGHAND
337 #undef IS_ENABLED_BY_DEFAULT
340 #include "nsCSSPropsGenerated.inc"