Bug 1074056 - Part 1 - Add support for interpolation hints to CSS gradients. r=dbaron

This commit is contained in:
Rik Cabanier 2014-10-22 14:24:00 +02:00
parent be6fb5965d
commit 85aa244222
8 changed files with 86 additions and 17 deletions

View File

@ -8804,12 +8804,15 @@ CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient)
{
nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement();
if (!ParseVariant(stop->mColor, VARIANT_COLOR, nullptr)) {
return false;
stop->mIsInterpolationHint = true;
}
// Stop positions do not have to fall between the starting-point and
// ending-point, so we don't use ParseNonNegativeVariant.
if (!ParseVariant(stop->mLocation, VARIANT_LP | VARIANT_CALC, nullptr)) {
if (stop->mIsInterpolationHint) {
return false;
}
stop->mLocation.SetNoneValue();
}
return true;
@ -9157,6 +9160,20 @@ CSSParserImpl::ParseGradientColorStops(nsCSSValueGradient* aGradient,
return false;
}
// Check if interpolation hints are in the correct location
bool previousPointWasInterpolationHint = true;
for (size_t x = 0; x < aGradient->mStops.Length(); x++) {
bool isInterpolationHint = aGradient->mStops[x].mIsInterpolationHint;
if (isInterpolationHint && previousPointWasInterpolationHint) {
return false;
}
previousPointWasInterpolationHint = isInterpolationHint;
}
if (previousPointWasInterpolationHint) {
return false;
}
aValue.SetGradientValue(aGradient);
return true;
}

View File

@ -1414,10 +1414,15 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
}
for (uint32_t i = 0 ;;) {
bool isInterpolationHint = gradient->mStops[i].mIsInterpolationHint;
if (!isInterpolationHint) {
gradient->mStops[i].mColor.AppendToString(aProperty, aResult,
aSerialization);
}
if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) {
if (!isInterpolationHint) {
aResult.Append(' ');
}
gradient->mStops[i].mLocation.AppendToString(aProperty, aResult,
aSerialization);
}
@ -2351,14 +2356,16 @@ css::ImageValue::~ImageValue()
nsCSSValueGradientStop::nsCSSValueGradientStop()
: mLocation(eCSSUnit_None),
mColor(eCSSUnit_Null)
mColor(eCSSUnit_Null),
mIsInterpolationHint(false)
{
MOZ_COUNT_CTOR(nsCSSValueGradientStop);
}
nsCSSValueGradientStop::nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther)
: mLocation(aOther.mLocation),
mColor(aOther.mColor)
mColor(aOther.mColor),
mIsInterpolationHint(aOther.mIsInterpolationHint)
{
MOZ_COUNT_CTOR(nsCSSValueGradientStop);
}

View File

@ -1341,11 +1341,15 @@ public:
nsCSSValue mLocation;
nsCSSValue mColor;
// If mIsInterpolationHint is true, there is no color, just
// a location.
bool mIsInterpolationHint;
bool operator==(const nsCSSValueGradientStop& aOther) const
{
return (mLocation == aOther.mLocation &&
mColor == aOther.mColor);
mIsInterpolationHint == aOther.mIsInterpolationHint &&
(mIsInterpolationHint || mColor == aOther.mColor));
}
bool operator!=(const nsCSSValueGradientStop& aOther) const

View File

@ -1928,13 +1928,19 @@ nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
if (needSep) {
aString.AppendLiteral(", ");
}
SetToRGBAColor(tmpVal, aGradient->mStops[i].mColor);
const auto& stop = aGradient->mStops[i];
if (!stop.mIsInterpolationHint) {
SetToRGBAColor(tmpVal, stop.mColor);
tmpVal->GetCssText(tokenString);
aString.Append(tokenString);
}
if (aGradient->mStops[i].mLocation.GetUnit() != eStyleUnit_None) {
if (stop.mLocation.GetUnit() != eStyleUnit_None) {
if (!stop.mIsInterpolationHint) {
aString.Append(' ');
AppendCSSGradientLength(aGradient->mStops[i].mLocation, tmpVal, aString);
}
AppendCSSGradientLength(stop.mLocation, tmpVal, aString);
}
needSep = true;
}

