summaryrefslogtreecommitdiffstats
path: root/layout/style/CSSVariableDeclarations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/CSSVariableDeclarations.cpp')
-rw-r--r--layout/style/CSSVariableDeclarations.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/layout/style/CSSVariableDeclarations.cpp b/layout/style/CSSVariableDeclarations.cpp
new file mode 100644
index 000000000..67bb8d732
--- /dev/null
+++ b/layout/style/CSSVariableDeclarations.cpp
@@ -0,0 +1,195 @@
+/* -*- 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/. */
+
+/* CSS Custom Property assignments for a Declaration at a given priority */
+
+#include "CSSVariableDeclarations.h"
+
+#include "CSSVariableResolver.h"
+#include "nsCSSScanner.h"
+#include "nsRuleData.h"
+
+// These three special string values are used to represent specified values of
+// 'initial', 'inherit' and 'unset'. (Note that none of these are valid
+// variable values.)
+#define INITIAL_VALUE "!"
+#define INHERIT_VALUE ";"
+#define UNSET_VALUE ")"
+
+namespace mozilla {
+
+CSSVariableDeclarations::CSSVariableDeclarations()
+{
+ MOZ_COUNT_CTOR(CSSVariableDeclarations);
+}
+
+CSSVariableDeclarations::CSSVariableDeclarations(const CSSVariableDeclarations& aOther)
+{
+ MOZ_COUNT_CTOR(CSSVariableDeclarations);
+ CopyVariablesFrom(aOther);
+}
+
+#ifdef DEBUG
+CSSVariableDeclarations::~CSSVariableDeclarations()
+{
+ MOZ_COUNT_DTOR(CSSVariableDeclarations);
+}
+#endif
+
+CSSVariableDeclarations&
+CSSVariableDeclarations::operator=(const CSSVariableDeclarations& aOther)
+{
+ if (this == &aOther) {
+ return *this;
+ }
+
+ mVariables.Clear();
+ CopyVariablesFrom(aOther);
+ return *this;
+}
+
+void
+CSSVariableDeclarations::CopyVariablesFrom(const CSSVariableDeclarations& aOther)
+{
+ for (auto iter = aOther.mVariables.ConstIter(); !iter.Done(); iter.Next()) {
+ mVariables.Put(iter.Key(), iter.UserData());
+ }
+}
+
+bool
+CSSVariableDeclarations::Has(const nsAString& aName) const
+{
+ nsString value;
+ return mVariables.Get(aName, &value);
+}
+
+bool
+CSSVariableDeclarations::Get(const nsAString& aName,
+ Type& aType,
+ nsString& aTokenStream) const
+{
+ nsString value;
+ if (!mVariables.Get(aName, &value)) {
+ return false;
+ }
+ if (value.EqualsLiteral(INITIAL_VALUE)) {
+ aType = eInitial;
+ aTokenStream.Truncate();
+ } else if (value.EqualsLiteral(INHERIT_VALUE)) {
+ aType = eInitial;
+ aTokenStream.Truncate();
+ } else if (value.EqualsLiteral(UNSET_VALUE)) {
+ aType = eUnset;
+ aTokenStream.Truncate();
+ } else {
+ aType = eTokenStream;
+ aTokenStream = value;
+ }
+ return true;
+}
+
+void
+CSSVariableDeclarations::PutTokenStream(const nsAString& aName,
+ const nsString& aTokenStream)
+{
+ MOZ_ASSERT(!aTokenStream.EqualsLiteral(INITIAL_VALUE) &&
+ !aTokenStream.EqualsLiteral(INHERIT_VALUE) &&
+ !aTokenStream.EqualsLiteral(UNSET_VALUE));
+ mVariables.Put(aName, aTokenStream);
+}
+
+void
+CSSVariableDeclarations::PutInitial(const nsAString& aName)
+{
+ mVariables.Put(aName, NS_LITERAL_STRING(INITIAL_VALUE));
+}
+
+void
+CSSVariableDeclarations::PutInherit(const nsAString& aName)
+{
+ mVariables.Put(aName, NS_LITERAL_STRING(INHERIT_VALUE));
+}
+
+void
+CSSVariableDeclarations::PutUnset(const nsAString& aName)
+{
+ mVariables.Put(aName, NS_LITERAL_STRING(UNSET_VALUE));
+}
+
+void
+CSSVariableDeclarations::Remove(const nsAString& aName)
+{
+ mVariables.Remove(aName);
+}
+
+void
+CSSVariableDeclarations::MapRuleInfoInto(nsRuleData* aRuleData)
+{
+ if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Variables))) {
+ return;
+ }
+
+ if (!aRuleData->mVariables) {
+ aRuleData->mVariables = new CSSVariableDeclarations(*this);
+ } else {
+ for (auto iter = mVariables.Iter(); !iter.Done(); iter.Next()) {
+ nsDataHashtable<nsStringHashKey, nsString>& variables =
+ aRuleData->mVariables->mVariables;
+ const nsAString& aName = iter.Key();
+ if (!variables.Contains(aName)) {
+ variables.Put(aName, iter.UserData());
+ }
+ }
+ }
+}
+
+void
+CSSVariableDeclarations::AddVariablesToResolver(
+ CSSVariableResolver* aResolver) const
+{
+ for (auto iter = mVariables.ConstIter(); !iter.Done(); iter.Next()) {
+ const nsAString& name = iter.Key();
+ nsString value = iter.UserData();
+ if (value.EqualsLiteral(INITIAL_VALUE)) {
+ // Values of 'initial' are treated the same as an invalid value in the
+ // variable resolver.
+ aResolver->Put(name, EmptyString(),
+ eCSSTokenSerialization_Nothing,
+ eCSSTokenSerialization_Nothing,
+ false);
+ } else if (value.EqualsLiteral(INHERIT_VALUE) ||
+ value.EqualsLiteral(UNSET_VALUE)) {
+ // Values of 'inherit' and 'unset' don't need any handling, since it means
+ // we just need to keep whatever value is currently in the resolver. This
+ // is because the specified variable declarations already have only the
+ // winning declaration for the variable and no longer have any of the
+ // others.
+ } else {
+ // At this point, we don't know what token types are at the start and end
+ // of the specified variable value. These will be determined later during
+ // the resolving process.
+ aResolver->Put(name, value,
+ eCSSTokenSerialization_Nothing,
+ eCSSTokenSerialization_Nothing,
+ false);
+ }
+ }
+}
+
+size_t
+CSSVariableDeclarations::SizeOfIncludingThis(
+ mozilla::MallocSizeOf aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mVariables.ShallowSizeOfExcludingThis(aMallocSizeOf);
+ for (auto iter = mVariables.ConstIter(); !iter.Done(); iter.Next()) {
+ n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+ n += iter.Data().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+ }
+ return n;
+}
+
+} // namespace mozilla