Bug 506826 - Parsing for background-image: -moz-element(#elementID). r=dbaron

This commit is contained in:
Markus Stange 2010-08-13 15:33:37 +02:00
Родитель 8577cd7530
Коммит f71c692289
10 изменённых файлов: 147 добавлений и 25 удалений

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

@ -95,6 +95,7 @@ CSS_KEY(-moz-dialog, _moz_dialog)
CSS_KEY(-moz-dialogtext, _moz_dialogtext) CSS_KEY(-moz-dialogtext, _moz_dialogtext)
CSS_KEY(-moz-document, _moz_document) CSS_KEY(-moz-document, _moz_document)
CSS_KEY(-moz-dragtargetzone, _moz_dragtargetzone) CSS_KEY(-moz-dragtargetzone, _moz_dragtargetzone)
CSS_KEY(-moz-element, _moz_element)
CSS_KEY(-moz-eventreerow, _moz_eventreerow) CSS_KEY(-moz-eventreerow, _moz_eventreerow)
CSS_KEY(-moz-ethiopic-halehame, _moz_ethiopic_halehame) CSS_KEY(-moz-ethiopic-halehame, _moz_ethiopic_halehame)
CSS_KEY(-moz-ethiopic-numeric, _moz_ethiopic_numeric) CSS_KEY(-moz-ethiopic-numeric, _moz_ethiopic_numeric)

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

@ -120,6 +120,7 @@ namespace css = mozilla::css;
#define VARIANT_ZERO_ANGLE 0x02000000 // unitless zero for angles #define VARIANT_ZERO_ANGLE 0x02000000 // unitless zero for angles
#define VARIANT_CALC 0x04000000 // eCSSUnit_Calc #define VARIANT_CALC 0x04000000 // eCSSUnit_Calc
#define VARIANT_CALC_NO_MIN_MAX 0x08000000 // no min() and max() for calc() #define VARIANT_CALC_NO_MIN_MAX 0x08000000 // no min() and max() for calc()
#define VARIANT_ELEMENT 0x10000000 // eCSSUnit_Element
// Common combinations of variants // Common combinations of variants
#define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH) #define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH)
@ -158,6 +159,8 @@ namespace css = mozilla::css;
#define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE) #define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE)
#define VARIANT_TRANSFORM_LPCALC (VARIANT_LP | VARIANT_CALC | \ #define VARIANT_TRANSFORM_LPCALC (VARIANT_LP | VARIANT_CALC | \
VARIANT_CALC_NO_MIN_MAX) VARIANT_CALC_NO_MIN_MAX)
#define VARIANT_IMAGE (VARIANT_URL | VARIANT_NONE | VARIANT_GRADIENT | \
VARIANT_IMAGE_RECT | VARIANT_ELEMENT)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -562,6 +565,7 @@ protected:
PRBool TranslateDimension(nsCSSValue& aValue, PRInt32 aVariantMask, PRBool TranslateDimension(nsCSSValue& aValue, PRInt32 aVariantMask,
float aNumber, const nsString& aUnit); float aNumber, const nsString& aUnit);
PRBool ParseImageRect(nsCSSValue& aImage); PRBool ParseImageRect(nsCSSValue& aImage);
PRBool ParseElement(nsCSSValue& aValue);
PRBool ParseColorStop(nsCSSValueGradient* aGradient); PRBool ParseColorStop(nsCSSValueGradient* aGradient);
PRBool ParseGradient(nsCSSValue& aValue, PRBool aIsRadial, PRBool ParseGradient(nsCSSValue& aValue, PRBool aIsRadial,
PRBool aIsRepeating); PRBool aIsRepeating);
@ -4438,6 +4442,11 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
tk->mIdent.LowerCaseEqualsLiteral("-moz-image-rect")) { tk->mIdent.LowerCaseEqualsLiteral("-moz-image-rect")) {
return ParseImageRect(aValue); return ParseImageRect(aValue);
} }
if ((aVariantMask & VARIANT_ELEMENT) != 0 &&
eCSSToken_Function == tk->mType &&
tk->mIdent.LowerCaseEqualsLiteral("-moz-element")) {
return ParseElement(aValue);
}
if ((aVariantMask & VARIANT_COLOR) != 0) { if ((aVariantMask & VARIANT_COLOR) != 0) {
if ((mNavQuirkMode && !IsParsingCompoundProperty()) || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix if ((mNavQuirkMode && !IsParsingCompoundProperty()) || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix
(eCSSToken_ID == tk->mType) || (eCSSToken_ID == tk->mType) ||
@ -4743,6 +4752,32 @@ CSSParserImpl::ParseImageRect(nsCSSValue& aImage)
return PR_TRUE; return PR_TRUE;
} }
SkipUntil(')');
return PR_FALSE;
}
// <element>: -moz-element(# <element_id> )
PRBool
CSSParserImpl::ParseElement(nsCSSValue& aValue)
{
// A non-iterative for loop to break out when an error occurs.
for (;;) {
if (!GetToken(PR_TRUE))
break;
if (mToken.mType == eCSSToken_ID) {
aValue.SetStringValue(mToken.mIdent, eCSSUnit_Element);
} else {
UngetToken();
break;
}
if (!ExpectSymbol(')', PR_TRUE))
break;
return PR_TRUE;
}
// If we detect a syntax error, we must match the opening parenthesis of the // If we detect a syntax error, we must match the opening parenthesis of the
// function with the closing parenthesis and skip all the tokens in between. // function with the closing parenthesis and skip all the tokens in between.
SkipUntil(')'); SkipUntil(')');
@ -5593,9 +5628,7 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
return ParseVariant(aValue, VARIANT_HC, nsnull); return ParseVariant(aValue, VARIANT_HC, nsnull);
case eCSSProperty_background_image: case eCSSProperty_background_image:
// Used only internally. // Used only internally.
return ParseVariant(aValue, return ParseVariant(aValue, VARIANT_IMAGE | VARIANT_INHERIT, nsnull);
VARIANT_HUO | VARIANT_GRADIENT | VARIANT_IMAGE_RECT,
nsnull);
case eCSSProperty__moz_background_inline_policy: case eCSSProperty__moz_background_inline_policy:
return ParseVariant(aValue, VARIANT_HK, return ParseVariant(aValue, VARIANT_HK,
nsCSSProps::kBackgroundInlinePolicyKTable); nsCSSProps::kBackgroundInlinePolicyKTable);
@ -6380,7 +6413,8 @@ CSSParserImpl::ParseBackgroundItem(CSSParserImpl::BackgroundItem& aItem,
mToken.mIdent.LowerCaseEqualsLiteral("-moz-radial-gradient") || mToken.mIdent.LowerCaseEqualsLiteral("-moz-radial-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient") || mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-linear-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") || mToken.mIdent.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-image-rect"))) { mToken.mIdent.LowerCaseEqualsLiteral("-moz-image-rect") ||
mToken.mIdent.LowerCaseEqualsLiteral("-moz-element"))) {
if (haveImage) if (haveImage)
return PR_FALSE; return PR_FALSE;
haveImage = PR_TRUE; haveImage = PR_TRUE;

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

@ -741,6 +741,14 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsDependentString(GetOriginalURLValue()), aResult); nsDependentString(GetOriginalURLValue()), aResult);
aResult.Append(NS_LITERAL_STRING(")")); aResult.Append(NS_LITERAL_STRING(")"));
} }
else if (eCSSUnit_Element == unit) {
aResult.Append(NS_LITERAL_STRING("-moz-element(#"));
nsAutoString tmpStr;
GetStringValue(tmpStr);
nsStyleUtil::AppendEscapedCSSIdent(
nsDependentString(tmpStr), aResult);
aResult.Append(NS_LITERAL_STRING(")"));
}
else if (eCSSUnit_Percent == unit) { else if (eCSSUnit_Percent == unit) {
nsAutoString tmpStr; nsAutoString tmpStr;
tmpStr.AppendFloat(GetPercentValue() * 100.0f); tmpStr.AppendFloat(GetPercentValue() * 100.0f);
@ -846,6 +854,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
case eCSSUnit_Families: break; case eCSSUnit_Families: break;
case eCSSUnit_URL: break; case eCSSUnit_URL: break;
case eCSSUnit_Image: break; case eCSSUnit_Image: break;
case eCSSUnit_Element: break;
case eCSSUnit_Array: break; case eCSSUnit_Array: break;
case eCSSUnit_Attr: case eCSSUnit_Attr:
case eCSSUnit_Cubic_Bezier: case eCSSUnit_Cubic_Bezier:

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

@ -109,6 +109,7 @@ enum nsCSSUnit {
eCSSUnit_Attr = 14, // (PRUnichar*) a attr(string) value eCSSUnit_Attr = 14, // (PRUnichar*) a attr(string) value
eCSSUnit_Local_Font = 15, // (PRUnichar*) a local font name eCSSUnit_Local_Font = 15, // (PRUnichar*) a local font name
eCSSUnit_Font_Format = 16, // (PRUnichar*) a font format name eCSSUnit_Font_Format = 16, // (PRUnichar*) a font format name
eCSSUnit_Element = 17, // (PRUnichar*) an element id
eCSSUnit_Array = 20, // (nsCSSValue::Array*) a list of values eCSSUnit_Array = 20, // (nsCSSValue::Array*) a list of values
eCSSUnit_Counter = 21, // (nsCSSValue::Array*) a counter(string,[string]) value eCSSUnit_Counter = 21, // (nsCSSValue::Array*) a counter(string,[string]) value
eCSSUnit_Counters = 22, // (nsCSSValue::Array*) a counters(string,string[,string]) value eCSSUnit_Counters = 22, // (nsCSSValue::Array*) a counters(string,string[,string]) value
@ -259,7 +260,7 @@ public:
{ return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Maximum; } { return eCSSUnit_Calc <= mUnit && mUnit <= eCSSUnit_Calc_Maximum; }
PRBool UnitHasStringValue() const PRBool UnitHasStringValue() const
{ return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Font_Format; } { return eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Element; }
PRBool UnitHasArrayValue() const PRBool UnitHasArrayValue() const
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Maximum; } { return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Maximum; }

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

@ -1614,6 +1614,17 @@ nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
aValue->SetString(gradientString); aValue->SetString(gradientString);
break; break;
} }
case eStyleImageType_Element:
{
nsAutoString elementId;
nsStyleUtil::AppendEscapedCSSIdent(
nsDependentString(aStyleImage.GetElementId()), elementId);
nsAutoString elementString = NS_LITERAL_STRING("-moz-element(#") +
elementId +
NS_LITERAL_STRING(")");
aValue->SetString(elementString);
break;
}
case eStyleImageType_Null: case eStyleImageType_Null:
aValue->SetIdent(eCSSKeyword_none); aValue->SetIdent(eCSSKeyword_none);
break; break;

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

