Bug 897392 - Implement parsing of filter:hue-rotate(). r=heycam

This commit is contained in:
Dirk Schulze 2013-07-26 16:02:33 +10:00
parent 8a7d1fe132
commit 569ef7a7ef
9 changed files with 152 additions and 34 deletions

View File

@ -288,6 +288,7 @@ CSS_KEY(historical-forms, historical_forms)
CSS_KEY(historical-ligatures, historical_ligatures)
CSS_KEY(horizontal, horizontal)
CSS_KEY(horizontal-tb, horizontal_tb)
CSS_KEY(hue-rotate, hue_rotate)
CSS_KEY(hz, hz)
CSS_KEY(icon, icon)
CSS_KEY(ignore, ignore)

View File

@ -10081,15 +10081,19 @@ CSSParserImpl::ParseSingleFilter(nsCSSValue* aValue)
// VARIANT_NONNEGATIVE_DIMENSION will already reject negative lengths.
rejectNegativeArgument = false;
break;
case eCSSKeyword_brightness:
case eCSSKeyword_contrast:
case eCSSKeyword_saturate:
break;
case eCSSKeyword_grayscale:
case eCSSKeyword_invert:
case eCSSKeyword_sepia:
case eCSSKeyword_opacity:
clampArgumentToOne = true;
break;
case eCSSKeyword_brightness:
case eCSSKeyword_contrast:
case eCSSKeyword_saturate:
case eCSSKeyword_hue_rotate:
variantMask = VARIANT_ANGLE;
rejectNegativeArgument = false;
break;
default:
// Unrecognized filter function.

View File

