/* -*- 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/. */ /* CSS Custom Property assignments for a Declaration at a given priority */ #include "CSSVariableDeclarations.h" #include "CSSVariableResolver.h" #include "nsCSSScanner.h" #include "nsRuleData.h" // These two special string values are used to represent specified values of // 'initial' and 'inherit'. (Note that neither is a valid variable value.) #define INITIAL_VALUE "!" #define INHERIT_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; } /* static */ PLDHashOperator CSSVariableDeclarations::EnumerateVariableForCopy(const nsAString& aName, nsString aValue, void* aData) { CSSVariableDeclarations* variables = static_cast(aData); variables->mVariables.Put(aName, aValue); return PL_DHASH_NEXT; } void CSSVariableDeclarations::CopyVariablesFrom(const CSSVariableDeclarations& aOther) { aOther.mVariables.EnumerateRead(EnumerateVariableForCopy, this); } 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 { 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)); 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::Remove(const nsAString& aName) { mVariables.Remove(aName); } /* static */ PLDHashOperator CSSVariableDeclarations::EnumerateVariableForMapRuleInfoInto( const nsAString& aName, nsString aValue, void* aData) { nsDataHashtable* variables = static_cast*>(aData); if (!variables->Contains(aName)) { variables->Put(aName, aValue); } return PL_DHASH_NEXT; } void CSSVariableDeclarations::MapRuleInfoInto(nsRuleData* aRuleData) { if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Variables))) { return; } if (!aRuleData->mVariables) { aRuleData->mVariables = new CSSVariableDeclarations(*this); } else { mVariables.EnumerateRead(EnumerateVariableForMapRuleInfoInto, aRuleData->mVariables.get()); } } /* static */ PLDHashOperator CSSVariableDeclarations::EnumerateVariableForAddVariablesToResolver( const nsAString& aName, nsString aValue, void* aData) { CSSVariableResolver* resolver = static_cast(aData); if (aValue.EqualsLiteral(INITIAL_VALUE)) { // Values of 'initial' are treated the same as an invalid value in the // variable resolver. resolver->Put(aName, EmptyString(), eCSSTokenSerialization_Nothing, eCSSTokenSerialization_Nothing, false); } else if (aValue.EqualsLiteral(INHERIT_VALUE)) { // Values of 'inherit' 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. resolver->Put(aName, aValue, eCSSTokenSerialization_Nothing, eCSSTokenSerialization_Nothing, false); } return PL_DHASH_NEXT; } void CSSVariableDeclarations::AddVariablesToResolver( CSSVariableResolver* aResolver) const { mVariables.EnumerateRead(EnumerateVariableForAddVariablesToResolver, aResolver); } static size_t SizeOfTableEntry(const nsAString& aKey, const nsString& aValue, MallocSizeOf aMallocSizeOf, void* aUserArg) { size_t n = 0; n += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); n += aValue.SizeOfExcludingThisIfUnshared(aMallocSizeOf); return n; } size_t CSSVariableDeclarations::SizeOfIncludingThis( mozilla::MallocSizeOf aMallocSizeOf) const { size_t n = aMallocSizeOf(this); n += mVariables.SizeOfExcludingThis(SizeOfTableEntry, aMallocSizeOf); return n; } } // namespace mozilla