@ -955,6 +955,9 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
} }
break; break;
} }
case eCSSUnit_Element:
aResult.SetElementId(aValue.GetStringBufferValue());
break;
case eCSSUnit_None: case eCSSUnit_None:
break; break;
default: default:

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

@ -474,15 +474,15 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther)
DO_STRUCT_DIFFERENCE(Position); DO_STRUCT_DIFFERENCE(Position);
DO_STRUCT_DIFFERENCE(TextReset); DO_STRUCT_DIFFERENCE(TextReset);
// At this point, we know that the worst kind of damage we could do is // Most backgrounds only require a re-render (i.e., a VISUAL change), but
// a re-render (i.e., a VISUAL change). // backgrounds using -moz-element need to reset SVG effects, too.
maxHint = NS_STYLE_HINT_VISUAL; maxHint = nsChangeHint(NS_STYLE_HINT_VISUAL | nsChangeHint_UpdateEffects);
// The following structs cause (as their maximal difference) a
// re-render to occur. VISUAL Structs: Color, Background
DO_STRUCT_DIFFERENCE(Color);
DO_STRUCT_DIFFERENCE(Background); DO_STRUCT_DIFFERENCE(Background);
// Color only needs a repaint.
maxHint = NS_STYLE_HINT_VISUAL;
DO_STRUCT_DIFFERENCE(Color);
#undef DO_STRUCT_DIFFERENCE #undef DO_STRUCT_DIFFERENCE
// Note that we do not check whether this->RelevantLinkVisited() != // Note that we do not check whether this->RelevantLinkVisited() !=

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