@ -1710,16 +1710,8 @@ nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
if (needSep) {
aString.AppendLiteral(" ");
}
tmpVal->SetNumber(aGradient->mAngle.GetAngleValue());
tmpVal->GetCssText(tokenString);
SetCssTextToCoord(tokenString, aGradient->mAngle);
aString.Append(tokenString);
switch (aGradient->mAngle.GetUnit()) {
case eStyleUnit_Degree: aString.AppendLiteral("deg"); break;
case eStyleUnit_Grad: aString.AppendLiteral("grad"); break;
case eStyleUnit_Radian: aString.AppendLiteral("rad"); break;
case eStyleUnit_Turn: aString.AppendLiteral("turn"); break;
default: NS_NOTREACHED("unrecognized angle unit");
}
needSep = true;
}
@ -4007,6 +3999,23 @@ nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
SetValueToCalc(calc, aValue);
}
break;
case eStyleUnit_Degree:
aValue->SetDegree(aCoord.GetAngleValue());
break;
case eStyleUnit_Grad:
aValue->SetGrad(aCoord.GetAngleValue());
break;
case eStyleUnit_Radian:
aValue->SetRadian(aCoord.GetAngleValue());
break;
case eStyleUnit_Turn:
aValue->SetTurn(aCoord.GetAngleValue());
break;
default:
NS_ERROR("Can't handle this unit");
break;
@ -4495,6 +4504,9 @@ GetFilterFunctionName(nsAString& aString, nsStyleFilter::Type mType)
case nsStyleFilter::Type::eGrayscale:
aString.AssignLiteral("grayscale(");
break;
case nsStyleFilter::Type::eHueRotate:
aString.AssignLiteral("hue-rotate(");
break;
case nsStyleFilter::Type::eInvert:
aString.AssignLiteral("invert(");
break;
@ -4530,7 +4542,7 @@ nsComputedDOMStyle::CreatePrimitiveValueForStyleFilter(
// Filter function argument.
nsAutoString argumentString;
SetCssTextToCoord(argumentString, aStyleFilter.mCoord);
SetCssTextToCoord(argumentString, aStyleFilter.mFilterParameter);
filterFunctionString.Append(argumentString);
// Filter function closing parenthesis.

View File

@ -18,6 +18,13 @@
using namespace mozilla;
// There is no CSS_TURN constant on the CSSPrimitiveValue interface,
// since that unit is newer than DOM Level 2 Style, and CSS OM will
// probably expose CSS values in some other way in the future. We
// use this value in mType for "turn"-unit angles, but we define it
// here to avoid exposing it to content.
#define CSS_TURN 30U
nsROCSSPrimitiveValue::nsROCSSPrimitiveValue()
: CSSValue(), mType(CSS_PX)
{
@ -134,6 +141,30 @@ nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
tmpStr.AppendFloat(mValue.mFloat);
break;
}
case CSS_DEG :
{
tmpStr.AppendFloat(mValue.mFloat);
tmpStr.AppendLiteral("deg");
break;
}
case CSS_GRAD :
{
tmpStr.AppendFloat(mValue.mFloat);
tmpStr.AppendLiteral("grad");
break;
}
case CSS_RAD :
{
tmpStr.AppendFloat(mValue.mFloat);
tmpStr.AppendLiteral("rad");
break;
}
case CSS_TURN :
{
tmpStr.AppendFloat(mValue.mFloat);
tmpStr.AppendLiteral("turn");
break;
}
case CSS_RECT :
{
NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null");
@ -230,9 +261,6 @@ nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText)
case CSS_UNKNOWN :
case CSS_EMS :
case CSS_EXS :
case CSS_DEG :
case CSS_RAD :
case CSS_GRAD :
case CSS_MS :
case CSS_HZ :
case CSS_KHZ :
@ -520,6 +548,38 @@ nsROCSSPrimitiveValue::SetPercent(float aValue)
mType = CSS_PERCENTAGE;
}
void
nsROCSSPrimitiveValue::SetDegree(float aValue)
{
Reset();
mValue.mFloat = aValue;
mType = CSS_DEG;
}
void
nsROCSSPrimitiveValue::SetGrad(float aValue)
{
Reset();
mValue.mFloat = aValue;
mType = CSS_GRAD;
}
void
nsROCSSPrimitiveValue::SetRadian(float aValue)
{
Reset();
mValue.mFloat = aValue;
mType = CSS_RAD;
}
void
nsROCSSPrimitiveValue::SetTurn(float aValue)
{
Reset();
mValue.mFloat = aValue;
mType = CSS_TURN;
}
void
nsROCSSPrimitiveValue::SetAppUnits(nscoord aValue)
{

View File

@ -44,6 +44,11 @@ public:
// CSSPrimitiveValue
uint16_t PrimitiveType()
{
// New value types were introduced but not added to CSS OM.
// Return CSS_UNKNOWN to avoid exposing CSS_TURN to content.
if (mType > CSS_RGBCOLOR) {
return CSS_UNKNOWN;
}
return mType;
}
void SetFloatValue(uint16_t aUnitType, float aValue,
@ -64,6 +69,10 @@ public:
void SetNumber(int32_t aValue);
void SetNumber(uint32_t aValue);
void SetPercent(float aValue);
void SetDegree(float aValue);
void SetGrad(float aValue);
void SetRadian(float aValue);
void SetTurn(float aValue);
void SetAppUnits(nscoord aValue);
void SetAppUnits(float aValue);
void SetIdent(nsCSSKeyword aKeyword);

View File

@ -653,6 +653,7 @@ GetFloatFromBoxPosition(int32_t aEnumValue)
#define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY
#define SETCOORD_STORE_CALC 0x00080000
#define SETCOORD_BOX_POSITION 0x00100000 // exclusive with _ENUMERATED
#define SETCOORD_ANGLE 0x00200000
#define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
#define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
@ -765,6 +766,19 @@ static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord,
result = false; // didn't set anything
}
}
else if ((aMask & SETCOORD_ANGLE) != 0 &&
(aValue.IsAngularUnit())) {
nsStyleUnit unit;
switch (aValue.GetUnit()) {
case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
case eCSSUnit_Grad: unit = eStyleUnit_Grad; break;
case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
case eCSSUnit_Turn: unit = eStyleUnit_Turn; break;
default: NS_NOTREACHED("unrecognized angular unit");
unit = eStyleUnit_Degree;
}
aCoord.SetAngleValue(aValue.GetAngleValue(), unit);
}
else {
result = false; // didn't set anything
}
@ -987,18 +1001,9 @@ static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
aResult.mRepeating = gradient->mIsRepeating;
// angle
if (gradient->mAngle.IsAngularUnit()) {
nsStyleUnit unit;
switch (gradient->mAngle.GetUnit()) {
case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
case eCSSUnit_Grad: unit = eStyleUnit_Grad; break;
case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
case eCSSUnit_Turn: unit = eStyleUnit_Turn; break;
default: NS_NOTREACHED("unrecognized angular unit");
unit = eStyleUnit_Degree;
}
aResult.mAngle.SetAngleValue(gradient->mAngle.GetAngleValue(), unit);
} else {
const nsStyleCoord dummyParentCoord;
if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE,
aContext, aPresContext, aCanStoreInRuleTree)) {
NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
"bad unit for gradient angle");
aResult.mAngle.SetNoneValue();
@ -7720,6 +7725,8 @@ StyleFilterTypeForFunctionName(nsCSSKeyword functionName)
return nsStyleFilter::Type::eContrast;
case eCSSKeyword_grayscale:
return nsStyleFilter::Type::eGrayscale;
case eCSSKeyword_hue_rotate:
return nsStyleFilter::Type::eHueRotate;
case eCSSKeyword_invert:
return nsStyleFilter::Type::eInvert;
case eCSSKeyword_opacity:
@ -7756,16 +7763,20 @@ SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
aStyleFilter->mType = StyleFilterTypeForFunctionName(functionName);
int32_t mask = SETCOORD_PERCENT | SETCOORD_FACTOR;
if (aStyleFilter->mType == nsStyleFilter::Type::eBlur)
if (aStyleFilter->mType == nsStyleFilter::Type::eBlur) {
mask = SETCOORD_LENGTH | SETCOORD_STORE_CALC;
} else if (aStyleFilter->mType == nsStyleFilter::Type::eHueRotate) {
mask = SETCOORD_ANGLE;
}
NS_ABORT_IF_FALSE(filterFunction->Count() == 2,
"all filter functions except drop-shadow should have "
"exactly one argument");
nsCSSValue& arg = filterFunction->Item(1);
DebugOnly<bool> success = SetCoord(arg, aStyleFilter->mCoord, nsStyleCoord(),
mask, aStyleContext, aPresContext,
DebugOnly<bool> success = SetCoord(arg, aStyleFilter->mFilterParameter,
nsStyleCoord(), mask,
aStyleContext, aPresContext,
aCanStoreInRuleTree);
NS_ABORT_IF_FALSE(success, "unexpected unit");
}

