Simplify storage of computed calc() as a result of removing min() and max(). (Bug 363249) r=bzbarsky a2.0=blocking2.0:beta6

This commit is contained in:
L. David Baron 2010-09-11 09:27:13 -07:00
Родитель e031591955
Коммит 3d7d18c200
8 изменённых файлов: 211 добавлений и 584 удалений

Просмотреть файл

@ -3216,75 +3216,6 @@ nsIFrame::InlinePrefWidthData::ForceBreak(nsIRenderingContext *aRenderingContext
skipWhitespace = PR_TRUE;
}
/**
* This class does calc() computation of lengths and percents separately.
*
* FIXME: remove this in the next patch
*
* It is used only for intrinsic width computation, where being an
* approximation is sometimes ok (although it would be good to fix at
* some point in the future).
*/
struct LengthPercentPairWithMinMaxCalcOps : public css::StyleCoordInputCalcOps
{
struct result_type {
nscoord mLength;
float mPercent;
result_type(nscoord aLength, float aPercent)
: mLength(aLength), mPercent(aPercent) {}
};
result_type ComputeLeafValue(const nsStyleCoord& aValue)
{
if (aValue.GetUnit() == eStyleUnit_Percent) {
return result_type(0, aValue.GetPercentValue());
}
return result_type(aValue.GetCoordValue(), 0.0f);
}
result_type
MergeAdditive(nsCSSUnit aCalcFunction,
result_type aValue1, result_type aValue2)
{
if (aCalcFunction == eCSSUnit_Calc_Plus) {
return result_type(NSCoordSaturatingAdd(aValue1.mLength,
aValue2.mLength),
aValue1.mPercent + aValue2.mPercent);
}
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Minus,
"unexpected unit");
return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
aValue2.mLength, 0),
aValue1.mPercent - aValue2.mPercent);
}
result_type
MergeMultiplicativeL(nsCSSUnit aCalcFunction,
float aValue1, result_type aValue2)
{
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_L,
"unexpected unit");
return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
aValue1 * aValue2.mPercent);
}
result_type
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
result_type aValue1, float aValue2)
{
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_R ||
aCalcFunction == eCSSUnit_Calc_Divided,
"unexpected unit");
if (aCalcFunction == eCSSUnit_Calc_Divided) {
aValue2 = 1.0f / aValue2;
}
return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
aValue1.mPercent * aValue2);
}
};
static void
AddCoord(const nsStyleCoord& aStyle,
nsIRenderingContext* aRenderingContext,
@ -3292,20 +3223,35 @@ AddCoord(const nsStyleCoord& aStyle,
nscoord* aCoord, float* aPercent,
PRBool aClampNegativeToZero)
{
if (!aStyle.IsCoordPercentCalcUnit()) {
return;
switch (aStyle.GetUnit()) {
case eStyleUnit_Coord: {
NS_ASSERTION(!aClampNegativeToZero || aStyle.GetCoordValue() >= 0,
"unexpected negative value");
*aCoord += aStyle.GetCoordValue();
return;
}
case eStyleUnit_Percent: {
NS_ASSERTION(!aClampNegativeToZero || aStyle.GetPercentValue() >= 0.0f,
"unexpected negative value");
*aPercent += aStyle.GetPercentValue();
return;
}
case eStyleUnit_Calc: {
const nsStyleCoord::Calc *calc = aStyle.GetCalcValue();
if (aClampNegativeToZero) {
// This is far from ideal when one is negative and one is positive.
*aCoord += NS_MAX(calc->mLength, 0);
*aPercent += NS_MAX(calc->mPercent, 0.0f);
} else {
*aCoord += calc->mLength;
*aPercent += calc->mPercent;
}
return;
}
default: {
return;
}
}
LengthPercentPairWithMinMaxCalcOps ops;
LengthPercentPairWithMinMaxCalcOps::result_type pair =
css::ComputeCalc(aStyle, ops);
if (aClampNegativeToZero) {
// This is far from ideal when one is negative and one is positive.
pair.mLength = NS_MAX(pair.mLength, 0);
pair.mPercent = NS_MAX(pair.mPercent, 0.0f);
}
*aCoord += pair.mLength;
*aPercent += pair.mPercent;
}
/* virtual */ nsIFrame::IntrinsicWidthOffsetData
@ -3313,10 +3259,6 @@ nsFrame::IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext)
{
IntrinsicWidthOffsetData result;
// FIXME: The handling of calc() with min() and max() by AddCoord
// is a rough approximation. It could be improved, but only by
// changing the IntrinsicWidthOffsets API substantially. See the
// comment above LengthPercentPairWithMinMaxCalcOps.
const nsStyleMargin *styleMargin = GetStyleMargin();
AddCoord(styleMargin->mMargin.GetLeft(), aRenderingContext, this,
&result.hMargin, &result.hPctMargin, PR_FALSE);

Просмотреть файл

@ -143,36 +143,6 @@ ComputeCalc(const typename CalcOps::input_type& aValue, CalcOps &aOps)
}
}
#define CHECK_UNIT(u_) \
PR_STATIC_ASSERT(int(eCSSUnit_##u_) + 14 == int(eStyleUnit_##u_)); \
PR_STATIC_ASSERT(eCSSUnit_##u_ >= eCSSUnit_Calc); \
PR_STATIC_ASSERT(eCSSUnit_##u_ <= eCSSUnit_Calc_Divided);
CHECK_UNIT(Calc)
CHECK_UNIT(Calc_Plus)
CHECK_UNIT(Calc_Minus)
CHECK_UNIT(Calc_Times_L)
CHECK_UNIT(Calc_Times_R)
CHECK_UNIT(Calc_Divided)
#undef CHECK_UNIT
inline nsStyleUnit
ConvertCalcUnit(nsCSSUnit aUnit)
{
NS_ABORT_IF_FALSE(eCSSUnit_Calc <= aUnit &&
aUnit <= eCSSUnit_Calc_Divided, "out of range");
return nsStyleUnit(aUnit + 14);
}
inline nsCSSUnit
ConvertCalcUnit(nsStyleUnit aUnit)
{
NS_ABORT_IF_FALSE(eStyleUnit_Calc <= aUnit &&
aUnit <= eStyleUnit_Calc_Divided, "out of range");
return nsCSSUnit(aUnit - 14);
}
/**
* The input unit operation for input_type being nsCSSValue.
*/
@ -188,30 +158,6 @@ struct CSSValueInputCalcOps
};
/**
* The input unit operation for input_type being nsStyleCoord
*/
struct StyleCoordInputCalcOps
{
typedef nsStyleCoord input_type;
typedef nsStyleCoord::Array input_array_type;
static nsCSSUnit GetUnit(const nsStyleCoord& aValue)
{
if (aValue.IsCalcUnit()) {
return css::ConvertCalcUnit(aValue.GetUnit());
}
return eCSSUnit_Null;
}
float ComputeNumber(const nsStyleCoord& aValue)
{
NS_ABORT_IF_FALSE(PR_FALSE, "SpecifiedToComputedCalcOps should not "
"leave numbers in structure");
return 0.0f;
}
};
/**
* Basic*CalcOps provide a partial implementation of the CalcOps
* template parameter to ComputeCalc, for those callers whose merging

Просмотреть файл

@ -3802,54 +3802,6 @@ nsComputedDOMStyle::GetBorderStyleFor(mozilla::css::Side aSide, nsIDOMCSSValue**
return NS_OK;
}
struct StyleCoordSerializeCalcOps {
StyleCoordSerializeCalcOps(nsAString& aResult)
: mResult(aResult)
{
}
typedef nsStyleCoord input_type;
typedef nsStyleCoord::Array input_array_type;
static nsCSSUnit GetUnit(const input_type& aValue) {
if (aValue.IsCalcUnit()) {
return css::ConvertCalcUnit(aValue.GetUnit());
}
return eCSSUnit_Null;
}
void Append(const char* aString)
{
mResult.AppendASCII(aString);
}
void AppendLeafValue(const input_type& aValue)
{
nsRefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue();
if (aValue.GetUnit() == eStyleUnit_Percent) {
val->SetPercent(aValue.GetPercentValue());
} else {
NS_ABORT_IF_FALSE(aValue.GetUnit() == eStyleUnit_Coord,
"unexpected unit");
val->SetAppUnits(aValue.GetCoordValue());
}
nsAutoString tmp;
val->GetCssText(tmp);
mResult.Append(tmp);
}
void AppendNumber(const input_type& aValue)
{
NS_ABORT_IF_FALSE(PR_FALSE,
"should not have numbers in nsStyleCoord calc()");
}
private:
nsAString &mResult;
};
void
nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
const nsStyleCoord& aCoord,
@ -3909,37 +3861,51 @@ nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
aValue->SetIdent(eCSSKeyword_none);
break;
default:
if (aCoord.IsCalcUnit()) {
nscoord percentageBase;
if (!aCoord.CalcHasPercent()) {
nscoord val = nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
if (aClampNegativeCalc && val < 0) {
NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
"parser should have rejected value");
val = 0;
}
aValue->SetAppUnits(NS_MAX(aMinAppUnits, NS_MIN(val, aMaxAppUnits)));
} else if (aPercentageBaseGetter &&
(this->*aPercentageBaseGetter)(percentageBase)) {
nscoord val =
nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
if (aClampNegativeCalc && val < 0) {
NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
"parser should have rejected value");
val = 0;
}
aValue->SetAppUnits(NS_MAX(aMinAppUnits, NS_MIN(val, aMaxAppUnits)));
} else {
nsAutoString tmp;
StyleCoordSerializeCalcOps ops(tmp);
css::SerializeCalc(aCoord, ops);
aValue->SetString(tmp); // not really SetString
case eStyleUnit_Calc:
nscoord percentageBase;
if (!aCoord.CalcHasPercent()) {
nscoord val = nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
if (aClampNegativeCalc && val < 0) {
NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
"parser should have rejected value");
val = 0;
}
aValue->SetAppUnits(NS_MAX(aMinAppUnits, NS_MIN(val, aMaxAppUnits)));
} else if (aPercentageBaseGetter &&
(this->*aPercentageBaseGetter)(percentageBase)) {
nscoord val =
nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
if (aClampNegativeCalc && val < 0) {
NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
"parser should have rejected value");
val = 0;
}
aValue->SetAppUnits(NS_MAX(aMinAppUnits, NS_MIN(val, aMaxAppUnits)));
} else {
NS_ERROR("Can't handle this unit");
nsStyleCoord::Calc *calc = aCoord.GetCalcValue();
nsRefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue();
nsAutoString tmp, result;
result.AppendLiteral("-moz-calc(");
val->SetAppUnits(calc->mLength);
val->GetCssText(tmp);
result.Append(tmp);
result.AppendLiteral(" + ");
val->SetPercent(calc->mPercent);
val->GetCssText(tmp);
result.Append(tmp);
result.AppendLiteral(")");
aValue->SetString(result); // not really SetString
}
break;
default:
NS_ERROR("Can't handle this unit");
break;
}
}

Просмотреть файл

@ -371,134 +371,75 @@ nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
PR_TRUE, PR_FALSE, canStoreInRuleTree);
}
struct SpecifiedToComputedCalcOps : public css::NumbersAlreadyNormalizedOps
struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps
{
// FIXME (perf): Is there too much copying as a result of returning
// nsStyleCoord objects?
typedef nsStyleCoord result_type;
typedef nsRuleNode::ComputedCalc result_type;
nsStyleContext* const mStyleContext;
nsPresContext* const mPresContext;
PRBool& mCanStoreInRuleTree;
SpecifiedToComputedCalcOps(nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree)
: mStyleContext(aStyleContext),
LengthPercentPairCalcOps(nsStyleContext* aContext,
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree)
: mContext(aContext),
mPresContext(aPresContext),
mCanStoreInRuleTree(aCanStoreInRuleTree)
mCanStoreInRuleTree(aCanStoreInRuleTree),
mHasPercent(PR_FALSE) {}
nsStyleContext* mContext;
nsPresContext* mPresContext;
PRBool& mCanStoreInRuleTree;
PRBool mHasPercent;
result_type ComputeLeafValue(const nsCSSValue& aValue)
{
if (aValue.GetUnit() == eCSSUnit_Percent) {
mHasPercent = PR_TRUE;
return result_type(0, aValue.GetPercentValue());
}
return result_type(CalcLength(aValue, mContext, mPresContext,
mCanStoreInRuleTree),
0.0f);
}
result_type
MergeAdditive(nsCSSUnit aCalcFunction,
result_type aValue1, result_type aValue2)
{
nsStyleUnit unit1 = aValue1.GetUnit();
nsStyleUnit unit2 = aValue2.GetUnit();
NS_ABORT_IF_FALSE(unit1 == eStyleUnit_Coord ||
unit1 == eStyleUnit_Percent ||
aValue1.IsCalcUnit(),
"unexpected unit");
NS_ABORT_IF_FALSE(unit2 == eStyleUnit_Coord ||
unit2 == eStyleUnit_Percent ||
aValue2.IsCalcUnit(),
"unexpected unit");
nsStyleCoord result;
if (unit1 == unit2 && !aValue1.IsCalcUnit()) {
// Merge nodes that we don't need to keep separate.
if (unit1 == eStyleUnit_Percent) {
css::BasicFloatCalcOps ops;
result.SetPercentValue(ops.MergeAdditive(aCalcFunction,
aValue1.GetPercentValue(),
aValue2.GetPercentValue()));
} else {
css::BasicCoordCalcOps ops;
result.SetCoordValue(ops.MergeAdditive(aCalcFunction,
aValue1.GetCoordValue(),
aValue2.GetCoordValue()));
}
} else {
nsStyleCoord::Array *array =
nsStyleCoord::Array::Create(mStyleContext, mCanStoreInRuleTree, 2);
array->Item(0) = aValue1;
array->Item(1) = aValue2;
result.SetArrayValue(array, css::ConvertCalcUnit(aCalcFunction));
if (aCalcFunction == eCSSUnit_Calc_Plus) {
return result_type(NSCoordSaturatingAdd(aValue1.mLength,
aValue2.mLength),
aValue1.mPercent + aValue2.mPercent);
}
return result;
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Minus,
"min() and max() are not allowed in calc() on "
"transform");
return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
aValue2.mLength, 0),
aValue1.mPercent - aValue2.mPercent);
}
result_type
MergeMultiplicativeL(nsCSSUnit aCalcFunction,
float aValue1, result_type aValue2)
{
nsStyleCoord result;
switch (aValue2.GetUnit()) {
case eStyleUnit_Percent: {
css::BasicFloatCalcOps ops;
result.SetPercentValue(ops.MergeMultiplicativeL(
aCalcFunction, aValue1, aValue2.GetPercentValue()));
break;
}
case eStyleUnit_Coord: {
css::BasicCoordCalcOps ops;
result.SetCoordValue(ops.MergeMultiplicativeL(
aCalcFunction, aValue1, aValue2.GetCoordValue()));
break;
}
default:
NS_ABORT_IF_FALSE(aValue2.IsCalcUnit(), "unexpected unit");
nsStyleCoord::Array *array =
nsStyleCoord::Array::Create(mStyleContext, mCanStoreInRuleTree, 2);
array->Item(0).SetFactorValue(aValue1);
array->Item(1) = aValue2;
result.SetArrayValue(array, css::ConvertCalcUnit(aCalcFunction));
break;
}
return result;
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_L,
"unexpected unit");
return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
aValue1 * aValue2.mPercent);
}
result_type
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
result_type aValue1, float aValue2)
{
nsStyleCoord result;
switch (aValue1.GetUnit()) {
case eStyleUnit_Percent: {
css::BasicFloatCalcOps ops;
result.SetPercentValue(ops.MergeMultiplicativeR(
aCalcFunction, aValue1.GetPercentValue(), aValue2));
break;
}
case eStyleUnit_Coord: {
css::BasicCoordCalcOps ops;
result.SetCoordValue(ops.MergeMultiplicativeR(
aCalcFunction, aValue1.GetCoordValue(), aValue2));
break;
}
default:
NS_ABORT_IF_FALSE(aValue1.IsCalcUnit(), "unexpected unit");
nsStyleCoord::Array *array =
nsStyleCoord::Array::Create(mStyleContext, mCanStoreInRuleTree, 2);
array->Item(0) = aValue1;
array->Item(1).SetFactorValue(aValue2);
result.SetArrayValue(array, css::ConvertCalcUnit(aCalcFunction));
break;
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_R ||
aCalcFunction == eCSSUnit_Calc_Divided,
"unexpected unit");
if (aCalcFunction == eCSSUnit_Calc_Divided) {
aValue2 = 1.0f / aValue2;
}
return result;
return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
aValue1.mPercent * aValue2);
}
result_type ComputeLeafValue(const nsCSSValue& aValue)
{
nsStyleCoord result;
if (aValue.GetUnit() == eCSSUnit_Percent) {
result.SetPercentValue(aValue.GetPercentValue());
} else {
result.SetCoordValue(CalcLength(aValue, mStyleContext, mPresContext,
mCanStoreInRuleTree));
}
return result;
}
};
static void
@ -506,41 +447,33 @@ SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
nsStyleContext* aStyleContext,
PRBool& aCanStoreInRuleTree)
{
SpecifiedToComputedCalcOps ops(aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
aCoord = ComputeCalc(aValue, ops);
if (!aCoord.IsCalcUnit()) {
// Some callers distinguish between calc(50%) and 50%, or calc(50px)
// and 50px.
nsStyleCoord::Array *array =
nsStyleCoord::Array::Create(aStyleContext, aCanStoreInRuleTree, 1);
array->Item(0) = aCoord;
aCoord.SetArrayValue(array, eStyleUnit_Calc);
}
LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
nsStyleCoord::Calc *calcObj =
new (aStyleContext->Alloc(sizeof(nsStyleCoord::Calc))) nsStyleCoord::Calc;
// Because we use aStyleContext->Alloc(), we have to store the result
// on the style context and not in the rule tree.
aCanStoreInRuleTree = PR_FALSE;
calcObj->mLength = vals.mLength;
calcObj->mPercent = vals.mPercent;
calcObj->mHasPercent = ops.mHasPercent;
aCoord.SetCalcValue(calcObj);
}
struct ComputeComputedCalcCalcOps : public css::StyleCoordInputCalcOps,
public css::BasicCoordCalcOps
/* static */ nsRuleNode::ComputedCalc
nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree)
{
const nscoord mPercentageBasis;
ComputeComputedCalcCalcOps(nscoord aPercentageBasis)
: mPercentageBasis(aPercentageBasis)
{
}
result_type ComputeLeafValue(const nsStyleCoord& aValue)
{
nscoord result;
if (aValue.GetUnit() == eStyleUnit_Percent) {
result =
NSToCoordFloorClamped(mPercentageBasis * aValue.GetPercentValue());
} else {
result = aValue.GetCoordValue();
}
return result;
}
};
LengthPercentPairCalcOps ops(aStyleContext, aPresContext,
aCanStoreInRuleTree);
return ComputeCalc(aValue, ops);
}
// This is our public API for handling calc() expressions that involve
// percentages.
@ -548,8 +481,26 @@ struct ComputeComputedCalcCalcOps : public css::StyleCoordInputCalcOps,
nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
nscoord aPercentageBasis)
{
ComputeComputedCalcCalcOps ops(aPercentageBasis);
return css::ComputeCalc(aValue, ops);
nsStyleCoord::Calc *calc = aValue.GetCalcValue();
return calc->mLength +
NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
}
/* static */ nscoord
nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
nscoord aPercentageBasis)
{
switch (aCoord.GetUnit()) {
case eStyleUnit_Coord:
return aCoord.GetCoordValue();
case eStyleUnit_Percent:
return NSToCoordFloorClamped(aPercentageBasis * aCoord.GetPercentValue());
case eStyleUnit_Calc:
return ComputeComputedCalc(aCoord, aPercentageBasis);
default:
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected unit");
return 0;
}
}
/* Given an enumerated value that represents a box position, converts it to

Просмотреть файл

@ -758,6 +758,19 @@ public:
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree);
struct ComputedCalc {
nscoord mLength;
float mPercent;
ComputedCalc(nscoord aLength, float aPercent)
: mLength(aLength), mPercent(aPercent) {}
};
static ComputedCalc
SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree);
// Compute the value of an nsStyleCoord that IsCalcUnit().
// (Values that don't require aPercentageBasis should be handled
// inside nsRuleNode rather than through this API.)
@ -767,11 +780,7 @@ public:
// Compute the value of an nsStyleCoord that is either a coord, a
// percent, or a calc expression.
static nscoord ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
nscoord aPercentageBasis)
{
// ComputeComputedCalc will handle coords and percents correctly
return ComputeComputedCalc(aCoord, aPercentageBasis);
}
nscoord aPercentageBasis);
// Return whether the rule tree for which this node is the root has
// cached data such that we need to do dynamic change handling for

Просмотреть файл

@ -91,7 +91,7 @@ nsStyleCoord& nsStyleCoord::operator=(const nsStyleCoord& aCopy)
if ((eStyleUnit_Percent <= mUnit) && (mUnit < eStyleUnit_Coord)) {
mValue.mFloat = aCopy.mValue.mFloat;
}
else if (IsArrayValue()) {
else if (IsPointerValue()) {
mValue.mPointer = aCopy.mValue.mPointer;
}
else {
@ -122,12 +122,7 @@ PRBool nsStyleCoord::operator==(const nsStyleCoord& aOther) const
case eStyleUnit_Enumerated:
return mValue.mInt == aOther.mValue.mInt;
case eStyleUnit_Calc:
case eStyleUnit_Calc_Plus:
case eStyleUnit_Calc_Minus:
case eStyleUnit_Calc_Times_L:
case eStyleUnit_Calc_Times_R:
case eStyleUnit_Calc_Divided:
return *this->GetArrayValue() == *aOther.GetArrayValue();
return *this->GetCalcValue() == *aOther.GetCalcValue();
}
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected unit");
return PR_FALSE;
@ -184,15 +179,10 @@ void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
}
}
void nsStyleCoord::SetArrayValue(Array* aValue, nsStyleUnit aUnit)
void nsStyleCoord::SetCalcValue(Calc* aValue)
{
mUnit = aUnit;
if (IsArrayValue()) {
mValue.mPointer = aValue;
} else {
NS_NOTREACHED("not a pointer value");
Reset();
}
mUnit = eStyleUnit_Calc;
mValue.mPointer = aValue;
}
void nsStyleCoord::SetNormalValue()
@ -231,63 +221,6 @@ nsStyleCoord::GetAngleValueInRadians() const
}
}
PRBool
nsStyleCoord::CalcHasPercent() const
{
NS_ABORT_IF_FALSE(IsCalcUnit(), "caller should check IsCalcUnit()");
nsStyleCoord::Array *a = GetArrayValue();
for (size_t i = 0, i_end = a->Count(); i < i_end; ++i) {
const nsStyleCoord &v = a->Item(i);
if (v.GetUnit() == eStyleUnit_Percent) {
return PR_TRUE;
}
if (v.IsCalcUnit() && v.CalcHasPercent()) {
return PR_TRUE;
}
}
return PR_FALSE;
}
inline void*
nsStyleCoord::Array::operator new(size_t aSelfSize,
nsStyleContext *aAllocationContext,
size_t aItemCount) CPP_THROW_NEW
{
NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have 0 item count");
return aAllocationContext->Alloc(
aSelfSize + sizeof(nsStyleCoord) * (aItemCount - 1));
}
/* static */ nsStyleCoord::Array*
nsStyleCoord::Array::Create(nsStyleContext *aAllocationContext,
PRBool& aCanStoreInRuleTree,
size_t aCount)
{
// While it's not ideal that every time we use an array, we force it
// not to be stored in the rule tree, it's the easiest option for now.
// (This is done only because of the style-context-scoped allocation.)
aCanStoreInRuleTree = PR_FALSE;
return new(aAllocationContext, aCount) Array(aCount);
}
bool
nsStyleCoord::Array::operator==(const Array& aOther) const
{
if (Count() != aOther.Count()) {
return false;
}
for (size_t i = 0; i < mCount; ++i) {
if ((*this)[i] != aOther[i]) {
return false;
}
}
return true;
}
// used by nsStyleSides and nsStyleCorners
#define COMPARE_INDEXED_COORD(i) \
PR_BEGIN_MACRO \

