Change storage of background-size and background-position to allow percentages and lengths. (Bug 594934) r=bzbarsky a=blocking2.0:betaN

This commit is contained in:
L. David Baron 2010-09-15 08:11:26 -07:00
parent c5db5e47e4
commit 04ad76518f
6 changed files with 132 additions and 120 deletions

View File

@ -881,23 +881,17 @@ ComputeBackgroundAnchorPoint(const nsStyleBackground::Layer& aLayer,
nsPoint* aTopLeft,
nsPoint* aAnchorPoint)
{
if (!aLayer.mPosition.mXIsPercent) {
aTopLeft->x = aAnchorPoint->x = aLayer.mPosition.mXPosition.mCoord;
}
else {
double percent = aLayer.mPosition.mXPosition.mFloat;
aAnchorPoint->x = NSToCoordRound(percent*aOriginBounds.width);
aTopLeft->x = NSToCoordRound(percent*(aOriginBounds.width - aImageSize.width));
}
double percentX = aLayer.mPosition.mXPosition.mPercent;
nscoord lengthX = aLayer.mPosition.mXPosition.mLength;
aAnchorPoint->x = lengthX + NSToCoordRound(percentX*aOriginBounds.width);
aTopLeft->x = lengthX +
NSToCoordRound(percentX*(aOriginBounds.width - aImageSize.width));
if (!aLayer.mPosition.mYIsPercent) {
aTopLeft->y = aAnchorPoint->y = aLayer.mPosition.mYPosition.mCoord;
}
else {
double percent = aLayer.mPosition.mYPosition.mFloat;
aAnchorPoint->y = NSToCoordRound(percent*aOriginBounds.height);
aTopLeft->y = NSToCoordRound(percent*(aOriginBounds.height - aImageSize.height));
}
double percentY = aLayer.mPosition.mYPosition.mPercent;
nscoord lengthY = aLayer.mPosition.mYPosition.mLength;
aAnchorPoint->y = lengthY + NSToCoordRound(percentY*aOriginBounds.height);
aTopLeft->y = lengthY +
NSToCoordRound(percentY*(aOriginBounds.height - aImageSize.height));
}
nsIFrame*
@ -2303,15 +2297,15 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
}
static inline float
ScaleDimension(nsStyleBackground::Size::Dimension aDimension,
ScaleDimension(const nsStyleBackground::Size::Dimension& aDimension,
PRUint8 aType,
nscoord aLength, nscoord aAvailLength)
{
switch (aType) {
case nsStyleBackground::Size::ePercentage:
return double(aDimension.mFloat) * (double(aAvailLength) / double(aLength));
case nsStyleBackground::Size::eLength:
return double(aDimension.mCoord) / double(aLength);
case nsStyleBackground::Size::eLengthPercentage:
return (double(aDimension.mPercent) * double(aAvailLength) +
double(aDimension.mLength)) /
double(aLength);
default:
NS_ABORT_IF_FALSE(PR_FALSE, "bad aDimension.mType");
return 1.0f;

View File

@ -1719,16 +1719,20 @@ nsComputedDOMStyle::DoGetBackgroundPosition(nsIDOMCSSValue** aValue)
const nsStyleBackground::Position &pos = bg->mLayers[i].mPosition;
if (pos.mXIsPercent) {
valX->SetPercent(pos.mXPosition.mFloat);
if (pos.mXPosition.mLength != 0) {
NS_ABORT_IF_FALSE(pos.mXPosition.mPercent == 0.0f,
"can't have both until calc() implemented");
valX->SetAppUnits(pos.mXPosition.mLength);
} else {
valX->SetAppUnits(pos.mXPosition.mCoord);
valX->SetPercent(pos.mXPosition.mPercent);
}
if (pos.mYIsPercent) {
valY->SetPercent(pos.mYPosition.mFloat);
if (pos.mYPosition.mLength != 0) {
NS_ABORT_IF_FALSE(pos.mYPosition.mPercent == 0.0f,
"can't have both until calc() implemented");
valY->SetAppUnits(pos.mYPosition.mLength);
} else {
valY->SetAppUnits(pos.mYPosition.mCoord);
valY->SetPercent(pos.mYPosition.mPercent);
}
}
@ -1796,22 +1800,32 @@ nsComputedDOMStyle::DoGetMozBackgroundSize(nsIDOMCSSValue** aValue)
if (size.mWidthType == nsStyleBackground::Size::eAuto) {
valX->SetIdent(eCSSKeyword_auto);
} else if (size.mWidthType == nsStyleBackground::Size::ePercentage) {
valX->SetPercent(size.mWidth.mFloat);
} else {
NS_ABORT_IF_FALSE(size.mWidthType == nsStyleBackground::Size::eLength,
NS_ABORT_IF_FALSE(size.mWidthType ==
nsStyleBackground::Size::eLengthPercentage,
"bad mWidthType");
valX->SetAppUnits(size.mWidth.mCoord);
if (size.mWidth.mLength != 0) {
NS_ABORT_IF_FALSE(size.mWidth.mPercent == 0.0f,
"can't have both until calc() implemented");
valX->SetAppUnits(size.mWidth.mLength);
} else {
valX->SetPercent(size.mWidth.mPercent);
}
}
if (size.mHeightType == nsStyleBackground::Size::eAuto) {
valY->SetIdent(eCSSKeyword_auto);
} else if (size.mHeightType == nsStyleBackground::Size::ePercentage) {
valY->SetPercent(size.mHeight.mFloat);
} else {
NS_ABORT_IF_FALSE(size.mHeightType == nsStyleBackground::Size::eLength,
NS_ABORT_IF_FALSE(size.mHeightType ==
nsStyleBackground::Size::eLengthPercentage,
"bad mHeightType");
valY->SetAppUnits(size.mHeight.mCoord);
if (size.mHeight.mLength != 0) {
NS_ABORT_IF_FALSE(size.mHeight.mPercent == 0.0f,
"can't have both until calc() implemented");
valY->SetAppUnits(size.mHeight.mLength);
} else {
valY->SetPercent(size.mHeight.mPercent);
}
}
break;
}

View File

@ -4461,16 +4461,13 @@ struct BackgroundPositionAxis {
nsCSSValue nsCSSValuePairList::*specified;
nsStyleBackground::Position::PositionCoord
nsStyleBackground::Position::*result;
PRPackedBool nsStyleBackground::Position::*isPercent;
};
static const BackgroundPositionAxis gBGPosAxes[] = {
{ &nsCSSValuePairList::mXValue,
&nsStyleBackground::Position::mXPosition,
&nsStyleBackground::Position::mXIsPercent },
&nsStyleBackground::Position::mXPosition },
{ &nsCSSValuePairList::mYValue,
&nsStyleBackground::Position::mYPosition,
&nsStyleBackground::Position::mYIsPercent }
&nsStyleBackground::Position::mYPosition }
};
NS_SPECIALIZE_TEMPLATE
@ -4487,19 +4484,19 @@ struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Position>
axis != axis_end; ++axis) {
const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
if (eCSSUnit_Percent == specified.GetUnit()) {
(position.*(axis->result)).mFloat = specified.GetPercentValue();
position.*(axis->isPercent) = PR_TRUE;
(position.*(axis->result)).mLength = 0;
(position.*(axis->result)).mPercent = specified.GetPercentValue();
}
else if (specified.IsLengthUnit()) {
(position.*(axis->result)).mCoord =
(position.*(axis->result)).mLength =
CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
position.*(axis->isPercent) = PR_FALSE;
(position.*(axis->result)).mPercent = 0.0f;
}
else if (eCSSUnit_Enumerated == specified.GetUnit()) {
(position.*(axis->result)).mFloat =
(position.*(axis->result)).mLength = 0;
(position.*(axis->result)).mPercent =
GetFloatFromBoxPosition(specified.GetIntValue());
position.*(axis->isPercent) = PR_TRUE;
} else {
NS_NOTREACHED("unexpected unit");
}
@ -4569,15 +4566,17 @@ struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Size>
size.*(axis->type) = size.mWidthType;
}
else if (eCSSUnit_Percent == specified.GetUnit()) {
(size.*(axis->result)).mFloat = specified.GetPercentValue();
size.*(axis->type) = nsStyleBackground::Size::ePercentage;
(size.*(axis->result)).mLength = 0;
(size.*(axis->result)).mPercent = specified.GetPercentValue();
size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
}
else {
NS_ABORT_IF_FALSE(specified.IsLengthUnit(), "unexpected unit");
(size.*(axis->result)).mCoord =
(size.*(axis->result)).mLength =
CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
aCanStoreInRuleTree);
size.*(axis->type) = nsStyleBackground::Size::eLength;
(size.*(axis->result)).mPercent = 0.0f;
size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
}
}

