Bug 731271 - Part 2: Add new nsCSSValue units to store colors in their original syntactic form. r=dbaron

This commit is contained in:
Cameron McCormack 2013-09-16 09:35:48 +10:00
Родитель e93885019c
Коммит b3b6726cef
6 изменённых файлов: 202 добавлений и 22 удалений

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

@ -590,7 +590,7 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
return false;
}
if (value.GetUnit() == eCSSUnit_RGBAColor) {
if (value.IsNumericColorUnit()) {
// if we already have a color we can just use it directly
*aColor = value.GetColorValue();
} else {

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

@ -12069,8 +12069,8 @@ CSSParserImpl::ParseShadowItem(nsCSSValue& aValue, bool aIsBoxShadow)
} else {
// Must be a color (as string or color value)
NS_ASSERTION(xOrColor.GetUnit() == eCSSUnit_Ident ||
xOrColor.GetUnit() == eCSSUnit_RGBAColor ||
xOrColor.GetUnit() == eCSSUnit_EnumColor,
xOrColor.GetUnit() == eCSSUnit_EnumColor ||
xOrColor.IsNumericColorUnit(),
"Must be a color value");
val->Item(IndexColor) = xOrColor;
haveColor = true;

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

@ -20,7 +20,7 @@
#define VARIANT_KEYWORD 0x000001 // K
#define VARIANT_LENGTH 0x000002 // L
#define VARIANT_PERCENT 0x000004 // P
#define VARIANT_COLOR 0x000008 // C eCSSUnit_RGBAColor, eCSSUnit_Ident (e.g. "red")
#define VARIANT_COLOR 0x000008 // C eCSSUnit_*Color, eCSSUnit_Ident (e.g. "red")
#define VARIANT_URL 0x000010 // U
#define VARIANT_NUMBER 0x000020 // N
#define VARIANT_INTEGER 0x000040 // I

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

@ -121,9 +121,13 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_EnumColor) {
mValue.mInt = aCopy.mValue.mInt;
}
else if (eCSSUnit_RGBAColor == mUnit) {
else if (IsIntegerColorUnit()) {
mValue.mColor = aCopy.mValue.mColor;
}
else if (IsFloatColorUnit()) {
mValue.mFloatColor = aCopy.mValue.mFloatColor;
mValue.mFloatColor->AddRef();
}
else if (UnitHasArrayValue()) {
mValue.mArray = aCopy.mValue.mArray;
mValue.mArray->AddRef();
@ -207,9 +211,12 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_EnumColor)) {
return mValue.mInt == aOther.mValue.mInt;
}
else if (eCSSUnit_RGBAColor == mUnit) {
else if (IsIntegerColorUnit()) {
return mValue.mColor == aOther.mValue.mColor;
}
else if (IsFloatColorUnit()) {
return *mValue.mFloatColor == *aOther.mValue.mFloatColor;
}
else if (UnitHasArrayValue()) {
return *mValue.mArray == *aOther.mValue.mArray;
}
@ -305,6 +312,8 @@ void nsCSSValue::DoReset()
{
if (UnitHasStringValue()) {
mValue.mString->Release();
} else if (IsFloatColorUnit()) {
mValue.mFloatColor->Release();
} else if (UnitHasArrayValue()) {
mValue.mArray->Release();
} else if (eCSSUnit_URL == mUnit) {
@ -375,12 +384,32 @@ void nsCSSValue::SetStringValue(const nsString& aValue,
}
void nsCSSValue::SetColorValue(nscolor aValue)
{
SetIntegerColorValue(aValue, eCSSUnit_RGBAColor);
}
void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit)
{
Reset();
mUnit = eCSSUnit_RGBAColor;
mUnit = aUnit;
NS_ABORT_IF_FALSE(IsIntegerColorUnit(), "bad unit");
mValue.mColor = aValue;
}
void nsCSSValue::SetFloatColorValue(float aComponent1,
float aComponent2,
float aComponent3,
float aAlpha,
nsCSSUnit aUnit)
{
Reset();
mUnit = aUnit;
NS_ABORT_IF_FALSE(IsFloatColorUnit(), "bad unit");
mValue.mFloatColor =
new nsCSSValueFloatColor(aComponent1, aComponent2, aComponent3, aAlpha);
mValue.mFloatColor->AddRef();
}
void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
{
Reset();
@ -633,6 +662,15 @@ void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
}
}
nscolor nsCSSValue::GetColorValue() const
{
NS_ABORT_IF_FALSE(IsNumericColorUnit(), "not a color value");
if (IsFloatColorUnit()) {
return mValue.mFloatColor->GetColorValue(mUnit);
}
return mValue.mColor;
}
bool nsCSSValue::IsNonTransparentColor() const
{
// We have the value in the form it was specified in at this point, so we
@ -640,7 +678,8 @@ bool nsCSSValue::IsNonTransparentColor() const
// rgba notation.
nsDependentString buf;
return
(mUnit == eCSSUnit_RGBAColor && NS_GET_A(GetColorValue()) > 0) ||
(IsIntegerColorUnit() && NS_GET_A(GetColorValue()) > 0) ||
(IsFloatColorUnit() && mValue.mFloatColor->IsNonTransparentColor()) ||
(mUnit == eCSSUnit_Ident &&
!nsGkAtoms::transparent->Equals(GetStringValue(buf))) ||
(mUnit == eCSSUnit_EnumColor);
@ -979,7 +1018,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
NS_ABORT_IF_FALSE(false, "bad color value");
}
}
else if (eCSSUnit_RGBAColor == unit) {
else if (IsNumericColorUnit(unit)) {
nscolor color = GetColorValue();
if (color == NS_RGBA(0, 0, 0, 0)) {
// Use the strictest match for 'transparent' so we do correct
@ -1267,8 +1306,15 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
case eCSSUnit_Calc_Divided: break;
case eCSSUnit_Integer: break;
case eCSSUnit_Enumerated: break;
case eCSSUnit_EnumColor: break;
case eCSSUnit_RGBAColor: break;
case eCSSUnit_EnumColor: break;
case eCSSUnit_RGBColor: break;
case eCSSUnit_RGBAColor: break;
case eCSSUnit_HexColor: break;
case eCSSUnit_ShortHexColor: break;
case eCSSUnit_PercentageRGBColor: break;
case eCSSUnit_PercentageRGBAColor: break;
case eCSSUnit_HSLColor: break;
case eCSSUnit_HSLAColor: break;
case eCSSUnit_Percent: aResult.Append(PRUnichar('%')); break;
case eCSSUnit_Number: break;
case eCSSUnit_Gradient: break;
@ -1426,8 +1472,19 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
case eCSSUnit_EnumColor:
break;
// Color: nothing extra to measure.
// Integer Color: nothing extra to measure.
case eCSSUnit_RGBColor:
case eCSSUnit_RGBAColor:
case eCSSUnit_HexColor:
case eCSSUnit_ShortHexColor:
break;
// Float Color
case eCSSUnit_PercentageRGBColor:
case eCSSUnit_PercentageRGBAColor:
case eCSSUnit_HSLColor:
case eCSSUnit_HSLAColor:
n += mValue.mFloatColor->SizeOfIncludingThis(aMallocSizeOf);
break;
// Float: nothing extra to measure.
@ -2052,6 +2109,54 @@ nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
return n;
}
// --- nsCSSValueFloatColor -------------
bool
nsCSSValueFloatColor::operator==(nsCSSValueFloatColor& aOther) const
{
return mComponent1 == aOther.mComponent1 &&
mComponent2 == aOther.mComponent2 &&
mComponent3 == aOther.mComponent3 &&
mAlpha == aOther.mAlpha;
}
nscolor
nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
{
MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
if (aUnit == eCSSUnit_PercentageRGBColor ||
aUnit == eCSSUnit_PercentageRGBAColor) {
return NS_RGBA(NSToIntRound(mComponent1 * 255.0f),
NSToIntRound(mComponent2 * 255.0f),
NSToIntRound(mComponent3 * 255.0f),
NSToIntRound(mAlpha * 255.0f));
}
// HSL color
MOZ_ASSERT(aUnit == eCSSUnit_HSLColor ||
aUnit == eCSSUnit_HSLAColor);
nscolor hsl = NS_HSL2RGB(mComponent1, mComponent2, mComponent3);
return NS_RGBA(NS_GET_R(hsl),
NS_GET_G(hsl),
NS_GET_B(hsl),
NSToIntRound(mAlpha * 255.0f));
}
bool
nsCSSValueFloatColor::IsNonTransparentColor() const
{
return mAlpha > 0.0f;
}
size_t
nsCSSValueFloatColor::SizeOfIncludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
return n;
}
// --- nsCSSCornerSizes -----------------
nsCSSCornerSizes::nsCSSCornerSizes(void)
@ -2092,4 +2197,3 @@ nsCSSCornerSizes::corners[4] = {
&nsCSSCornerSizes::mBottomRight,
&nsCSSCornerSizes::mBottomLeft,
};

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

@ -209,8 +209,15 @@ enum nsCSSUnit {
eCSSUnit_Integer = 70, // (int) simple value
eCSSUnit_Enumerated = 71, // (int) value has enumerated meaning
eCSSUnit_EnumColor = 80, // (int) enumerated color (kColorKTable)
eCSSUnit_RGBAColor = 81, // (nscolor) an RGBA value
eCSSUnit_EnumColor = 80, // (int) enumerated color (kColorKTable)
eCSSUnit_RGBColor = 81, // (nscolor) an opaque RGBA value specified as rgb()
eCSSUnit_RGBAColor = 82, // (nscolor) an RGBA value specified as rgba()
eCSSUnit_HexColor = 83, // (nscolor) an opaque RGBA value specified as #rrggbb
eCSSUnit_ShortHexColor = 84, // (nscolor) an opaque RGBA value specified as #rgb
eCSSUnit_PercentageRGBColor = 85, // (nsCSSValueFloatColor*)
eCSSUnit_PercentageRGBAColor = 86, // (nsCSSValueFloatColor*)
eCSSUnit_HSLColor = 87, // (nsCSSValueFloatColor*)
eCSSUnit_HSLAColor = 88, // (nsCSSValueFloatColor*)
eCSSUnit_Percent = 90, // (float) 1.0 == 100%) value is percentage of something
eCSSUnit_Number = 91, // (float) value is numeric (usually multiplier, different behavior that percent)
@ -267,6 +274,7 @@ struct nsCSSValuePairList;
struct nsCSSValuePairList_heap;
struct nsCSSValueTriplet;
struct nsCSSValueTriplet_heap;
class nsCSSValueFloatColor;
class nsCSSValue {
public:
@ -349,6 +357,35 @@ public:
bool UnitHasArrayValue() const
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
// Checks for the nsCSSValue being of a particular type of color unit:
//
// - IsIntegerColorUnit returns true for:
// eCSSUnit_RGBColor -- rgb(int,int,int)
// eCSSUnit_RGBAColor -- rgba(int,int,int,float)
// eCSSUnit_HexColor -- #rrggbb
// eCSSUnit_ShortHexColor -- #rgb
//
// - IsFLoatColorUnit returns true for:
// eCSSUnit_PercentageRGBColor -- rgb(%,%,%)
// eCSSUnit_PercentageRGBAColor -- rgba(%,%,%,float)
// eCSSUnit_HSLColor -- hsl(float,%,%)
// eCSSUnit_HSLAColor -- hsla(float,%,%,float)
//
// - IsNumericColorUnit returns true for any of the above units.
//
// Note that color keywords and system colors are represented by
// eCSSUnit_EnumColor and eCSSUnit_Ident.
bool IsIntegerColorUnit() const { return IsIntegerColorUnit(mUnit); }
bool IsFloatColorUnit() const { return IsFloatColorUnit(mUnit); }
bool IsNumericColorUnit() const { return IsNumericColorUnit(mUnit); }
static bool IsIntegerColorUnit(nsCSSUnit aUnit)
{ return eCSSUnit_RGBColor <= aUnit && aUnit <= eCSSUnit_ShortHexColor; }
static bool IsFloatColorUnit(nsCSSUnit aUnit)
{ return eCSSUnit_PercentageRGBColor <= aUnit &&
aUnit <= eCSSUnit_HSLAColor; }
static bool IsNumericColorUnit(nsCSSUnit aUnit)
{ return IsIntegerColorUnit(aUnit) || IsFloatColorUnit(aUnit); }
int32_t GetIntValue() const
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Integer ||
@ -402,12 +439,7 @@ public:
return GetBufferValue(mValue.mString);
}
nscolor GetColorValue() const
{
NS_ABORT_IF_FALSE((mUnit == eCSSUnit_RGBAColor), "not a color value");
return mValue.mColor;
}
nscolor GetColorValue() const;
bool IsNonTransparentColor() const;
Array* GetArrayValue() const
@ -503,6 +535,11 @@ public:
void SetFloatValue(float aValue, nsCSSUnit aUnit);
void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
void SetColorValue(nscolor aValue);
void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit);
void SetFloatColorValue(float aComponent1,
float aComponent2,
float aComponent3,
float aAlpha, nsCSSUnit aUnit);
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage);
@ -573,6 +610,7 @@ protected:
nsCSSValueSharedList* mSharedList;
nsCSSValuePairList_heap* mPairList;
nsCSSValuePairList* mPairListDependent;
nsCSSValueFloatColor* mFloatColor;
} mValue;
};
@ -1285,6 +1323,44 @@ private:
nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) MOZ_DELETE;
};
class nsCSSValueFloatColor {
public:
nsCSSValueFloatColor(float aComponent1, float aComponent2, float aComponent3,
float aAlpha)
: mComponent1(aComponent1)
, mComponent2(aComponent2)
, mComponent3(aComponent3)
, mAlpha(aAlpha)
{
MOZ_COUNT_CTOR(nsCSSValueFloatColor);
}
~nsCSSValueFloatColor()
{
MOZ_COUNT_DTOR(nsCSSValueFloatColor);
}
bool operator==(nsCSSValueFloatColor& aOther) const;
nscolor GetColorValue(nsCSSUnit aUnit) const;
bool IsNonTransparentColor() const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
NS_INLINE_DECL_REFCOUNTING(nsCSSValueFloatColor)
private:
// FIXME: We should not be clamping specified RGB color components.
float mComponent1; // 0..1 for RGB, 0..360 for HSL
float mComponent2; // 0..1
float mComponent3; // 0..1
float mAlpha; // 0..1
nsCSSValueFloatColor(const nsCSSValueFloatColor& aOther) MOZ_DELETE;
nsCSSValueFloatColor& operator=(const nsCSSValueFloatColor& aOther)
MOZ_DELETE;
};
struct nsCSSCornerSizes {
nsCSSCornerSizes(void);
nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);

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

@ -850,7 +850,7 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
bool result = false;
nsCSSUnit unit = aValue.GetUnit();
if (eCSSUnit_RGBAColor == unit) {
if (aValue.IsNumericColorUnit()) {
aResult = aValue.GetColorValue();
result = true;
}