--- a/layout/style/CSSCalc.h
+++ b/layout/style/CSSCalc.h
@@ -3,16 +3,17 @@
* 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.
*
@@ -43,18 +44,18 @@ namespace css {
* result_type
* MergeMultiplicativeL(nsCSSUnit aCalcFunction,
* coeff_type aValue1, result_type aValue2);
*
* result_type
* MergeMultiplicativeR(nsCSSUnit aCalcFunction,
* result_type aValue1, coeff_type aValue2);
*
- * result_type
- * ComputeLeafValue(const input_type& aValue);
+ * 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
@@ -64,59 +65,76 @@ namespace css {
* 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 typename CalcOps::result_type
-ComputeCalc(const typename CalcOps::input_type& aValue, CalcOps &aOps)
+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(arr->Item(0), aOps);
+ 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 = ComputeCalc(arr->Item(0), aOps),
- rhs = ComputeCalc(arr->Item(1), aOps);
- return aOps.MergeAdditive(CalcOps::GetUnit(aValue), lhs, rhs);
+ 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 = ComputeCalc(arr->Item(1), aOps);
- return aOps.MergeMultiplicativeL(CalcOps::GetUnit(aValue), lhs, rhs);
+ 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 = ComputeCalc(arr->Item(0), aOps);
+ typename CalcOps::result_type lhs;
+ if (!ComputeCalc(lhs, arr->Item(0), aOps)) {
+ return false;
+ }
typename CalcOps::coeff_type rhs = aOps.ComputeCoefficient(arr->Item(1));
- return aOps.MergeMultiplicativeR(CalcOps::GetUnit(aValue), lhs, rhs);
+ aResult = aOps.MergeMultiplicativeR(CalcOps::GetUnit(aValue), lhs, rhs);
+ return true;
}
default: {
- return aOps.ComputeLeafValue(aValue);
+ return aOps.ComputeLeafValue(aResult, aValue);
}
}
}
/**
* The input unit operation for input_type being nsCSSValue.
*/
struct CSSValueInputCalcOps
@@ -172,94 +190,16 @@ struct BasicCoordCalcOps
"unexpected unit");
if (aCalcFunction == eCSSUnit_Calc_Divided) {
aValue2 = 1.0f / aValue2;
}
return NSCoordSaturatingMultiply(aValue1, aValue2);
}
};
-struct BasicFloatCalcOps
-{
- typedef float result_type;
- typedef float 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");
- return aValue1 / aValue2;
- }
-};
-
-struct BasicIntegerCalcOps
-{
- typedef int result_type;
- typedef int 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_UNREACHABLE("We should catch and prevent divisions in integer "
- "calc()s in the parser.");
- return 1;
- }
-};
-
/**
* 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;
@@ -403,54 +343,93 @@ SerializeCalcInternal(const typename Cal
aOps.Append(")");
}
} else {
aOps.AppendLeafValue(aValue);
}
}
/**
- * ReduceNumberCalcOps is a CalcOps implementation for pure-number calc()
- * (sub-)expressions, input as nsCSSValues.
+ * 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.
*/
-struct ReduceNumberCalcOps : public mozilla::css::BasicFloatCalcOps,
- public mozilla::css::CSSValueInputCalcOps
+template<typename type, nsCSSUnit unit>
+struct ReduceCalcOps : public mozilla::css::CSSValueInputCalcOps
{
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ 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(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
- return aValue.GetFloatValue();
+ 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)
{
- return mozilla::css::ComputeCalc(aValue, *this);
- }
-};
-
-/**
- * ReduceIntegerCalcOps is a CalcOps implementation for pure-integer calc()
- * (sub-)expressions, input as nsCSSValues.
- */
-struct ReduceIntegerCalcOps : public mozilla::css::BasicIntegerCalcOps,
- public mozilla::css::CSSValueInputCalcOps
-{
- result_type
- ComputeLeafValue(const nsCSSValue& aValue)
- {
- MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Integer, "unexpected unit");
- return aValue.GetIntValue();
- }
-
- coeff_type
- ComputeCoefficient(const nsCSSValue& aValue)
- {
- return mozilla::css::ComputeCalc(aValue, *this);
+ 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_) */
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -13621,37 +13621,46 @@ CSSParserImpl::ParseCalcMultiplicativeEx
"ParseCalcTerm did not set variantMask appropriately");
MOZ_ASSERT(!(variantMask & VARIANT_NUMBER) ||
!(variantMask & ~int32_t(VARIANT_NUMBER)),
"ParseCalcTerm did not set variantMask appropriately");
if (variantMask & VARIANT_NUMBER) {
// Simplify the value immediately so we can check for division by
// zero.
- mozilla::css::ReduceNumberCalcOps ops;
- float number = mozilla::css::ComputeCalc(*storage, ops);
+ float number;
+ mozilla::css::ReduceCalcOps<float, eCSSUnit_Number> ops;
+ if (!mozilla::css::ComputeCalc(number, *storage, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected unit");
+ }
if (number == 0.0 && afterDivision)
return false;
storage->SetFloatValue(number, eCSSUnit_Number);
} else {
gotValue = true;
if (storage != &aValue) {
// Simplify any numbers in the Times_L position (which are
// not simplified by the check above).
MOZ_ASSERT(storage == &aValue.GetArrayValue()->Item(1),
"unexpected relationship to current storage");
nsCSSValue &leftValue = aValue.GetArrayValue()->Item(0);
if (variantMask & VARIANT_INTEGER) {
- mozilla::css::ReduceIntegerCalcOps ops;
- int integer = mozilla::css::ComputeCalc(leftValue, ops);
+ int integer;
+ mozilla::css::ReduceCalcOps<int, eCSSUnit_Integer> ops;
+ if (!mozilla::css::ComputeCalc(integer, leftValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected unit");
+ }
leftValue.SetIntValue(integer, eCSSUnit_Integer);
} else {
- mozilla::css::ReduceNumberCalcOps ops;
- float number = mozilla::css::ComputeCalc(leftValue, ops);
+ float number;
+ mozilla::css::ReduceCalcOps<float, eCSSUnit_Number> ops;
+ if (!mozilla::css::ComputeCalc(number, leftValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected unit");
+ }
leftValue.SetFloatValue(number, eCSSUnit_Number);
}
}
}
bool hadWS = RequireWhitespace();
if (!GetToken(false)) {
*aHadFinalWS = hadWS;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -339,21 +339,23 @@ struct CalcLengthCalcOps : public css::B
mStyleContext(aStyleContext),
mPresContext(aPresContext),
mUseProvidedRootEmSize(aUseProvidedRootEmSize),
mUseUserFontSet(aUseUserFontSet),
mConditions(aConditions)
{
}
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
{
- return CalcLengthWith(aValue, mFontSize, mStyleFont,
- mStyleContext, mPresContext, mUseProvidedRootEmSize,
- mUseUserFontSet, mConditions);
+ aResult = CalcLengthWith(aValue, mFontSize, mStyleFont,
+ mStyleContext, mPresContext,
+ mUseProvidedRootEmSize, mUseUserFontSet,
+ mConditions);
+ return true;
}
};
static inline nscoord ScaleCoordRound(const nsCSSValue& aValue, float aFactor)
{
return NSToCoordRoundWithClamp(aValue.GetFloatValue() * aFactor);
}
@@ -547,17 +549,21 @@ static nscoord CalcLengthWith(const nsCS
// calc(), we can handle calc() here and just compute a final
// result. We ensure that we don't get to this code for other
// properties by not calling CalcLength in those cases: SetCoord
// only calls CalcLength for a calc when it is appropriate to do so.
CalcLengthCalcOps ops(aFontSize, aStyleFont,
aStyleContext, aPresContext,
aUseProvidedRootEmSize, aUseUserFontSet,
aConditions);
- return css::ComputeCalc(aValue, ops);
+ nscoord result;
+ if (!css::ComputeCalc(result, aValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
+ return result;
}
switch (aValue.GetUnit()) {
// nsPresContext::SetVisibleArea and
// nsPresContext::MediaFeatureValuesChanged handle dynamic changes
// of the basis for viewport units by rebuilding the rule tree and
// style context tree. Not caching them in the rule tree wouldn't
// be sufficient to handle these changes because we also need a way
// to get rid of cached values in the style context tree without any
@@ -741,25 +747,27 @@ struct LengthPercentPairCalcOps : public
mConditions(aConditions),
mHasPercent(false) {}
nsStyleContext* mContext;
nsPresContext* mPresContext;
RuleNodeCacheConditions& mConditions;
bool mHasPercent;
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
{
if (aValue.GetUnit() == eCSSUnit_Percent) {
mHasPercent = true;
- return result_type(0, aValue.GetPercentValue());
- }
- return result_type(CalcLength(aValue, mContext, mPresContext,
- mConditions),
- 0.0f);
+ aResult = result_type(0, aValue.GetPercentValue());
+ return true;
+ }
+ aResult = result_type(CalcLength(aValue, mContext, mPresContext,
+ mConditions),
+ 0.0f);
+ return true;
}
result_type
MergeAdditive(nsCSSUnit aCalcFunction,
result_type aValue1, result_type aValue2)
{
if (aCalcFunction == eCSSUnit_Calc_Plus) {
return result_type(NSCoordSaturatingAdd(aValue1.mLength,
@@ -801,17 +809,20 @@ struct LengthPercentPairCalcOps : public
static void
SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
nsStyleContext* aStyleContext,
RuleNodeCacheConditions& aConditions)
{
LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
aConditions);
- nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
+ nsRuleNode::ComputedCalc vals;
+ if (!ComputeCalc(vals, aValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc;
calcObj->mLength = vals.mLength;
calcObj->mPercent = vals.mPercent;
calcObj->mHasPercent = ops.mHasPercent;
aCoord.SetCalcValue(calcObj);
@@ -820,17 +831,21 @@ SpecifiedCalcToComputedCalc(const nsCSSV
/* static */ nsRuleNode::ComputedCalc
nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions)
{
LengthPercentPairCalcOps ops(aStyleContext, aPresContext,
aConditions);
- return ComputeCalc(aValue, ops);
+ nsRuleNode::ComputedCalc result;
+ if (!ComputeCalc(result, aValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
+ return result;
}
// This is our public API for handling calc() expressions that involve
// percentages.
/* static */ nscoord
nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
nscoord aPercentageBasis)
{
@@ -3358,17 +3373,17 @@ struct SetFontSizeCalcOps : public css::
mParentFont(aParentFont),
mPresContext(aPresContext),
mStyleContext(aStyleContext),
mAtRoot(aAtRoot),
mConditions(aConditions)
{
}
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
{
nscoord size;
if (aValue.IsLengthUnit()) {
// Note that font-based length units use the parent's size
// unadjusted for scriptlevel changes. A scriptlevel change
// between us and the parent is simply ignored.
size = CalcLengthWith(aValue, mParentSize,
mParentFont,
@@ -3385,17 +3400,18 @@ struct SetFontSizeCalcOps : public css::
// ignored.
// aValue.GetPercentValue() may be negative for, e.g., calc(-50%)
size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue());
} else {
MOZ_ASSERT(false, "unexpected value");
size = mParentSize;
}
- return size;
+ aResult = size;
+ return true;
}
};
/* static */ void
nsRuleNode::SetFontSize(nsPresContext* aPresContext,
GeckoStyleContext* aContext,
const nsRuleData* aRuleData,
const nsStyleFont* aFont,
@@ -3451,17 +3467,19 @@ nsRuleNode::SetFontSize(nsPresContext* a
}
else if (sizeValue->IsLengthUnit() ||
sizeValue->GetUnit() == eCSSUnit_Percent ||
sizeValue->IsCalcUnit()) {
SetFontSizeCalcOps ops(aParentSize, aParentFont,
aPresContext, aContext,
aAtRoot,
aConditions);
- *aSize = css::ComputeCalc(*sizeValue, ops);
+ if (!css::ComputeCalc(*aSize, *sizeValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
if (*aSize < 0) {
MOZ_ASSERT(sizeValue->IsCalcUnit(),
"negative lengths and percents should be rejected by parser");
*aSize = 0;
}
// The calc ops will always zoom its result according to the value
// of aParentFont->mAllowZoom.
sizeIsZoomedAccordingToParent = true;
@@ -4594,70 +4612,68 @@ struct LengthNumberCalcOps : public css:
return result;
}
MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided,
"unexpected unit");
result.mValue = aValue1.mValue / aValue2;
return result;
}
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
{
- LengthNumberCalcObj result;
if (aValue.IsLengthUnit()) {
- result.mIsNumber = false;
- result.mValue = CalcLength(aValue, mStyleContext,
+ aResult.mIsNumber = false;
+ aResult.mValue = CalcLength(aValue, mStyleContext,
mPresContext, mConditions);
}
else if (eCSSUnit_Number == aValue.GetUnit()) {
- result.mIsNumber = true;
- result.mValue = aValue.GetFloatValue();
+ aResult.mIsNumber = true;
+ aResult.mValue = aValue.GetFloatValue();
} else {
MOZ_ASSERT(false, "unexpected value");
- result.mIsNumber = true;
- result.mValue = 1.0f;
- }
-
- return result;
+ aResult.mIsNumber = true;
+ aResult.mValue = 1.0f;
+ }
+
+ return true;
}
};
struct SetLineHeightCalcOps : public LengthNumberCalcOps
{
SetLineHeightCalcOps(GeckoStyleContext* aStyleContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions)
: LengthNumberCalcOps(aStyleContext, aPresContext, aConditions)
{
}
- result_type ComputeLeafValue(const nsCSSValue& aValue)
+ bool ComputeLeafValue(result_type& aResult, const nsCSSValue& aValue)
{
- LengthNumberCalcObj result;
if (aValue.IsLengthUnit()) {
- result.mIsNumber = false;
- result.mValue = CalcLength(aValue, mStyleContext,
+ aResult.mIsNumber = false;
+ aResult.mValue = CalcLength(aValue, mStyleContext,
mPresContext, mConditions);
}
else if (eCSSUnit_Percent == aValue.GetUnit()) {
mConditions.SetUncacheable();
- result.mIsNumber = false;
+ aResult.mIsNumber = false;
nscoord fontSize = mStyleContext->StyleFont()->mFont.size;
- result.mValue = fontSize * aValue.GetPercentValue();
+ aResult.mValue = fontSize * aValue.GetPercentValue();
}
else if (eCSSUnit_Number == aValue.GetUnit()) {
- result.mIsNumber = true;
- result.mValue = aValue.GetFloatValue();
+ aResult.mIsNumber = true;
+ aResult.mValue = aValue.GetFloatValue();
} else {
MOZ_ASSERT(false, "unexpected value");
- result.mIsNumber = true;
- result.mValue = 1.0f;
- }
-
- return result;
+ aResult.mIsNumber = true;
+ aResult.mValue = 1.0f;
+ }
+
+ return true;
}
};
const void*
nsRuleNode::ComputeTextData(void* aStartStruct,
const nsRuleData* aRuleData,
GeckoStyleContext* aContext,
nsRuleNode* aHighestNode,
@@ -4674,17 +4690,20 @@ nsRuleNode::ComputeTextData(void* aStart
};
// tab-size: number, length, calc, inherit
const nsCSSValue* tabSizeValue = aRuleData->ValueForTabSize();
if (tabSizeValue->GetUnit() == eCSSUnit_Initial) {
text->mTabSize = nsStyleCoord(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor);
} else if (eCSSUnit_Calc == tabSizeValue->GetUnit()) {
LengthNumberCalcOps ops(aContext, mPresContext, conditions);
- LengthNumberCalcObj obj = css::ComputeCalc(*tabSizeValue, ops);
+ LengthNumberCalcObj obj;
+ if (!css::ComputeCalc(obj, *tabSizeValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
float value = obj.mValue < 0 ? 0 : obj.mValue;
if (obj.mIsNumber) {
text->mTabSize.SetFactorValue(value);
} else {
text->mTabSize.SetCoordValue(
NSToCoordRoundWithClamp(value));
}
} else {
@@ -4729,17 +4748,20 @@ nsRuleNode::ComputeTextData(void* aStart
lineHeightValue->GetPercentValue()));
}
else if (eCSSUnit_Initial == lineHeightValue->GetUnit() ||
eCSSUnit_System_Font == lineHeightValue->GetUnit()) {
text->mLineHeight.SetNormalValue();
}
else if (eCSSUnit_Calc == lineHeightValue->GetUnit()) {
SetLineHeightCalcOps ops(aContext, mPresContext, conditions);
- LengthNumberCalcObj obj = css::ComputeCalc(*lineHeightValue, ops);
+ LengthNumberCalcObj obj;
+ if (!css::ComputeCalc(obj, *lineHeightValue, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
if (obj.mIsNumber) {
text->mLineHeight.SetFactorValue(obj.mValue);
} else {
text->mLineHeight.SetCoordValue(
NSToCoordRoundWithClamp(obj.mValue));
}
}
else {
@@ -6871,17 +6893,20 @@ ComputePositionCoord(GeckoStyleContext*
aStyleContext->PresContext(),
aConditions);
aResult->mPercent = 0.0f;
aResult->mHasPercent = false;
} else if (aOffset.IsCalcUnit()) {
LengthPercentPairCalcOps ops(aStyleContext,
aStyleContext->PresContext(),
aConditions);
- nsRuleNode::ComputedCalc vals = ComputeCalc(aOffset, ops);
+ nsRuleNode::ComputedCalc vals;
+ if (!ComputeCalc(vals, aOffset, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
aResult->mLength = vals.mLength;
aResult->mPercent = vals.mPercent;
aResult->mHasPercent = ops.mHasPercent;
} else {
aResult->mLength = 0;
aResult->mPercent = 0.0f;
aResult->mHasPercent = false;
NS_ASSERTION(aOffset.GetUnit() == eCSSUnit_Null, "unexpected unit");
@@ -7044,17 +7069,20 @@ struct BackgroundItemComputer<nsCSSValue
(size.*(axis->result)).mPercent = 0.0f;
(size.*(axis->result)).mHasPercent = false;
size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
} else {
MOZ_ASSERT(specified.IsCalcUnit(), "unexpected unit");
LengthPercentPairCalcOps ops(aStyleContext,
aStyleContext->PresContext(),
aConditions);
- nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops);
+ nsRuleNode::ComputedCalc vals;
+ if (!ComputeCalc(vals, specified, ops)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected ComputeCalc failure");
+ }
(size.*(axis->result)).mLength = vals.mLength;
(size.*(axis->result)).mPercent = vals.mPercent;
(size.*(axis->result)).mHasPercent = ops.mHasPercent;
size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
}
}
MOZ_ASSERT(size.mWidthType < nsStyleImageLayers::Size::eDimensionType_COUNT,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -1010,16 +1010,18 @@ public:
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
mozilla::RuleNodeCacheConditions& aConditions);
struct ComputedCalc {
nscoord mLength;
float mPercent;
+ ComputedCalc() {}
+
ComputedCalc(nscoord aLength, float aPercent)
: mLength(aLength), mPercent(aPercent) {}
};
static ComputedCalc
SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
mozilla::RuleNodeCacheConditions& aConditions);