Bug 1273706 - Part 6: Add CSSProperty type for custom properties. r?heycam
Add CSSProperty type to replace nsCSSPropertyID in places where we might
want to represent custom properties. In particular, a later patch in this
series will modify the animation code to use these where appropriate.
A CSSProperty is a tagged union containing a nsCSSPropertyID or holding a
reference to an nsIAtom corresponding to the custom property name, sans the
leading --.
MozReview-Commit-ID: 3bEXG3qCxHt
new file mode 100644
--- /dev/null
+++ b/layout/style/CSSProperty.h
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/* type for representing CSS properties (custom or 'fixed'/standard) */
+
+#ifndef mozilla_CSSProperty_h
+#define mozilla_CSSProperty_h
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Move.h"
+#include "mozilla/RefPtr.h"
+#include "nsCSSPropertyID.h"
+#include "nsCSSProps.h"
+#include "nsIAtom.h"
+#include "nsStyleStructFwd.h"
+
+namespace mozilla {
+
+/**
+ * A CSSProperty represents either a registered custom property or a standard
+ * CSS property. IsFixed() and AsFixed() check for and retrieve standard CSS
+ * properties, and IsCustom() and AsCustom() do the same for custom properties.
+ * Custom properties are encoded as atoms containing their names without the
+ * leading '--', while standard properties are represented by nsCSSProperty.
+ */
+class CSSProperty
+{
+private:
+ enum State : uint8_t {
+ Invalid,
+ Fixed,
+ Custom,
+ };
+
+public:
+ CSSProperty()
+ : mState(State::Invalid)
+ {
+ }
+
+ explicit CSSProperty(nsCSSPropertyID aProperty)
+ : mState(State::Fixed)
+ , mFixed(aProperty)
+ {
+ }
+
+ explicit CSSProperty(nsIAtom* aProperty)
+ : mState(State::Custom)
+ , mCustom(aProperty)
+ {
+ mCustom->AddRef();
+ }
+
+ explicit CSSProperty(already_AddRefed<nsIAtom> aProperty)
+ : mState(State::Custom)
+ , mCustom(aProperty.take())
+ {
+ }
+
+ CSSProperty(const CSSProperty& aOther)
+ : mState(aOther.mState)
+ {
+ if (mState == State::Custom) {
+ mCustom = aOther.mCustom;
+ mCustom->AddRef();
+ } else {
+ mFixed = aOther.mFixed;
+ }
+ }
+
+ CSSProperty(CSSProperty&& aOther)
+ : mState(State::Invalid)
+ {
+ *this = aOther;
+ }
+
+ CSSProperty& operator=(const CSSProperty& aOther)
+ {
+ CSSProperty copy(aOther);
+ *this = Move(copy);
+ return *this;
+ }
+
+ CSSProperty& operator=(CSSProperty&& aOther)
+ {
+ if (mState == State::Custom) {
+ mCustom->Release();
+ }
+ mState = aOther.mState;
+ if (mState == State::Custom) {
+ mCustom = aOther.mCustom;
+ // Don't want double-frees.
+ aOther.mCustom = nullptr;
+ aOther.mState = State::Invalid;
+ } else {
+ mFixed = aOther.mFixed;
+ }
+ return *this;
+ }
+
+ bool operator==(const CSSProperty& aOther) const
+ {
+ MOZ_ASSERT(mState != State::Invalid &&
+ aOther.mState != State::Invalid);
+ if (mState == State::Custom) {
+ return aOther.mState == State::Custom &&
+ mCustom == aOther.mCustom;
+ } else {
+ return mFixed == aOther.mFixed;
+ }
+ }
+
+ bool operator!=(const CSSProperty& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ bool operator==(const nsCSSPropertyID& aOther) const
+ {
+ MOZ_ASSERT(mState != State::Invalid);
+ return mState == State::Fixed &&
+ mFixed == aOther;
+ }
+
+ bool operator!=(const nsCSSPropertyID& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ bool operator==(nsIAtom* aOther) const
+ {
+ MOZ_ASSERT(mState != State::Invalid);
+ return mState == State::Custom &&
+ mCustom == aOther;
+ }
+
+ bool operator!=(nsIAtom* aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ ~CSSProperty()
+ {
+ if (mState == State::Custom) {
+ mCustom->Release();
+ }
+ }
+
+ bool IsFixed() const
+ {
+ MOZ_ASSERT(mState != State::Invalid);
+ return mState == State::Fixed;
+ }
+
+ bool IsCustom() const
+ {
+ MOZ_ASSERT(mState != State::Invalid);
+ return mState == State::Custom;
+ }
+
+ nsCSSPropertyID AsFixed() const
+ {
+ MOZ_ASSERT(mState == State::Fixed);
+ return mFixed;
+ }
+
+ nsIAtom* AsCustom() const
+ {
+ MOZ_ASSERT(mState == State::Custom);
+ return mCustom;
+ }
+
+ /**
+ * GetStyleStructID returns the nsStyleStructID corresponding to this
+ * property. Custom properties always have style struct ID
+ * eStyleStruct_Variables.
+ */
+ nsStyleStructID GetStyleStructID() const
+ {
+ switch (mState) {
+ case State::Invalid:
+ MOZ_ASSERT(false);
+ break;
+ case State::Fixed:
+ return nsCSSProps::kSIDTable[mFixed];
+ case State::Custom:
+ return eStyleStruct_Variables;
+ }
+ return nsStyleStructID_None;
+ }
+
+ /**
+ * ToString converts this property into its CSS property name.
+ * Custom properties have '--' prefixed.
+ */
+ void ToString(nsAString& aString) const
+ {
+ aString.Truncate(0);
+ switch (mState) {
+ case State::Invalid:
+ MOZ_ASSERT(false);
+ break;
+ case State::Fixed:
+ aString = NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(mFixed));
+ break;
+ case State::Custom:
+ nsAutoString name;
+ mCustom->ToString(name);
+ aString.AppendLiteral("--");
+ aString.Append(name);
+ break;
+ }
+ }
+
+ /**
+ * IsShorthand returns true iff this represents a fixed shorthand property.
+ * Custom properties are never shorthands.
+ */
+ bool IsShorthand() const
+ {
+ MOZ_ASSERT(mState != State::Invalid);
+ if (mState == State::Custom) {
+ return false;
+ }
+ return nsCSSProps::IsShorthand(mFixed);
+ }
+
+ /**
+ * IsCustomLessThan returns true iff this and aOther are custom properties
+ * and the custom property name for this property is less than (according to
+ * nsString::operator<) aOther's custom property name. It is an error to call
+ * IsCustomLessThan if this or aOther do not represent custom properties.
+ */
+ bool IsCustomLessThan(const CSSProperty& aOther) const
+ {
+ MOZ_ASSERT(mState == State::Custom &&
+ aOther.mState == State::Custom);
+ nsString left;
+ nsString right;
+ mCustom->ToString(left);
+ aOther.mCustom->ToString(right);
+ return left < right;
+ }
+
+private:
+ State mState;
+ union {
+ nsCSSPropertyID mFixed;
+ nsIAtom* mCustom;
+ };
+};
+
+} // namespace mozilla
+
+#endif // mozilla_CSSProperty_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -77,16 +77,17 @@ EXPORTS += [
'nsStyleStructInlines.h',
'nsStyleTransformMatrix.h',
'nsStyleUtil.h',
]
EXPORTS.mozilla += [
'AnimationCollection.h',
'CSSEnabledState.h',
+ 'CSSProperty.h',
'CSSStyleSheet.h',
'CSSVariableDeclarations.h',
'CSSVariableResolver.h',
'CSSVariableValues.h',
'HandleRefPtr.h',
'IncrementalClearCOMRuleArray.h',
'LayerAnimationInfo.h',
'RuleNodeCacheConditions.h',