diff options
Diffstat (limited to 'layout/style/nsCSSProps.cpp')
-rw-r--r-- | layout/style/nsCSSProps.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp new file mode 100644 index 0000000000..6413038e36 --- /dev/null +++ b/layout/style/nsCSSProps.cpp @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * methods for dealing with CSS properties and tables of the keyword + * values they accept + */ + +#include "nsCSSProps.h" + +#include "mozilla/ArrayUtils.h" +#include "mozilla/Casting.h" + +#include "gfxPlatform.h" +#include "nsLayoutUtils.h" +#include "nsIWidget.h" +#include "nsStyleConsts.h" // For system widget appearance types + +#include "mozilla/dom/Animation.h" +#include "mozilla/dom/AnimationEffectBinding.h" // for PlaybackDirection +#include "mozilla/gfx/gfxVars.h" // for UseWebRender +#include "mozilla/gfx/gfxVarReceiver.h" +#include "mozilla/LookAndFeel.h" // for system colors + +#include "nsString.h" +#include "nsStaticNameTable.h" + +#include "mozilla/Preferences.h" +#include "mozilla/StaticPrefs_layout.h" + +using namespace mozilla; + +static int32_t gPropertyTableRefCount; +static nsStaticCaseInsensitiveNameTable* gFontDescTable; +static nsStaticCaseInsensitiveNameTable* gCounterDescTable; +static nsDataHashtable<nsCStringHashKey, nsCSSPropertyID>* + gPropertyIDLNameTable; + +static const char* const kCSSRawFontDescs[] = { +#define CSS_FONT_DESC(name_, method_) #name_, +#include "nsCSSFontDescList.h" +#undef CSS_FONT_DESC +}; + +static const char* const kCSSRawCounterDescs[] = { +#define CSS_COUNTER_DESC(name_, method_) #name_, +#include "nsCSSCounterDescList.h" +#undef CSS_COUNTER_DESC +}; + +static nsStaticCaseInsensitiveNameTable* CreateStaticTable( + const char* const aRawTable[], int32_t aLength) { + auto table = new nsStaticCaseInsensitiveNameTable(aRawTable, aLength); +#ifdef DEBUG + // Partially verify the entries. + for (int32_t index = 0; index < aLength; ++index) { + nsAutoCString temp(aRawTable[index]); + MOZ_ASSERT(-1 == temp.FindChar('_'), + "underscore char in case insensitive name table"); + } +#endif + return table; +} + +void nsCSSProps::RecomputeEnabledState(const char* aPref, void*) { + MOZ_RELEASE_ASSERT(NS_IsMainThread()); + DebugOnly<bool> foundPref = false; + for (const PropertyPref* pref = kPropertyPrefTable; + pref->mPropID != eCSSProperty_UNKNOWN; pref++) { + if (!aPref || !strcmp(aPref, pref->mPref)) { + foundPref = true; +#ifdef FUZZING + gPropertyEnabled[pref->mPropID] = true; +#else + gPropertyEnabled[pref->mPropID] = Preferences::GetBool(pref->mPref); +#endif + if (pref->mPropID == eCSSProperty_backdrop_filter) { + gPropertyEnabled[pref->mPropID] &= + gfx::gfxVars::GetUseWebRenderOrDefault(); + } + } + } + MOZ_ASSERT(foundPref); +} + +void nsCSSProps::AddRefTable(void) { + if (0 == gPropertyTableRefCount++) { + MOZ_ASSERT(!gFontDescTable, "pre existing array!"); + MOZ_ASSERT(!gCounterDescTable, "pre existing array!"); + MOZ_ASSERT(!gPropertyIDLNameTable, "pre existing array!"); + + gFontDescTable = CreateStaticTable(kCSSRawFontDescs, eCSSFontDesc_COUNT); + gCounterDescTable = + CreateStaticTable(kCSSRawCounterDescs, eCSSCounterDesc_COUNT); + + gPropertyIDLNameTable = + new nsDataHashtable<nsCStringHashKey, nsCSSPropertyID>; + for (nsCSSPropertyID p = nsCSSPropertyID(0); + size_t(p) < ArrayLength(kIDLNameTable); p = nsCSSPropertyID(p + 1)) { + if (kIDLNameTable[p]) { + gPropertyIDLNameTable->Put(nsDependentCString(kIDLNameTable[p]), p); + } + } + + static bool prefObserversInited = false; + if (!prefObserversInited) { + prefObserversInited = true; + for (const PropertyPref* pref = kPropertyPrefTable; + pref->mPropID != eCSSProperty_UNKNOWN; pref++) { + // https://bugzilla.mozilla.org/show_bug.cgi?id=1472523 + // We need to use nsCString instead of substring because the preference + // callback code stores them. Using AssignLiteral prevents any + // unnecessary allocations. + nsCString prefName; + prefName.AssignLiteral(pref->mPref, strlen(pref->mPref)); + Preferences::RegisterCallback(nsCSSProps::RecomputeEnabledState, + prefName); + } + RecomputeEnabledState(/* aPrefName = */ nullptr); + } + } +} + +void nsCSSProps::ReleaseTable(void) { + if (0 == --gPropertyTableRefCount) { + delete gFontDescTable; + gFontDescTable = nullptr; + + delete gCounterDescTable; + gCounterDescTable = nullptr; + + delete gPropertyIDLNameTable; + gPropertyIDLNameTable = nullptr; + } +} + +/* static */ +bool nsCSSProps::IsCustomPropertyName(const nsACString& aProperty) { + return aProperty.Length() >= CSS_CUSTOM_NAME_PREFIX_LENGTH && + StringBeginsWith(aProperty, "--"_ns); +} + +nsCSSPropertyID nsCSSProps::LookupPropertyByIDLName( + const nsACString& aPropertyIDLName, EnabledState aEnabled) { + MOZ_ASSERT(gPropertyIDLNameTable, "no lookup table, needs addref"); + nsCSSPropertyID res; + if (!gPropertyIDLNameTable->Get(aPropertyIDLName, &res)) { + return eCSSProperty_UNKNOWN; + } + MOZ_ASSERT(res < eCSSProperty_COUNT); + if (!IsEnabled(res, aEnabled)) { + return eCSSProperty_UNKNOWN; + } + return res; +} + +nsCSSFontDesc nsCSSProps::LookupFontDesc(const nsACString& aFontDesc) { + MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref"); + nsCSSFontDesc which = nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc)); + + if (which == eCSSFontDesc_Display && + !StaticPrefs::layout_css_font_display_enabled()) { + which = eCSSFontDesc_UNKNOWN; + } + return which; +} + +const nsCString& nsCSSProps::GetStringValue(nsCSSFontDesc aFontDescID) { + MOZ_ASSERT(gFontDescTable, "no lookup table, needs addref"); + if (gFontDescTable) { + return gFontDescTable->GetStringValue(int32_t(aFontDescID)); + } else { + static nsDependentCString sNullStr(""); + return sNullStr; + } +} + +const nsCString& nsCSSProps::GetStringValue(nsCSSCounterDesc aCounterDesc) { + MOZ_ASSERT(gCounterDescTable, "no lookup table, needs addref"); + if (gCounterDescTable) { + return gCounterDescTable->GetStringValue(int32_t(aCounterDesc)); + } else { + static nsDependentCString sNullStr(""); + return sNullStr; + } +} +const CSSPropFlags nsCSSProps::kFlagsTable[eCSSProperty_COUNT] = { +#define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) flags_, +#define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) flags_, +#include "mozilla/ServoCSSPropList.h" +#undef CSS_PROP_SHORTHAND +#undef CSS_PROP_LONGHAND +}; + +/* static */ +bool nsCSSProps::gPropertyEnabled[eCSSProperty_COUNT_with_aliases] = { +// If the property has any "ENABLED_IN" flag set, it is disabled by +// default. Note that, if a property has pref, whatever its default +// value is, it will later be changed in nsCSSProps::AddRefTable(). +// If the property has "ENABLED_IN" flags but doesn't have a pref, +// it is an internal property which is disabled elsewhere. +#define IS_ENABLED_BY_DEFAULT(flags_) \ + (!((flags_) & (CSSPropFlags::EnabledMask | CSSPropFlags::Inaccessible))) + +#define CSS_PROP_LONGHAND(name_, id_, method_, flags_, ...) \ + IS_ENABLED_BY_DEFAULT(flags_), +#define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, ...) \ + IS_ENABLED_BY_DEFAULT(flags_), +#define CSS_PROP_ALIAS(...) true, +#include "mozilla/ServoCSSPropList.h" +#undef CSS_PROP_ALIAS +#undef CSS_PROP_SHORTHAND +#undef CSS_PROP_LONGHAND + +#undef IS_ENABLED_BY_DEFAULT +}; + +/** + * A singleton class to register as a receiver for gfxVars. + * Updates the state of backdrop-filter's pref if the gfx + * WebRender var changes state. + */ +class nsCSSPropsGfxVarReceiver final : public gfx::gfxVarReceiver { + constexpr nsCSSPropsGfxVarReceiver() = default; + + // WebRender's last known enabled state. + static bool sLastKnownUseWebRender; + static nsCSSPropsGfxVarReceiver sInstance; + + public: + static gfx::gfxVarReceiver& GetInstance() { return sInstance; } + + void OnVarChanged(const gfx::GfxVarUpdate&) override { + bool enabled = gfxVars::UseWebRender(); + if (sLastKnownUseWebRender != enabled) { + sLastKnownUseWebRender = enabled; + nsCSSProps::RecomputeEnabledState("layout.css.backdrop-filter.enabled"); + } + } +}; + +/* static */ +nsCSSPropsGfxVarReceiver nsCSSPropsGfxVarReceiver::sInstance = + nsCSSPropsGfxVarReceiver(); + +/* static */ +bool nsCSSPropsGfxVarReceiver::sLastKnownUseWebRender = false; + +/* static */ +gfx::gfxVarReceiver& nsCSSProps::GfxVarReceiver() { + return nsCSSPropsGfxVarReceiver::GetInstance(); +} + +#include "nsCSSPropsGenerated.inc" |