Allow mixing length and percentage values with keyword values for the background-position property, which is now allowed per section 14.2.1 of CSS 2.1
r+sr=dbaron
a=asa
This commit is contained in:
caillon%redhat.com 2004-04-10 05:08:02 +00:00
Родитель 5bef1e18e0
Коммит 626eea0b43
2 изменённых файлов: 196 добавлений и 190 удалений

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

@ -3976,8 +3976,8 @@ PRBool CSSParserImpl::ParseProperty(nsresult& aErrorCode,
#define BG_BOTTOM 0x04
#define BG_LEFT 0x08
#define BG_RIGHT 0x10
#define BG_CENTER1 0x20
#define BG_CENTER2 0x40
#define BG_CTB (BG_CENTER | BG_TOP | BG_BOTTOM)
#define BG_CLR (BG_CENTER | BG_LEFT | BG_RIGHT)
// Note: Don't change this table unless you update
// parseBackgroundPosition!
@ -4442,6 +4442,30 @@ PRBool CSSParserImpl::ParseAzimuth(nsresult& aErrorCode, nsCSSValue& aValue)
return PR_FALSE;
}
static nsCSSValue
BackgroundPositionMaskToCSSValue(PRInt32 aMask, PRBool isX)
{
PRInt32 pct = 50;
if (isX) {
if (aMask & BG_LEFT) {
pct = 0;
}
else if (aMask & BG_RIGHT) {
pct = 100;
}
}
else {
if (aMask & BG_TOP) {
pct = 0;
}
else if (aMask & BG_BOTTOM) {
pct = 100;
}
}
return nsCSSValue(pct, eCSSUnit_Enumerated);
}
PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
{
const PRInt32 numProps = 6;
@ -4461,36 +4485,11 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
}
if (0 != (found & 0x30)) { // found one or more position values, validate them
if (0 == (found & 0x20)) { // x value only
if (0 == (found & 0x20)) {
if (eCSSUnit_Enumerated == values[4].GetUnit()) {
switch (values[4].GetIntValue()) {
case BG_CENTER:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_TOP:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_BOTTOM:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(100, eCSSUnit_Enumerated);
break;
case BG_LEFT:
values[4].SetIntValue(0, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_RIGHT:
values[4].SetIntValue(100, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
}
}
else if (eCSSUnit_Inherit == values[4].GetUnit()) {
values[5].SetInheritValue();
}
else if (eCSSUnit_Initial == values[4].GetUnit()) {
values[5].SetInitialValue();
PRInt32 mask = values[4].GetIntValue();
values[4] = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
values[5] = BackgroundPositionMaskToCSSValue(mask, PR_FALSE);
}
else {
values[5].SetPercentValue(0.5f);
@ -4499,9 +4498,9 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
else { // both x & y values
nsCSSUnit xUnit = values[4].GetUnit();
nsCSSUnit yUnit = values[5].GetUnit();
if (eCSSUnit_Enumerated == xUnit) { // if one is enumerated, both must be
if (eCSSUnit_Enumerated == xUnit) {
PRInt32 xValue = values[4].GetIntValue();
if (eCSSUnit_Enumerated == yUnit) {
PRInt32 xValue = values[4].GetIntValue();
PRInt32 yValue = values[5].GetIntValue();
if (0 != (xValue & (BG_LEFT | BG_RIGHT)) && // x is really an x value
0 != (yValue & (BG_LEFT | BG_RIGHT))) { // y is also an x value
@ -4517,40 +4516,27 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
xValue = yValue;
yValue = holdXValue;
}
switch (xValue) {
case BG_LEFT:
values[4].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_CENTER:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_RIGHT:
values[4].SetIntValue(100, eCSSUnit_Enumerated);
break;
default:
NS_ERROR("bad x value");
}
switch (yValue) {
case BG_TOP:
values[5].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_CENTER:
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_BOTTOM:
values[5].SetIntValue(100, eCSSUnit_Enumerated);
break;
default:
NS_ERROR("bad y value");
}
NS_ASSERTION(xValue & BG_CLR, "bad x value");
NS_ASSERTION(yValue & BG_CTB, "bad y value");
values[4] = BackgroundPositionMaskToCSSValue(xValue, PR_TRUE);
values[5] = BackgroundPositionMaskToCSSValue(yValue, PR_FALSE);
}
else {
return PR_FALSE;
if (!(xValue & BG_CLR)) {
// The first keyword can only be 'center', 'left', or 'right'
return PR_FALSE;
}
values[4] = BackgroundPositionMaskToCSSValue(xValue, PR_TRUE);
}
}
else {
if (eCSSUnit_Enumerated == yUnit) {
return PR_FALSE;
PRInt32 yValue = values[5].GetIntValue();
if (!(yValue & BG_CTB)) {
// The second keyword can only be 'center', 'top', or 'bottom'
return PR_FALSE;
}
values[5] = BackgroundPositionMaskToCSSValue(yValue, PR_FALSE);
}
}
}
@ -4598,8 +4584,8 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
{
// First try a number or a length value
nsCSSValue xValue;
// First try a percentage or a length value
nsCSSValue xValue, yValue;
if (ParseVariant(aErrorCode, xValue, VARIANT_HLP, nsnull)) {
if (eCSSUnit_Inherit == xValue.GetUnit() ||
eCSSUnit_Initial == xValue.GetUnit()) { // both are inherited or both are set to initial
@ -4610,8 +4596,8 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
}
return PR_FALSE;
}
// We have one number/length. Get the optional second number/length.
nsCSSValue yValue;
// We have one percentage/length. Get the optional second
// percentage/length/keyword.
if (ParseVariant(aErrorCode, yValue, VARIANT_LP, nsnull)) {
// We have two numbers
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
@ -4622,8 +4608,23 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
return PR_FALSE;
}
// We have one number which is the x position. Create an value for
// the vertical position which is of value 50%
if (ParseEnum(aErrorCode, yValue, kBackgroundXYPositionKTable)) {
PRInt32 yVal = yValue.GetIntValue();
if (!(yVal & BG_CTB)) {
// The second keyword can only be 'center', 'top', or 'bottom'
return PR_FALSE;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
yValue = BackgroundPositionMaskToCSSValue(yVal, PR_FALSE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;
}
// If only one percentage or length value is given, it sets the
// horizontal position only, and the vertical position will be 50%.
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, nsCSSValue(0.5f, eCSSUnit_Percent));
@ -4639,22 +4640,34 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
// any duplicate keywords other than center. We try to get two
// keywords but it's okay if there is only one.
PRInt32 mask = 0;
PRInt32 centerBit = BG_CENTER1;
for (PRInt32 i = 0; i < 2; i++) {
if (PR_FALSE == ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
break;
}
if (ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
PRInt32 bit = xValue.GetIntValue();
if (BG_CENTER == bit) {
// Special hack for center bits: We can have two of them
mask |= centerBit;
centerBit <<= 1;
continue;
} else if ((mask & bit) != 0) {
// no duplicate values allowed (other than center)
return PR_FALSE;
}
mask |= bit;
if (ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
bit = xValue.GetIntValue();
if (mask & (bit & ~BG_CENTER)) {
// Only the 'center' keyword can be duplicated.
return PR_FALSE;
}
mask |= bit;
}
else {
// Only one keyword. See if we have a length or percentage.
if (ParseVariant(aErrorCode, yValue, VARIANT_LP, nsnull)) {
if (!(mask & BG_CLR)) {
// The first keyword can only be 'center', 'left', or 'right'
return PR_FALSE;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
xValue = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;
}
}
}
// Check for bad input. Bad input consists of no matching keywords,
@ -4664,22 +4677,12 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
return PR_FALSE;
}
// Map good input
PRInt32 xEnumValue = 50;
if ((mask & (BG_LEFT | BG_RIGHT)) != 0) {
// We have an x value
xEnumValue = ((mask & BG_LEFT) != 0) ? 0 : 100;
}
PRInt32 yEnumValue = 50;
if ((mask & (BG_TOP | BG_BOTTOM)) != 0) {
// We have a y value
yEnumValue = ((mask & BG_TOP) != 0) ? 0 : 100;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
// Create style values
AppendValue(eCSSProperty_background_x_position, nsCSSValue(xEnumValue, eCSSUnit_Enumerated));
AppendValue(eCSSProperty_background_y_position, nsCSSValue(yEnumValue, eCSSUnit_Enumerated));
xValue = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
yValue = BackgroundPositionMaskToCSSValue(mask, PR_FALSE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;

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

@ -3976,8 +3976,8 @@ PRBool CSSParserImpl::ParseProperty(nsresult& aErrorCode,
#define BG_BOTTOM 0x04
#define BG_LEFT 0x08
#define BG_RIGHT 0x10
#define BG_CENTER1 0x20
#define BG_CENTER2 0x40
#define BG_CTB (BG_CENTER | BG_TOP | BG_BOTTOM)
#define BG_CLR (BG_CENTER | BG_LEFT | BG_RIGHT)
// Note: Don't change this table unless you update
// parseBackgroundPosition!
@ -4442,6 +4442,30 @@ PRBool CSSParserImpl::ParseAzimuth(nsresult& aErrorCode, nsCSSValue& aValue)
return PR_FALSE;
}
static nsCSSValue
BackgroundPositionMaskToCSSValue(PRInt32 aMask, PRBool isX)
{
PRInt32 pct = 50;
if (isX) {
if (aMask & BG_LEFT) {
pct = 0;
}
else if (aMask & BG_RIGHT) {
pct = 100;
}
}
else {
if (aMask & BG_TOP) {
pct = 0;
}
else if (aMask & BG_BOTTOM) {
pct = 100;
}
}
return nsCSSValue(pct, eCSSUnit_Enumerated);
}
PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
{
const PRInt32 numProps = 6;
@ -4461,36 +4485,11 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
}
if (0 != (found & 0x30)) { // found one or more position values, validate them
if (0 == (found & 0x20)) { // x value only
if (0 == (found & 0x20)) {
if (eCSSUnit_Enumerated == values[4].GetUnit()) {
switch (values[4].GetIntValue()) {
case BG_CENTER:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_TOP:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_BOTTOM:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
values[5].SetIntValue(100, eCSSUnit_Enumerated);
break;
case BG_LEFT:
values[4].SetIntValue(0, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_RIGHT:
values[4].SetIntValue(100, eCSSUnit_Enumerated);
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
}
}
else if (eCSSUnit_Inherit == values[4].GetUnit()) {
values[5].SetInheritValue();
}
else if (eCSSUnit_Initial == values[4].GetUnit()) {
values[5].SetInitialValue();
PRInt32 mask = values[4].GetIntValue();
values[4] = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
values[5] = BackgroundPositionMaskToCSSValue(mask, PR_FALSE);
}
else {
values[5].SetPercentValue(0.5f);
@ -4499,9 +4498,9 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
else { // both x & y values
nsCSSUnit xUnit = values[4].GetUnit();
nsCSSUnit yUnit = values[5].GetUnit();
if (eCSSUnit_Enumerated == xUnit) { // if one is enumerated, both must be
if (eCSSUnit_Enumerated == xUnit) {
PRInt32 xValue = values[4].GetIntValue();
if (eCSSUnit_Enumerated == yUnit) {
PRInt32 xValue = values[4].GetIntValue();
PRInt32 yValue = values[5].GetIntValue();
if (0 != (xValue & (BG_LEFT | BG_RIGHT)) && // x is really an x value
0 != (yValue & (BG_LEFT | BG_RIGHT))) { // y is also an x value
@ -4517,40 +4516,27 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
xValue = yValue;
yValue = holdXValue;
}
switch (xValue) {
case BG_LEFT:
values[4].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_CENTER:
values[4].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_RIGHT:
values[4].SetIntValue(100, eCSSUnit_Enumerated);
break;
default:
NS_ERROR("bad x value");
}
switch (yValue) {
case BG_TOP:
values[5].SetIntValue(0, eCSSUnit_Enumerated);
break;
case BG_CENTER:
values[5].SetIntValue(50, eCSSUnit_Enumerated);
break;
case BG_BOTTOM:
values[5].SetIntValue(100, eCSSUnit_Enumerated);
break;
default:
NS_ERROR("bad y value");
}
NS_ASSERTION(xValue & BG_CLR, "bad x value");
NS_ASSERTION(yValue & BG_CTB, "bad y value");
values[4] = BackgroundPositionMaskToCSSValue(xValue, PR_TRUE);
values[5] = BackgroundPositionMaskToCSSValue(yValue, PR_FALSE);
}
else {
return PR_FALSE;
if (!(xValue & BG_CLR)) {
// The first keyword can only be 'center', 'left', or 'right'
return PR_FALSE;
}
values[4] = BackgroundPositionMaskToCSSValue(xValue, PR_TRUE);
}
}
else {
if (eCSSUnit_Enumerated == yUnit) {
return PR_FALSE;
PRInt32 yValue = values[5].GetIntValue();
if (!(yValue & BG_CTB)) {
// The second keyword can only be 'center', 'top', or 'bottom'
return PR_FALSE;
}
values[5] = BackgroundPositionMaskToCSSValue(yValue, PR_FALSE);
}
}
}
@ -4598,8 +4584,8 @@ PRBool CSSParserImpl::ParseBackground(nsresult& aErrorCode)
PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
{
// First try a number or a length value
nsCSSValue xValue;
// First try a percentage or a length value
nsCSSValue xValue, yValue;
if (ParseVariant(aErrorCode, xValue, VARIANT_HLP, nsnull)) {
if (eCSSUnit_Inherit == xValue.GetUnit() ||
eCSSUnit_Initial == xValue.GetUnit()) { // both are inherited or both are set to initial
@ -4610,8 +4596,8 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
}
return PR_FALSE;
}
// We have one number/length. Get the optional second number/length.
nsCSSValue yValue;
// We have one percentage/length. Get the optional second
// percentage/length/keyword.
if (ParseVariant(aErrorCode, yValue, VARIANT_LP, nsnull)) {
// We have two numbers
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
@ -4622,8 +4608,23 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
return PR_FALSE;
}
// We have one number which is the x position. Create an value for
// the vertical position which is of value 50%
if (ParseEnum(aErrorCode, yValue, kBackgroundXYPositionKTable)) {
PRInt32 yVal = yValue.GetIntValue();
if (!(yVal & BG_CTB)) {
// The second keyword can only be 'center', 'top', or 'bottom'
return PR_FALSE;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
yValue = BackgroundPositionMaskToCSSValue(yVal, PR_FALSE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;
}
// If only one percentage or length value is given, it sets the
// horizontal position only, and the vertical position will be 50%.
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, nsCSSValue(0.5f, eCSSUnit_Percent));
@ -4639,22 +4640,34 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
// any duplicate keywords other than center. We try to get two
// keywords but it's okay if there is only one.
PRInt32 mask = 0;
PRInt32 centerBit = BG_CENTER1;
for (PRInt32 i = 0; i < 2; i++) {
if (PR_FALSE == ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
break;
}
if (ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
PRInt32 bit = xValue.GetIntValue();
if (BG_CENTER == bit) {
// Special hack for center bits: We can have two of them
mask |= centerBit;
centerBit <<= 1;
continue;
} else if ((mask & bit) != 0) {
// no duplicate values allowed (other than center)
return PR_FALSE;
}
mask |= bit;
if (ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {
bit = xValue.GetIntValue();
if (mask & (bit & ~BG_CENTER)) {
// Only the 'center' keyword can be duplicated.
return PR_FALSE;
}
mask |= bit;
}
else {
// Only one keyword. See if we have a length or percentage.
if (ParseVariant(aErrorCode, yValue, VARIANT_LP, nsnull)) {
if (!(mask & BG_CLR)) {
// The first keyword can only be 'center', 'left', or 'right'
return PR_FALSE;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
xValue = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;
}
}
}
// Check for bad input. Bad input consists of no matching keywords,
@ -4664,22 +4677,12 @@ PRBool CSSParserImpl::ParseBackgroundPosition(nsresult& aErrorCode)
return PR_FALSE;
}
// Map good input
PRInt32 xEnumValue = 50;
if ((mask & (BG_LEFT | BG_RIGHT)) != 0) {
// We have an x value
xEnumValue = ((mask & BG_LEFT) != 0) ? 0 : 100;
}
PRInt32 yEnumValue = 50;
if ((mask & (BG_TOP | BG_BOTTOM)) != 0) {
// We have a y value
yEnumValue = ((mask & BG_TOP) != 0) ? 0 : 100;
}
if (ExpectEndProperty(aErrorCode, PR_TRUE)) {
// Create style values
AppendValue(eCSSProperty_background_x_position, nsCSSValue(xEnumValue, eCSSUnit_Enumerated));
AppendValue(eCSSProperty_background_y_position, nsCSSValue(yEnumValue, eCSSUnit_Enumerated));
xValue = BackgroundPositionMaskToCSSValue(mask, PR_TRUE);
yValue = BackgroundPositionMaskToCSSValue(mask, PR_FALSE);
AppendValue(eCSSProperty_background_x_position, xValue);
AppendValue(eCSSProperty_background_y_position, yValue);
return PR_TRUE;
}
return PR_FALSE;