@ -1378,6 +1378,8 @@ nsStyleImage::DoCopy(const nsStyleImage& aOther)
SetImageData(aOther.mImage); SetImageData(aOther.mImage);
else if (aOther.mType == eStyleImageType_Gradient) else if (aOther.mType == eStyleImageType_Gradient)
SetGradientData(aOther.mGradient); SetGradientData(aOther.mGradient);
else if (aOther.mType == eStyleImageType_Element)
SetElementId(aOther.mElementId);
SetCropRect(aOther.mCropRect); SetCropRect(aOther.mCropRect);
} }
@ -1389,6 +1391,8 @@ nsStyleImage::SetNull()
mGradient->Release(); mGradient->Release();
else if (mType == eStyleImageType_Image) else if (mType == eStyleImageType_Image)
NS_RELEASE(mImage); NS_RELEASE(mImage);
else if (mType == eStyleImageType_Element)
nsCRT::free(mElementId);
mType = eStyleImageType_Null; mType = eStyleImageType_Null;
mCropRect = nsnull; mCropRect = nsnull;
@ -1423,6 +1427,18 @@ nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
} }
} }
void
nsStyleImage::SetElementId(const PRUnichar* aElementId)
{
if (mType != eStyleImageType_Null)
SetNull();
if (aElementId) {
mElementId = nsCRT::strdup(aElementId);
mType = eStyleImageType_Element;
}
}
void void
nsStyleImage::SetCropRect(nsStyleSides* aCropRect) nsStyleImage::SetCropRect(nsStyleSides* aCropRect)
{ {
@ -1506,6 +1522,9 @@ nsStyleImage::IsOpaque() const
return PR_FALSE; return PR_FALSE;
} }
if (mType == eStyleImageType_Element)
return PR_FALSE;
NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type"); NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type");
nsCOMPtr<imgIContainer> imageContainer; nsCOMPtr<imgIContainer> imageContainer;
@ -1537,6 +1556,7 @@ nsStyleImage::IsComplete() const
case eStyleImageType_Null: case eStyleImageType_Null:
return PR_FALSE; return PR_FALSE;
case eStyleImageType_Gradient: case eStyleImageType_Gradient:
case eStyleImageType_Element:
return PR_TRUE; return PR_TRUE;
case eStyleImageType_Image: case eStyleImageType_Image:
{ {
@ -1573,6 +1593,9 @@ nsStyleImage::operator==(const nsStyleImage& aOther) const
if (mType == eStyleImageType_Gradient) if (mType == eStyleImageType_Gradient)
return *mGradient == *aOther.mGradient; return *mGradient == *aOther.mGradient;
if (mType == eStyleImageType_Element)
return nsCRT::strcmp(mElementId, aOther.mElementId) == 0;
return PR_TRUE; return PR_TRUE;
} }
@ -1631,17 +1654,33 @@ nsStyleBackground::~nsStyleBackground()
nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
{ {
if (mBackgroundColor != aOther.mBackgroundColor || const nsStyleBackground* moreLayers =
mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy || mImageCount > aOther.mImageCount ? this : &aOther;
mImageCount != aOther.mImageCount) const nsStyleBackground* lessLayers =
return NS_STYLE_HINT_VISUAL; mImageCount > aOther.mImageCount ? &aOther : this;
// We checked the image count above. bool hasVisualDifference = false;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
if (mLayers[i] != aOther.mLayers[i]) NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) {
return NS_STYLE_HINT_VISUAL; if (i < lessLayers->mImageCount) {
if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) {
if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
(lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))
return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
hasVisualDifference = true;
}
} else {
if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)
return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
hasVisualDifference = true;
}
} }
if (hasVisualDifference ||
mBackgroundColor != aOther.mBackgroundColor ||
mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy)
return NS_STYLE_HINT_VISUAL;
return NS_STYLE_HINT_NONE; return NS_STYLE_HINT_NONE;
} }
@ -1649,7 +1688,7 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther)
/* static */ /* static */
nsChangeHint nsStyleBackground::MaxDifference() nsChangeHint nsStyleBackground::MaxDifference()
{ {
return NS_STYLE_HINT_VISUAL; return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
} }
#endif #endif

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