View File

@ -1107,12 +1107,20 @@ static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
NS_NOTREACHED("unexpected unit for gradient stop location");
}
stop.mIsInterpolationHint = valueStop.mIsInterpolationHint;
// inherit is not a valid color for stops, so we pass in a dummy
// parent color
NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit,
"inherit is not a valid color for gradient stops");
if (!valueStop.mIsInterpolationHint) {
SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext,
aContext, stop.mColor, aCanStoreInRuleTree);
} else {
// Always initialize to the same color so we don't need to worry
// about comparisons.
stop.mColor = NS_RGB(0, 0, 0);
}
aResult.mStops.AppendElement(stop);
}

View File

@ -1766,8 +1766,11 @@ nsStyleGradient::operator==(const nsStyleGradient& aOther) const
return false;
for (uint32_t i = 0; i < mStops.Length(); i++) {
if (mStops[i].mLocation != aOther.mStops[i].mLocation ||
mStops[i].mColor != aOther.mStops[i].mColor)
const auto& stop1 = mStops[i];
const auto& stop2 = aOther.mStops[i];
if (stop1.mLocation != stop2.mLocation ||
stop1.mIsInterpolationHint != stop2.mIsInterpolationHint ||
(!stop1.mIsInterpolationHint && stop1.mColor != stop2.mColor))
return false;
}

View File

@ -138,6 +138,11 @@ public:
struct nsStyleGradientStop {
nsStyleCoord mLocation; // percent, coord, calc, none
nscolor mColor;
bool mIsInterpolationHint;
// Use ==/!= on nsStyleGradient instead of on the gradient stop.
bool operator==(const nsStyleGradientStop&) const MOZ_DELETE;
bool operator!=(const nsStyleGradientStop&) const MOZ_DELETE;
};
class nsStyleGradient MOZ_FINAL {

View File

@ -86,6 +86,18 @@ var validGradientAndElementValues = [
"linear-gradient(1turn, red, blue)",
"linear-gradient(.414rad, red, blue)",
"linear-gradient(.414rad, red, 50%, blue)",
"linear-gradient(.414rad, red, 0%, blue)",
"linear-gradient(.414rad, red, 100%, blue)",
"linear-gradient(.414rad, red 50%, 50%, blue 50%)",
"linear-gradient(.414rad, red 50%, 20%, blue 50%)",
"linear-gradient(.414rad, red 50%, 30%, blue 10%)",
"linear-gradient(to right bottom, red, 20%, green 50%, 65%, blue)",
"linear-gradient(to right bottom, red, 20%, green 10%, blue)",
"linear-gradient(to right bottom, red, 50%, green 50%, 50%, blue)",
"linear-gradient(to right bottom, red, 0%, green 50%, 100%, blue)",
"-moz-linear-gradient(red, blue)",
"-moz-linear-gradient(red, yellow, blue)",
"-moz-linear-gradient(red 1px, yellow 20%, blue 24em, green)",
@ -504,6 +516,13 @@ var invalidGradientAndElementValues = [
"linear-gradient(1turn 20px, red, blue)",
"linear-gradient(.414rad bottom, red, blue)",
"linear-gradient(to top, 0%, blue)",
"linear-gradient(to top, red, 100%)",
"linear-gradient(to top, red, 45%, 56%, blue)",
"linear-gradient(to top, red,, blue)",
"linear-gradient(to top, red, green 35%, 15%, 54%, blue)",
"radial-gradient(top left 45deg, red, blue)",
"radial-gradient(20% bottom -300deg, red, blue)",
"radial-gradient(center 20% 1.95929rad, red, blue)",