View File

@ -1017,7 +1017,7 @@ nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
if (mType == eURL) {
mURL = aSource.mURL;
} else if (mType != eNull) {
mCoord = aSource.mCoord;
mFilterParameter = aSource.mFilterParameter;
}
}
@ -1036,7 +1036,7 @@ nsStyleFilter::operator==(const nsStyleFilter& aOther) const
if (mType == eURL) {
return EqualURIs(mURL, aOther.mURL);
} else if (mType != eNull) {
return mCoord == aOther.mCoord;
return mFilterParameter == aOther.mFilterParameter;
}
return true;

View File

@ -2281,6 +2281,7 @@ struct nsStyleFilter {
eBlur,
eBrightness,
eContrast,
eHueRotate,
eInvert,
eOpacity,
eGrayscale,
@ -2290,7 +2291,7 @@ struct nsStyleFilter {
Type mType;
nsIURI* mURL;
nsStyleCoord mCoord;
nsStyleCoord mFilterParameter; // coord, percent, factor, angle
// FIXME: Add a nsCSSShadowItem when we implement drop shadow.
};

View File

@ -4466,6 +4466,16 @@ if (SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
"grayscale(350%)",
"grayscale(4.567)",
"hue-rotate(0deg)",
"hue-rotate(90deg)",
"hue-rotate(540deg)",
"hue-rotate(-90deg)",
"hue-rotate(10grad)",
"hue-rotate(1.6rad)",
"hue-rotate(-1.6rad)",
"hue-rotate(0.5turn)",
"hue-rotate(-2turn)",
"invert(0)",
"invert(50%)",
"invert(1)",
@ -4554,6 +4564,16 @@ if (SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
"grayscale(10px)",
"grayscale(-1)",
"hue-rotate()",
"hue-rotate(0)",
"hue-rotate(0.5 0.5)",
"hue-rotate(0.5,)",
"hue-rotate(0.5, 0.5)",
"hue-rotate(#my-filter)",
"hue-rotate(10px)",
"hue-rotate(-1)",
"hue-rotate(45deg,)",
"invert()",
"invert(0.5 0.5)",
"invert(0.5,)",