mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1448763 part 8 - Remove CSSCalc.h. r=emilio
MozReview-Commit-ID: eecZRhdxH8 --HG-- extra : rebase_source : a25a8d4de1916a92ff736303848daf259a9b265c
This commit is contained in:
parent
3248eb765c
commit
8c5331160e
@ -1,436 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef CSSCalc_h_
|
||||
#define CSSCalc_h_
|
||||
|
||||
#include "nsCSSValue.h"
|
||||
#include "nsStyleCoord.h"
|
||||
#include <math.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace css {
|
||||
|
||||
/**
|
||||
* ComputeCalc computes the result of a calc() expression tree.
|
||||
*
|
||||
* It is templatized over a CalcOps class that is expected to provide:
|
||||
*
|
||||
* // input_type and input_array_type have a bunch of very specific
|
||||
* // expectations (which happen to be met by two classes (nsCSSValue
|
||||
* // and nsStyleCoord). There must be methods (roughly):
|
||||
* // input_array_type* input_type::GetArrayValue();
|
||||
* // uint32_t input_array_type::Count() const;
|
||||
* // input_type& input_array_type::Item(uint32_t);
|
||||
* typedef ... input_type;
|
||||
* typedef ... input_array_type;
|
||||
*
|
||||
* typedef ... coeff_type;
|
||||
*
|
||||
* typedef ... result_type;
|
||||
*
|
||||
* // GetUnit(avalue) must return the correct nsCSSUnit for any
|
||||
* // value that represents a calc tree node (eCSSUnit_Calc*). For
|
||||
* // other nodes, it may return any non eCSSUnit_Calc* unit.
|
||||
* static nsCSSUnit GetUnit(const input_type& aValue);
|
||||
*
|
||||
* result_type
|
||||
* MergeAdditive(nsCSSUnit aCalcFunction,
|
||||
* result_type aValue1, result_type aValue2);
|
||||
*
|
||||
* result_type
|
||||
* MergeMultiplicativeL(nsCSSUnit aCalcFunction,
|
||||
* coeff_type aValue1, result_type aValue2);
|
||||
*
|
||||
* result_type
|
||||
* MergeMultiplicativeR(nsCSSUnit aCalcFunction,
|
||||
* result_type aValue1, coeff_type aValue2);
|
||||
*
|
||||
* bool
|
||||
* ComputeLeafValue(result_type& aResult, const input_type& aValue);
|
||||
*
|
||||
* coeff_type
|
||||
* ComputeCoefficient(const coeff_type& aValue);
|
||||
*
|
||||
* The CalcOps methods might compute the calc() expression down to a
|
||||
* number, reduce some parts of it to a number but replicate other
|
||||
* parts, or produce a tree with a different data structure (for
|
||||
* example, nsCSS* for specified values vs nsStyle* for computed
|
||||
* values).
|
||||
*
|
||||
* For each leaf in the calc() expression, ComputeCalc will call either
|
||||
* ComputeCoefficient (when the leaf is the left side of a Times_L or the
|
||||
* right side of a Times_R or Divided) or ComputeLeafValue (otherwise).
|
||||
* (The CalcOps in the CSS parser that reduces purely numeric
|
||||
* expressions in turn calls ComputeCalc on numbers; other ops can
|
||||
* presume that expressions in the coefficient positions have already been
|
||||
* normalized to a single numeric value and derive from, if their coefficient
|
||||
* types are floats, FloatCoeffsAlreadyNormalizedCalcOps.)
|
||||
*
|
||||
* ComputeCalc will fail and return false if ComputeLeafValue returns false at
|
||||
* any point during the computation. ComputeLeafValue shall return false if and
|
||||
* only if an unexpected (i.e., inconsistent) unit is encountered.
|
||||
*
|
||||
* coeff_type will be float most of the time, but it's templatized so that
|
||||
* ParseCalc can be used with <integer>s too.
|
||||
*
|
||||
* For non-leaves, one of the Merge functions will be called:
|
||||
* MergeAdditive for Plus and Minus
|
||||
* MergeMultiplicativeL for Times_L (coeff * value)
|
||||
* MergeMultiplicativeR for Times_R (value * coeff) and Divided
|
||||
*/
|
||||
template <class CalcOps>
|
||||
static bool
|
||||
ComputeCalc(typename CalcOps::result_type& aResult,
|
||||
const typename CalcOps::input_type& aValue, CalcOps &aOps)
|
||||
{
|
||||
switch (CalcOps::GetUnit(aValue)) {
|
||||
case eCSSUnit_Calc: {
|
||||
typename CalcOps::input_array_type *arr = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(arr->Count() == 1, "unexpected length");
|
||||
return ComputeCalc(aResult, arr->Item(0), aOps);
|
||||
}
|
||||
case eCSSUnit_Calc_Plus:
|
||||
case eCSSUnit_Calc_Minus: {
|
||||
typename CalcOps::input_array_type *arr = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(arr->Count() == 2, "unexpected length");
|
||||
typename CalcOps::result_type lhs, rhs;
|
||||
if (!ComputeCalc(lhs, arr->Item(0), aOps) ||
|
||||
!ComputeCalc(rhs, arr->Item(1), aOps)) {
|
||||
return false;
|
||||
}
|
||||
aResult = aOps.MergeAdditive(CalcOps::GetUnit(aValue), lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
case eCSSUnit_Calc_Times_L: {
|
||||
typename CalcOps::input_array_type *arr = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(arr->Count() == 2, "unexpected length");
|
||||
typename CalcOps::coeff_type lhs = aOps.ComputeCoefficient(arr->Item(0));
|
||||
typename CalcOps::result_type rhs;
|
||||
if (!ComputeCalc(rhs, arr->Item(1), aOps)) {
|
||||
return false;
|
||||
}
|
||||
aResult = aOps.MergeMultiplicativeL(CalcOps::GetUnit(aValue), lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
case eCSSUnit_Calc_Times_R:
|
||||
case eCSSUnit_Calc_Divided: {
|
||||
typename CalcOps::input_array_type *arr = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(arr->Count() == 2, "unexpected length");
|
||||
typename CalcOps::result_type lhs;
|
||||
if (!ComputeCalc(lhs, arr->Item(0), aOps)) {
|
||||
return false;
|
||||
}
|
||||
typename CalcOps::coeff_type rhs = aOps.ComputeCoefficient(arr->Item(1));
|
||||
aResult = aOps.MergeMultiplicativeR(CalcOps::GetUnit(aValue), lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return aOps.ComputeLeafValue(aResult, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The input unit operation for input_type being nsCSSValue.
|
||||
*/
|
||||
struct CSSValueInputCalcOps
|
||||
{
|
||||
typedef nsCSSValue input_type;
|
||||
typedef nsCSSValue::Array input_array_type;
|
||||
|
||||
static nsCSSUnit GetUnit(const nsCSSValue& aValue)
|
||||
{
|
||||
return aValue.GetUnit();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Basic*CalcOps provide a partial implementation of the CalcOps
|
||||
* template parameter to ComputeCalc, for those callers whose merging
|
||||
* just consists of mathematics (rather than tree construction).
|
||||
*/
|
||||
|
||||
struct BasicCoordCalcOps
|
||||
{
|
||||
typedef nscoord result_type;
|
||||
typedef float coeff_type;
|
||||
|
||||
result_type
|
||||
MergeAdditive(nsCSSUnit aCalcFunction,
|
||||
result_type aValue1, result_type aValue2)
|
||||
{
|
||||
if (aCalcFunction == eCSSUnit_Calc_Plus) {
|
||||
return NSCoordSaturatingAdd(aValue1, aValue2);
|
||||
}
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus,
|
||||
"unexpected unit");
|
||||
return NSCoordSaturatingSubtract(aValue1, aValue2, 0);
|
||||
}
|
||||
|
||||
result_type
|
||||
MergeMultiplicativeL(nsCSSUnit aCalcFunction,
|
||||
coeff_type aValue1, result_type aValue2)
|
||||
{
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
|
||||
"unexpected unit");
|
||||
return NSCoordSaturatingMultiply(aValue2, aValue1);
|
||||
}
|
||||
|
||||
result_type
|
||||
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
|
||||
result_type aValue1, coeff_type aValue2)
|
||||
{
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_R ||
|
||||
aCalcFunction == eCSSUnit_Calc_Divided,
|
||||
"unexpected unit");
|
||||
if (aCalcFunction == eCSSUnit_Calc_Divided) {
|
||||
aValue2 = 1.0f / aValue2;
|
||||
}
|
||||
return NSCoordSaturatingMultiply(aValue1, aValue2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A ComputeCoefficient implementation for callers that can assume coefficients
|
||||
* are floats and are already normalized (i.e., anything past the parser except
|
||||
* pure-integer calcs, whose coefficients are integers).
|
||||
*/
|
||||
struct FloatCoeffsAlreadyNormalizedOps : public CSSValueInputCalcOps
|
||||
{
|
||||
typedef float coeff_type;
|
||||
|
||||
coeff_type ComputeCoefficient(const nsCSSValue& aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
|
||||
return aValue.GetFloatValue();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* SerializeCalc appends the serialization of aValue to a string.
|
||||
*
|
||||
* It is templatized over a CalcOps class that is expected to provide:
|
||||
*
|
||||
* // input_type and input_array_type have a bunch of very specific
|
||||
* // expectations (which happen to be met by two classes (nsCSSValue
|
||||
* // and nsStyleCoord). There must be methods (roughly):
|
||||
* // input_array_type* input_type::GetArrayValue();
|
||||
* // uint32_t input_array_type::Count() const;
|
||||
* // input_type& input_array_type::Item(uint32_t);
|
||||
* typedef ... input_type;
|
||||
* typedef ... input_array_type;
|
||||
*
|
||||
* static nsCSSUnit GetUnit(const input_type& aValue);
|
||||
*
|
||||
* void Append(const char* aString);
|
||||
* void AppendLeafValue(const input_type& aValue);
|
||||
*
|
||||
* // AppendCoefficient accepts an input_type value, which represents a
|
||||
* // value in the coefficient position, not a value of coeff_type,
|
||||
* // because we're serializing the calc() expression itself.
|
||||
* void AppendCoefficient(const input_type& aValue);
|
||||
*
|
||||
* Data structures given may or may not have a toplevel eCSSUnit_Calc
|
||||
* node representing a calc whose toplevel is not min() or max().
|
||||
*/
|
||||
|
||||
template <class CalcOps>
|
||||
static void
|
||||
SerializeCalcInternal(const typename CalcOps::input_type& aValue, CalcOps &aOps);
|
||||
|
||||
// Serialize the toplevel value in a calc() tree. See big comment
|
||||
// above.
|
||||
template <class CalcOps>
|
||||
static void
|
||||
SerializeCalc(const typename CalcOps::input_type& aValue, CalcOps &aOps)
|
||||
{
|
||||
aOps.Append("calc(");
|
||||
nsCSSUnit unit = CalcOps::GetUnit(aValue);
|
||||
if (unit == eCSSUnit_Calc) {
|
||||
const typename CalcOps::input_array_type *array = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(array->Count() == 1, "unexpected length");
|
||||
SerializeCalcInternal(array->Item(0), aOps);
|
||||
} else {
|
||||
SerializeCalcInternal(aValue, aOps);
|
||||
}
|
||||
aOps.Append(")");
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsCalcAdditiveUnit(nsCSSUnit aUnit)
|
||||
{
|
||||
return aUnit == eCSSUnit_Calc_Plus ||
|
||||
aUnit == eCSSUnit_Calc_Minus;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsCalcMultiplicativeUnit(nsCSSUnit aUnit)
|
||||
{
|
||||
return aUnit == eCSSUnit_Calc_Times_L ||
|
||||
aUnit == eCSSUnit_Calc_Times_R ||
|
||||
aUnit == eCSSUnit_Calc_Divided;
|
||||
}
|
||||
|
||||
// Serialize a non-toplevel value in a calc() tree. See big comment
|
||||
// above.
|
||||
template <class CalcOps>
|
||||
/* static */ void
|
||||
SerializeCalcInternal(const typename CalcOps::input_type& aValue, CalcOps &aOps)
|
||||
{
|
||||
nsCSSUnit unit = CalcOps::GetUnit(aValue);
|
||||
if (IsCalcAdditiveUnit(unit)) {
|
||||
const typename CalcOps::input_array_type *array = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(array->Count() == 2, "unexpected length");
|
||||
|
||||
SerializeCalcInternal(array->Item(0), aOps);
|
||||
|
||||
if (eCSSUnit_Calc_Plus == unit) {
|
||||
aOps.Append(" + ");
|
||||
} else {
|
||||
MOZ_ASSERT(eCSSUnit_Calc_Minus == unit, "unexpected unit");
|
||||
aOps.Append(" - ");
|
||||
}
|
||||
|
||||
bool needParens = IsCalcAdditiveUnit(CalcOps::GetUnit(array->Item(1)));
|
||||
if (needParens) {
|
||||
aOps.Append("(");
|
||||
}
|
||||
SerializeCalcInternal(array->Item(1), aOps);
|
||||
if (needParens) {
|
||||
aOps.Append(")");
|
||||
}
|
||||
} else if (IsCalcMultiplicativeUnit(unit)) {
|
||||
const typename CalcOps::input_array_type *array = aValue.GetArrayValue();
|
||||
MOZ_ASSERT(array->Count() == 2, "unexpected length");
|
||||
|
||||
bool needParens = IsCalcAdditiveUnit(CalcOps::GetUnit(array->Item(0)));
|
||||
if (needParens) {
|
||||
aOps.Append("(");
|
||||
}
|
||||
if (unit == eCSSUnit_Calc_Times_L) {
|
||||
aOps.AppendCoefficient(array->Item(0));
|
||||
} else {
|
||||
SerializeCalcInternal(array->Item(0), aOps);
|
||||
}
|
||||
if (needParens) {
|
||||
aOps.Append(")");
|
||||
}
|
||||
|
||||
if (eCSSUnit_Calc_Times_L == unit || eCSSUnit_Calc_Times_R == unit) {
|
||||
aOps.Append(" * ");
|
||||
} else {
|
||||
MOZ_ASSERT(eCSSUnit_Calc_Divided == unit, "unexpected unit");
|
||||
aOps.Append(" / ");
|
||||
}
|
||||
|
||||
nsCSSUnit subUnit = CalcOps::GetUnit(array->Item(1));
|
||||
needParens = IsCalcAdditiveUnit(subUnit) ||
|
||||
IsCalcMultiplicativeUnit(subUnit);
|
||||
if (needParens) {
|
||||
aOps.Append("(");
|
||||
}
|
||||
if (unit == eCSSUnit_Calc_Times_L) {
|
||||
SerializeCalcInternal(array->Item(1), aOps);
|
||||
} else {
|
||||
aOps.AppendCoefficient(array->Item(1));
|
||||
}
|
||||
if (needParens) {
|
||||
aOps.Append(")");
|
||||
}
|
||||
} else {
|
||||
aOps.AppendLeafValue(aValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ReduceCalcOps is a CalcOps implementation for pure-number, pure-percent, and
|
||||
* pure-integer calc() (sub-)expressions, input as nsCSSValues.
|
||||
*
|
||||
* Instantiate with the appropriate coeff/result type and unit, for example:
|
||||
* ReduceCalcOps<float, eCSSUnit_Percent>
|
||||
* ReduceCalcOps<int, eCSSUnit_Integer>
|
||||
* ReduceCalcOps<float, eCSSUnit_Number>
|
||||
*
|
||||
* For example, nsCSSParser::ParseCalcMultiplicativeExpression uses it to
|
||||
* simplify numeric sub-expressions in order to check for division-by-zero.
|
||||
*/
|
||||
template<typename type, nsCSSUnit unit>
|
||||
struct ReduceCalcOps : public mozilla::css::CSSValueInputCalcOps
|
||||
{
|
||||
static_assert((std::is_same<type, int>::value && unit == eCSSUnit_Integer) ||
|
||||
(std::is_same<type, float>::value &&
|
||||
(unit == eCSSUnit_Number || unit == eCSSUnit_Percent)),
|
||||
"ReduceCalcOps: Invalid template arguments: must use "
|
||||
"int coefficient with eCSSUnit_Integer, or "
|
||||
"float coefficient with (eCSSUnit_Number or eCSSUnit_Percent)");
|
||||
|
||||
typedef type result_type;
|
||||
typedef type coeff_type;
|
||||
|
||||
result_type
|
||||
MergeAdditive(nsCSSUnit aCalcFunction,
|
||||
result_type aValue1, result_type aValue2)
|
||||
{
|
||||
if (aCalcFunction == eCSSUnit_Calc_Plus) {
|
||||
return aValue1 + aValue2;
|
||||
}
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus, "unexpected unit");
|
||||
return aValue1 - aValue2;
|
||||
}
|
||||
|
||||
result_type
|
||||
MergeMultiplicativeL(nsCSSUnit aCalcFunction,
|
||||
coeff_type aValue1, result_type aValue2)
|
||||
{
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L, "unexpected unit");
|
||||
return aValue1 * aValue2;
|
||||
}
|
||||
|
||||
result_type
|
||||
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
|
||||
result_type aValue1, coeff_type aValue2)
|
||||
{
|
||||
if (aCalcFunction == eCSSUnit_Calc_Times_R) {
|
||||
return aValue1 * aValue2;
|
||||
}
|
||||
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided, "unexpected unit");
|
||||
MOZ_ASSERT(unit != eCSSUnit_Integer,
|
||||
"We should catch and prevent divisions in integer "
|
||||
"calc()s in the parser");
|
||||
return aValue1 / aValue2;
|
||||
}
|
||||
|
||||
bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
|
||||
{
|
||||
if (aValue.GetUnit() != unit) {
|
||||
return false;
|
||||
}
|
||||
aResult = unit == eCSSUnit_Percent ? aValue.GetPercentValue() :
|
||||
unit == eCSSUnit_Integer ? aValue.GetIntValue() :
|
||||
aValue.GetFloatValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
coeff_type ComputeCoefficient(const nsCSSValue& aValue)
|
||||
{
|
||||
coeff_type coeff;
|
||||
if (!mozilla::css::ComputeCalc(coeff, aValue, *this)) {
|
||||
// Something's wrong; parser should enforce that calc() coefficients are
|
||||
// unitless, but failure in ComputeCalc means there was a unit mismatch.
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected unit");
|
||||
}
|
||||
return coeff;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* !defined(CSSCalc_h_) */
|
@ -16,7 +16,6 @@
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "CSSCalc.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "imgRequestProxy.h"
|
||||
|
Loading…
Reference in New Issue
Block a user