@ -186,13 +186,16 @@ private:
enum nsStyleImageType { enum nsStyleImageType {
eStyleImageType_Null, eStyleImageType_Null,
eStyleImageType_Image, eStyleImageType_Image,
eStyleImageType_Gradient eStyleImageType_Gradient,
eStyleImageType_Element
}; };
/** /**
* Represents a paintable image of one of the following types. * Represents a paintable image of one of the following types.
* (1) A real image loaded from an external source. * (1) A real image loaded from an external source.
* (2) A CSS linear or radial gradient. * (2) A CSS linear or radial gradient.
* (3) An element within a document, or an <img>, <video>, or <canvas> element
* not in a document.
* (*) Optionally a crop rect can be set to paint a partial (rectangular) * (*) Optionally a crop rect can be set to paint a partial (rectangular)
* region of an image. (Currently, this feature is only supported with an * region of an image. (Currently, this feature is only supported with an
* image of type (1)). * image of type (1)).
@ -210,6 +213,7 @@ struct nsStyleImage {
void SetNull(); void SetNull();
void SetImageData(imgIRequest* aImage); void SetImageData(imgIRequest* aImage);
void SetGradientData(nsStyleGradient* aGradient); void SetGradientData(nsStyleGradient* aGradient);
void SetElementId(const PRUnichar* aElementId);
void SetCropRect(nsStyleSides* aCropRect); void SetCropRect(nsStyleSides* aCropRect);
nsStyleImageType GetType() const { nsStyleImageType GetType() const {
@ -223,6 +227,10 @@ struct nsStyleImage {
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!"); NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
return mGradient; return mGradient;
} }
const PRUnichar* GetElementId() const {
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
return mElementId;
}
nsStyleSides* GetCropRect() const { nsStyleSides* GetCropRect() const {
NS_ASSERTION(mType == eStyleImageType_Image, NS_ASSERTION(mType == eStyleImageType_Image,
"Only image data can have a crop rect"); "Only image data can have a crop rect");
@ -252,7 +260,8 @@ struct nsStyleImage {
PRBool IsOpaque() const; PRBool IsOpaque() const;
/** /**
* @return PR_TRUE if this image is fully loaded, and its size is calculated; * @return PR_TRUE if this image is fully loaded, and its size is calculated;
* always returns PR_TRUE if |mType| is |eStyleImageType_Gradient|. * always returns PR_TRUE if |mType| is |eStyleImageType_Gradient| or
* |eStyleImageType_Element|.
*/ */
PRBool IsComplete() const; PRBool IsComplete() const;
/** /**
@ -282,6 +291,7 @@ private:
union { union {
imgIRequest* mImage; imgIRequest* mImage;
nsStyleGradient* mGradient; nsStyleGradient* mGradient;
PRUnichar* mElementId;
}; };
// This is _currently_ used only in conjunction with eStyleImageType_Image. // This is _currently_ used only in conjunction with eStyleImageType_Image.
nsAutoPtr<nsStyleSides> mCropRect; nsAutoPtr<nsStyleSides> mCropRect;
@ -399,11 +409,15 @@ struct nsStyleBackground {
// frame size when their dimensions are 'auto', images don't; both // frame size when their dimensions are 'auto', images don't; both
// types depend on the frame size when their dimensions are // types depend on the frame size when their dimensions are
// 'contain', 'cover', or a percentage. // 'contain', 'cover', or a percentage.
// -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 { PRBool DependsOnFrameSize(nsStyleImageType aType) const {
if (aType == eStyleImageType_Image) { if (aType == eStyleImageType_Image) {
return mWidthType <= ePercentage || mHeightType <= ePercentage; return mWidthType <= ePercentage || mHeightType <= ePercentage;
} else { } else {
NS_ABORT_IF_FALSE(aType == eStyleImageType_Gradient, NS_ABORT_IF_FALSE(aType == eStyleImageType_Gradient ||
aType == eStyleImageType_Element,
"unrecognized image type"); "unrecognized image type");
return mWidthType <= eAuto || mHeightType <= eAuto; return mWidthType <= eAuto || mHeightType <= eAuto;
} }

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

@ -802,6 +802,7 @@ var gCSSProperties = {
"-moz-linear-gradient(10px 10px -45deg, red, blue) repeat", "-moz-linear-gradient(10px 10px -45deg, red, blue) repeat",
"-moz-repeating-radial-gradient(10% bottom, #ffffff, black) scroll no-repeat", "-moz-repeating-radial-gradient(10% bottom, #ffffff, black) scroll no-repeat",
"-moz-repeating-linear-gradient(10px 10px -45deg, red, blue) repeat", "-moz-repeating-linear-gradient(10px 10px -45deg, red, blue) repeat",
"-moz-element(#test) lime",
/* multiple backgrounds */ /* multiple backgrounds */
"url(404.png), url(404.png)", "url(404.png), url(404.png)",
"url(404.png), url(404.png) transparent", "url(404.png), url(404.png) transparent",
@ -809,7 +810,7 @@ var gCSSProperties = {
"repeat-x, fixed, none", "repeat-x, fixed, none",
"0% top url(404.png), url(404.png) 0% top", "0% top url(404.png), url(404.png) 0% top",
"fixed repeat-y top left url(404.png), repeat-x green", "fixed repeat-y top left url(404.png), repeat-x green",
"url(404.png), -moz-linear-gradient(20px 20px -45deg, blue, green) black", "url(404.png), -moz-linear-gradient(20px 20px -45deg, blue, green), -moz-element(#a) black",
/* test cases with clip+origin in the shorthand */ /* test cases with clip+origin in the shorthand */
"url(404.png) green padding-box", "url(404.png) green padding-box",
"url(404.png) border-box transparent", "url(404.png) border-box transparent",
@ -876,6 +877,10 @@ var gCSSProperties = {
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"none, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none", "none, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), none",
"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)",
"-moz-element(#a)",
"-moz-element( #a )",
"-moz-element(#a-1)",
"-moz-element(#a\\:1)",
/* gradient torture test */ /* gradient torture test */
"-moz-linear-gradient(red, blue)", "-moz-linear-gradient(red, blue)",
"-moz-linear-gradient(red, yellow, blue)", "-moz-linear-gradient(red, yellow, blue)",
@ -1037,6 +1042,11 @@ var gCSSProperties = {
"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10, 50%, 30%, 0)", "-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10, 50%, 30%, 0)",
], ],
invalid_values: [ invalid_values: [
"-moz-element(#a:1)",
"-moz-element(a#a)",
"-moz-element(#a a)",
"-moz-element(#a+a)",
"-moz-element(#a()",
/* Old syntax */ /* Old syntax */
"-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))", "-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))",
"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))", "-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",