View File

@ -2182,15 +2182,19 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
resultTail = &item->mNext;
const nsStyleBackground::Position &pos = bg->mLayers[i].mPosition;
if (pos.mXIsPercent) {
item->mXValue.SetPercentValue(pos.mXPosition.mFloat);
if (pos.mXPosition.mLength == 0) {
item->mXValue.SetPercentValue(pos.mXPosition.mPercent);
} else {
nscoordToCSSValue(pos.mXPosition.mCoord, item->mXValue);
NS_ABORT_IF_FALSE(pos.mXPosition.mPercent == 0.0f,
"calc() isn't supported yet");
nscoordToCSSValue(pos.mXPosition.mLength, item->mXValue);
}
if (pos.mYIsPercent) {
item->mYValue.SetPercentValue(pos.mYPosition.mFloat);
if (pos.mYPosition.mLength == 0) {
item->mYValue.SetPercentValue(pos.mYPosition.mPercent);
} else {
nscoordToCSSValue(pos.mYPosition.mCoord, item->mYValue);
NS_ABORT_IF_FALSE(pos.mYPosition.mPercent == 0.0f,
"calc() isn't supported yet");
nscoordToCSSValue(pos.mYPosition.mLength, item->mYValue);
}
}
@ -2216,14 +2220,17 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
item->mXValue.SetIntValue(size.mWidthType,
eCSSUnit_Enumerated);
break;
case nsStyleBackground::Size::ePercentage:
item->mXValue.SetPercentValue(size.mWidth.mFloat);
break;
case nsStyleBackground::Size::eAuto:
item->mXValue.SetAutoValue();
break;
case nsStyleBackground::Size::eLength:
nscoordToCSSValue(size.mWidth.mCoord, item->mXValue);
case nsStyleBackground::Size::eLengthPercentage:
if (size.mWidth.mLength == 0) {
item->mXValue.SetPercentValue(size.mWidth.mPercent);
} else {
NS_ABORT_IF_FALSE(size.mWidth.mPercent == 0.0f,
"calc() isn't supported yet");
nscoordToCSSValue(size.mWidth.mLength, item->mXValue);
}
break;
}
@ -2232,14 +2239,17 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
case nsStyleBackground::Size::eCover:
// leave it null
break;
case nsStyleBackground::Size::ePercentage:
item->mYValue.SetPercentValue(size.mHeight.mFloat);
break;
case nsStyleBackground::Size::eAuto:
item->mYValue.SetAutoValue();
break;
case nsStyleBackground::Size::eLength:
nscoordToCSSValue(size.mHeight.mCoord, item->mYValue);
case nsStyleBackground::Size::eLengthPercentage:
if (size.mHeight.mLength == 0) {
item->mYValue.SetPercentValue(size.mHeight.mPercent);
} else {
NS_ABORT_IF_FALSE(size.mHeight.mPercent == 0.0f,
"calc() isn't supported yet");
nscoordToCSSValue(size.mHeight.mLength, item->mYValue);
}
break;
}
}