Просмотреть файл

@ -60,24 +60,18 @@ enum nsStyleUnit {
eStyleUnit_Coord = 20, // (nscoord) value is twips
eStyleUnit_Integer = 30, // (int) value is simple integer
eStyleUnit_Enumerated = 32, // (int) value has enumerated meaning
// The following are all of the eCSSUnit_Calc_* types. They are weak
// pointers to a calc tree allocated by nsStyleContext::Alloc.
// NOTE: They are in the same order as the eCSSUnit_Calc_* values so
// that converting between the two sets is just addition/subtraction.
eStyleUnit_Calc = 39, // (Array*) calc() toplevel, to
// distinguish 50% from calc(50%), etc.
eStyleUnit_Calc_Plus = 40, // (Array*) + node within calc()
eStyleUnit_Calc_Minus = 41, // (Array*) - within calc
eStyleUnit_Calc_Times_L = 42, // (Array*) num * val within calc
eStyleUnit_Calc_Times_R = 43, // (Array*) val * num within calc
eStyleUnit_Calc_Divided = 44 // (Array*) / within calc
// The following are allocated types. They are weak pointers to
// values allocated by nsStyleContext::Alloc.
eStyleUnit_Calc = 40 // (Calc*) calc() toplevel; always present
// to distinguish 50% from calc(50%), etc.
};
typedef union {
PRInt32 mInt; // nscoord is a PRInt32 for now
float mFloat;
// An mPointer is a weak pointer to a value that is guaranteed to
// outlive the nsStyleCoord. In the case of nsStyleCoord::Array*, it
// outlive the nsStyleCoord. In the case of nsStyleCoord::Calc*, it
// is a pointer owned by the style context, allocated through
// nsStyleContext::Alloc (and, therefore, is never stored in the rule
// tree).
@ -94,8 +88,19 @@ typedef union {
*/
class nsStyleCoord {
public:
struct Array;
friend struct Array;
struct Calc {
// Every calc() expression evaluates to a length plus a percentage.
nscoord mLength;
float mPercent;
PRPackedBool mHasPercent; // whether there was any % syntax, even if 0
bool operator==(const Calc& aOther) const {
return mLength == aOther.mLength &&
mPercent == aOther.mPercent &&
mHasPercent == aOther.mHasPercent;
}
bool operator!=(const Calc& aOther) const { return !(*this == aOther); }
};
nsStyleCoord(nsStyleUnit aUnit = eStyleUnit_Null);
enum CoordConstructorType { CoordConstructor };
@ -119,7 +124,11 @@ public:
}
PRBool IsCalcUnit() const {
return eStyleUnit_Calc <= mUnit && mUnit <= eStyleUnit_Calc_Divided;
return eStyleUnit_Calc == mUnit;
}
PRBool IsPointerValue() const {
return IsCalcUnit();
}
PRBool IsCoordPercentCalcUnit() const {
@ -130,10 +139,8 @@ public:
// Does this calc() expression have any percentages inside it? Can be
// called only when IsCalcUnit() is true.
PRBool CalcHasPercent() const;
PRBool IsArrayValue() const {
return IsCalcUnit();
PRBool CalcHasPercent() const {
return GetCalcValue()->mHasPercent;
}
PRBool HasPercent() const {
@ -152,7 +159,7 @@ public:
float GetFactorValue() const;
float GetAngleValue() const;
double GetAngleValueInRadians() const;
Array* GetArrayValue() const;
Calc* GetCalcValue() const;
void GetUnionValue(nsStyleUnion& aValue) const;
void Reset(); // sets to null
@ -164,65 +171,13 @@ public:
void SetNormalValue();
void SetAutoValue();
void SetNoneValue();
void SetArrayValue(Array* aValue, nsStyleUnit aUnit);
void SetCalcValue(Calc* aValue);
public: // FIXME: private!
nsStyleUnit mUnit;
nsStyleUnion mValue;
};
// A fixed-size array, that, like everything else in nsStyleCoord,
// doesn't require that its destructors be called.
struct nsStyleCoord::Array {
static Array* Create(nsStyleContext *aAllocationContext,
PRBool& aCanStoreInRuleTree,
size_t aCount);
size_t Count() const { return mCount; }
nsStyleCoord& operator[](size_t aIndex) {
NS_ABORT_IF_FALSE(aIndex < mCount, "out of range");
return mArray[aIndex];
}
const nsStyleCoord& operator[](size_t aIndex) const {
NS_ABORT_IF_FALSE(aIndex < mCount, "out of range");
return mArray[aIndex];
}
// Easier to use with an Array*:
nsStyleCoord& Item(size_t aIndex) { return (*this)[aIndex]; }
const nsStyleCoord& Item(size_t aIndex) const { return (*this)[aIndex]; }
bool operator==(const Array& aOther) const;
bool operator!=(const Array& aOther) const {
return !(*this == aOther);
}
private:
inline void* operator new(size_t aSelfSize,
nsStyleContext *aAllocationContext,
size_t aItemCount) CPP_THROW_NEW;
Array(size_t aCount)
: mCount(aCount)
{
// Initialize all entries not in the class.
for (size_t i = 1; i < aCount; ++i) {
new (mArray + i) nsStyleCoord();
}
}
size_t mCount;
nsStyleCoord mArray[1]; // for alignment, have the first element in the class
// not to be implemented
Array(const Array& aOther);
Array& operator=(const Array& aOther);
~Array();
};
/**
* Class that represents a set of top/right/bottom/left nsStyleCoords.
* This is commonly used to hold the widths of the borders, margins,
@ -308,7 +263,7 @@ inline nsStyleCoord::nsStyleCoord(const nsStyleCoord& aCopy)
if ((eStyleUnit_Percent <= mUnit) && (mUnit < eStyleUnit_Coord)) {
mValue.mFloat = aCopy.mValue.mFloat;
}
else if (IsArrayValue()) {
else if (IsPointerValue()) {
mValue.mPointer = aCopy.mValue.mPointer;
}
else {
@ -375,11 +330,11 @@ inline float nsStyleCoord::GetAngleValue() const
return 0.0f;
}
inline nsStyleCoord::Array* nsStyleCoord::GetArrayValue() const
inline nsStyleCoord::Calc* nsStyleCoord::GetCalcValue() const
{
NS_ASSERTION(IsArrayValue(), "not a pointer value");
if (IsArrayValue()) {
return static_cast<Array*>(mValue.mPointer);
NS_ASSERTION(IsCalcUnit(), "not a pointer value");
if (IsCalcUnit()) {
return static_cast<Calc*>(mValue.mPointer);
}
return nsnull;
}

Просмотреть файл

@ -229,81 +229,6 @@ static nscoord CalcLength(const nsCSSValue &aValue,
aCanStoreInRuleTree);
}
struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps
{
struct result_type {
nscoord mLength;
float mPercent;
result_type(nscoord aLength, float aPercent)
: mLength(aLength), mPercent(aPercent) {}
};
LengthPercentPairCalcOps(nsStyleContext* aContext,
nsPresContext* aPresContext,
PRBool& aCanStoreInRuleTree)
: mContext(aContext),
mPresContext(aPresContext),
mCanStoreInRuleTree(aCanStoreInRuleTree) {}
nsStyleContext* mContext;
nsPresContext* mPresContext;
PRBool& mCanStoreInRuleTree;
result_type ComputeLeafValue(const nsCSSValue& aValue)
{
if (aValue.GetUnit() == eCSSUnit_Percent) {
return result_type(0, aValue.GetPercentValue());
} else {
return result_type(CalcLength(aValue, mContext, mPresContext,
mCanStoreInRuleTree),
0.0f);
}
}
result_type
MergeAdditive(nsCSSUnit aCalcFunction,
result_type aValue1, result_type aValue2)
{
if (aCalcFunction == eCSSUnit_Calc_Plus) {
return result_type(NSCoordSaturatingAdd(aValue1.mLength,
aValue2.mLength),
aValue1.mPercent + aValue2.mPercent);
}
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Minus,
"min() and max() are not allowed in calc() on "
"transform");
return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
aValue2.mLength, 0),
aValue1.mPercent - aValue2.mPercent);
}
result_type
MergeMultiplicativeL(nsCSSUnit aCalcFunction,
float aValue1, result_type aValue2)
{
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_L,
"unexpected unit");
return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
aValue1 * aValue2.mPercent);
}
result_type
MergeMultiplicativeR(nsCSSUnit aCalcFunction,
result_type aValue1, float aValue2)
{
NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_R ||
aCalcFunction == eCSSUnit_Calc_Divided,
"unexpected unit");
if (aCalcFunction == eCSSUnit_Calc_Divided) {
aValue2 = 1.0f / aValue2;
}
return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
aValue1.mPercent * aValue2);
}
};
static void ProcessTranslatePart(nscoord& aOffset, float& aPercent,
const nsCSSValue& aValue,
nsStyleContext* aContext,
@ -313,9 +238,9 @@ static void ProcessTranslatePart(nscoord& aOffset, float& aPercent,
if (aValue.GetUnit() == eCSSUnit_Percent) {
aPercent = aValue.GetPercentValue();
} else if (aValue.IsCalcUnit()) {
LengthPercentPairCalcOps ops(aContext, aPresContext, aCanStoreInRuleTree);
LengthPercentPairCalcOps::result_type result =
css::ComputeCalc(aValue, ops);
nsRuleNode::ComputedCalc result =
nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
aCanStoreInRuleTree);
aPercent = result.mPercent;
aOffset = result.mLength;
} else {