gecko-dev/layout/style/CSSVariableValues.cpp

148 lines
3.6 KiB
C++
Raw Normal View History

/* -*- 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/. */
/* computed CSS Variable values */
#include "CSSVariableValues.h"
Bug 773296 - Part 8: Resolve and compute CSS variables. r=dbaron We add a new class CSSVariableResolver whose job is to take the inherited computed variables and the specified variable declarations and to perform cycle removal and resolution of the variables, storing the result in the CSSVariableValues object on an nsStyleVariables. We use CSSVariableResolver in nsRuleNode::ComputeVariablesData. The variable resolver does this: 1. Asks the CSSVariableValues and CSSVariableDeclarations objects to add their variables to it. 2. Calls in to a new nsCSSParser function EnumerateVariableReferences that informs the resolver which other variables a given variable references, and by doing so, builds a graph of variable dependencies. 3. Removes variables involved in cyclic references using Tarjan's strongly connected component algorithm, setting those variables to have an invalid value. 4. Calls in to a new nsCSSParser function ResolveVariableValue to resolve the remaining valid variables by substituting variable references. We extend nsCSSParser::ParseValueWithVariables to take a callback function to be invoked when encountering a variable reference. This lets EnumerateVariableReferences re-use ParseValueWithVariables. CSSParserImpl::ResolveValueWithVariableReferences needs different error handling behaviour from ParseValueWithVariables, so we don't re-use it. CSSParserImpl::AppendImpliedEOFCharacters is used to take the value returned from nsCSSScanner::GetImpliedEOFCharacters while resolving variable references that were declared using custom properties that encountered EOF before being closed properly. The SeparatorRequiredBetweenTokens helper function in nsCSSParser.cpp implements the serialization rules in CSS Syntax Module Level 3: https://dvcs.w3.org/hg/csswg/raw-file/3479cdefc59a/css-syntax/Overview.html#serialization
2013-12-12 02:09:41 +00:00
#include "CSSVariableResolver.h"
namespace mozilla {
CSSVariableValues::CSSVariableValues()
{
MOZ_COUNT_CTOR(CSSVariableValues);
}
CSSVariableValues::CSSVariableValues(const CSSVariableValues& aOther)
{
MOZ_COUNT_CTOR(CSSVariableValues);
CopyVariablesFrom(aOther);
}
#ifdef DEBUG
CSSVariableValues::~CSSVariableValues()
{
MOZ_COUNT_DTOR(CSSVariableValues);
}
#endif
CSSVariableValues&
CSSVariableValues::operator=(const CSSVariableValues& aOther)
{
if (this == &aOther) {
return *this;
}
mVariableIDs.Clear();
mVariables.Clear();
CopyVariablesFrom(aOther);
return *this;
}
bool
CSSVariableValues::operator==(const CSSVariableValues& aOther) const
{
if (mVariables.Length() != aOther.mVariables.Length()) {
return false;
}
for (size_t thisIndex = 0; thisIndex < mVariables.Length(); ++thisIndex) {
size_t otherIndex;
if (!aOther.mVariableIDs.Get(mVariables[thisIndex].mVariableName,
&otherIndex)) {
return false;
}
const nsString& otherValue = aOther.mVariables[otherIndex].mValue;
if (!mVariables[thisIndex].mValue.Equals(otherValue)) {
return false;
}
}
return true;
}
size_t
CSSVariableValues::Count() const
{
return mVariables.Length();
}
bool
CSSVariableValues::Get(const nsAString& aName, nsString& aValue) const
{
size_t id;
if (!mVariableIDs.Get(aName, &id)) {
return false;
}
aValue = mVariables[id].mValue;
return true;
}
bool
CSSVariableValues::Get(const nsAString& aName,
nsString& aValue,
nsCSSTokenSerializationType& aFirstToken,
nsCSSTokenSerializationType& aLastToken) const
{
size_t id;
if (!mVariableIDs.Get(aName, &id)) {
return false;
}
aValue = mVariables[id].mValue;
aFirstToken = mVariables[id].mFirstToken;
aLastToken = mVariables[id].mLastToken;
return true;
}
void
CSSVariableValues::GetVariableAt(size_t aIndex, nsAString& aName) const
{
aName = mVariables[aIndex].mVariableName;
}
void
CSSVariableValues::Put(const nsAString& aName,
nsString aValue,
nsCSSTokenSerializationType aFirstToken,
nsCSSTokenSerializationType aLastToken)
{
size_t id;
if (mVariableIDs.Get(aName, &id)) {
mVariables[id].mValue = aValue;
mVariables[id].mFirstToken = aFirstToken;
mVariables[id].mLastToken = aLastToken;
} else {
id = mVariables.Length();
mVariableIDs.Put(aName, id);
mVariables.AppendElement(Variable(aName, aValue, aFirstToken, aLastToken));
}
}
void
CSSVariableValues::CopyVariablesFrom(const CSSVariableValues& aOther)
{
for (size_t i = 0, n = aOther.mVariables.Length(); i < n; i++) {
Put(aOther.mVariables[i].mVariableName,
aOther.mVariables[i].mValue,
aOther.mVariables[i].mFirstToken,
aOther.mVariables[i].mLastToken);
}
}
Bug 773296 - Part 8: Resolve and compute CSS variables. r=dbaron We add a new class CSSVariableResolver whose job is to take the inherited computed variables and the specified variable declarations and to perform cycle removal and resolution of the variables, storing the result in the CSSVariableValues object on an nsStyleVariables. We use CSSVariableResolver in nsRuleNode::ComputeVariablesData. The variable resolver does this: 1. Asks the CSSVariableValues and CSSVariableDeclarations objects to add their variables to it. 2. Calls in to a new nsCSSParser function EnumerateVariableReferences that informs the resolver which other variables a given variable references, and by doing so, builds a graph of variable dependencies. 3. Removes variables involved in cyclic references using Tarjan's strongly connected component algorithm, setting those variables to have an invalid value. 4. Calls in to a new nsCSSParser function ResolveVariableValue to resolve the remaining valid variables by substituting variable references. We extend nsCSSParser::ParseValueWithVariables to take a callback function to be invoked when encountering a variable reference. This lets EnumerateVariableReferences re-use ParseValueWithVariables. CSSParserImpl::ResolveValueWithVariableReferences needs different error handling behaviour from ParseValueWithVariables, so we don't re-use it. CSSParserImpl::AppendImpliedEOFCharacters is used to take the value returned from nsCSSScanner::GetImpliedEOFCharacters while resolving variable references that were declared using custom properties that encountered EOF before being closed properly. The SeparatorRequiredBetweenTokens helper function in nsCSSParser.cpp implements the serialization rules in CSS Syntax Module Level 3: https://dvcs.w3.org/hg/csswg/raw-file/3479cdefc59a/css-syntax/Overview.html#serialization
2013-12-12 02:09:41 +00:00
void
CSSVariableValues::AddVariablesToResolver(CSSVariableResolver* aResolver) const
{
for (size_t i = 0, n = mVariables.Length(); i < n; i++) {
aResolver->Put(mVariables[i].mVariableName,
mVariables[i].mValue,
mVariables[i].mFirstToken,
mVariables[i].mLastToken,
true);
}
}
} // namespace mozilla