View File

@ -1815,10 +1815,10 @@ PRBool nsStyleBackground::IsTransparent() const
void
nsStyleBackground::Position::SetInitialValues()
{
mXPosition.mFloat = 0.0f;
mYPosition.mFloat = 0.0f;
mXIsPercent = PR_TRUE;
mYIsPercent = PR_TRUE;
mXPosition.mPercent = 0.0f;
mXPosition.mLength = 0;
mYPosition.mPercent = 0.0f;
mYPosition.mLength = 0;
}
void
@ -1827,7 +1827,7 @@ nsStyleBackground::Size::SetInitialValues()
mWidthType = mHeightType = eAuto;
}
PRBool
bool
nsStyleBackground::Size::operator==(const Size& aOther) const
{
NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT,
@ -1839,26 +1839,10 @@ nsStyleBackground::Size::operator==(const Size& aOther) const
NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT,
"bad mHeightType for aOther");
if (mWidthType != aOther.mWidthType || mHeightType != aOther.mHeightType)
return PR_FALSE;
if (mWidthType == ePercentage) {
if (mWidth.mFloat != aOther.mWidth.mFloat)
return PR_FALSE;
} else if (mWidthType == eLength) {
if (mWidth.mCoord != aOther.mWidth.mCoord)
return PR_FALSE;
}
if (mHeightType == ePercentage) {
if (mHeight.mFloat != aOther.mHeight.mFloat)
return PR_FALSE;
} else if (mHeightType == eLength) {
if (mHeight.mCoord != aOther.mHeight.mCoord)
return PR_FALSE;
}
return PR_TRUE;
return mWidthType == aOther.mWidthType &&
mHeightType == aOther.mHeightType &&
(mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
(mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
}
nsStyleBackground::Layer::Layer()

View File

@ -349,12 +349,18 @@ struct nsStyleBackground {
struct Position;
friend struct Position;
struct Position {
typedef union {
nscoord mCoord; // for lengths
float mFloat; // for percents
} PositionCoord;
struct PositionCoord {
// A 'background-position' can be a linear combination of length
// and percent (thanks to calc(), which can combine them).
nscoord mLength;
float mPercent;
bool operator==(const PositionCoord& aOther) const
{ return mLength == aOther.mLength && mPercent == aOther.mPercent; }
bool operator!=(const PositionCoord& aOther) const
{ return !(*this == aOther); }
};
PositionCoord mXPosition, mYPosition;
PRPackedBool mXIsPercent, mYIsPercent;
// Initialize nothing
Position() {}
@ -365,19 +371,14 @@ struct nsStyleBackground {
// True if the effective background image position described by this depends
// on the size of the corresponding frame.
PRBool DependsOnFrameSize() const {
return (mXIsPercent && mXPosition.mFloat != 0.0f) ||
(mYIsPercent && mYPosition.mFloat != 0.0f);
return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
}
PRBool operator==(const Position& aOther) const {
return mXIsPercent == aOther.mXIsPercent &&
(mXIsPercent ? (mXPosition.mFloat == aOther.mXPosition.mFloat)
: (mXPosition.mCoord == aOther.mXPosition.mCoord)) &&
mYIsPercent == aOther.mYIsPercent &&
(mYIsPercent ? (mYPosition.mFloat == aOther.mYPosition.mFloat)
: (mYPosition.mCoord == aOther.mYPosition.mCoord));
bool operator==(const Position& aOther) const {
return mXPosition == aOther.mXPosition &&
mYPosition == aOther.mYPosition;
}
PRBool operator!=(const Position& aOther) const {
bool operator!=(const Position& aOther) const {
return !(*this == aOther);
}
};
@ -385,25 +386,31 @@ struct nsStyleBackground {
struct Size;
friend struct Size;
struct Size {
typedef union {
nscoord mCoord; // for lengths
float mFloat; // for percents
} Dimension;
struct Dimension {
// A 'background-size' can be a linear combination of length
// and percent (thanks to calc(), which can combine them).
nscoord mLength;
float mPercent;
bool operator==(const Dimension& aOther) const
{ return mLength == aOther.mLength && mPercent == aOther.mPercent; }
bool operator!=(const Dimension& aOther) const
{ return !(*this == aOther); }
};
Dimension mWidth, mHeight;
// Dimension types which might change how a layer is painted when the
// corresponding frame's dimensions change *must* precede all dimension
// types which are agnostic to frame size; see DependsOnFrameSize below.
// Except for eLengthPercentage, Dimension types which might change
// how a layer is painted when the corresponding frame's dimensions
// change *must* precede all dimension types which are agnostic to
// frame size; see DependsOnFrameSize below.
enum DimensionType {
// If one of mWidth and mHeight is eContain or eCover, then both are.
// Also, these two values must equal the corresponding values in
// kBackgroundSizeKTable.
eContain, eCover,
ePercentage,
eAuto,
eLength,
eLengthPercentage,
eDimensionType_COUNT
};
PRUint8 mWidthType, mHeightType;
@ -416,9 +423,13 @@ struct nsStyleBackground {
// -moz-element also depends on the frame size when the dimensions
// are 'auto' since it could be an SVG gradient or pattern which
// behaves exactly like a CSS gradient.
PRBool DependsOnFrameSize(nsStyleImageType aType) const {
bool DependsOnFrameSize(nsStyleImageType aType) const {
if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
(mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
return true;
}
if (aType == eStyleImageType_Image) {
return mWidthType <= ePercentage || mHeightType <= ePercentage;
return mWidthType <= eCover || mHeightType <= eCover;
} else {
NS_ABORT_IF_FALSE(aType == eStyleImageType_Gradient ||
aType == eStyleImageType_Element,
@ -433,8 +444,8 @@ struct nsStyleBackground {
// Initialize to initial values
void SetInitialValues();
PRBool operator==(const Size& aOther) const;
PRBool operator!=(const Size& aOther) const {
bool operator==(const Size& aOther) const;
bool operator!=(const Size& aOther) const {
return !(*this == aOther);
}
};