Bug 1299741 part 7 - Support storing ComplexColor in nsCSSValue and StyleAnimationValue. r=heycam

This is a complete rewrite of the original part 8. Instead of storing
the ratio in mValueExtra, all values are stored in a struct in heap,
so that we support range outside [0.0, 1.0] in computation.

MozReview-Commit-ID: 7xUZSgQE5vA

--HG--
extra : rebase_source : 722d2aee06e59cdf061d0daae43d8dbc0a9641b4
This commit is contained in:
Xidorn Quan 2016-09-16 15:30:35 +10:00
Родитель 8f2d2e59dd
Коммит 154df81de1
4 изменённых файлов: 153 добавлений и 0 удалений

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

@ -3211,6 +3211,11 @@ StyleAnimationValue::UncomputeValue(nsCSSPropertyID aProperty,
aSpecifiedValue = *val;
break;
}
case eUnit_ComplexColor: {
aSpecifiedValue.SetComplexColorValue(
do_AddRef(aComputedValue.mValue.mComplexColor));
break;
}
case eUnit_CSSValuePair: {
// Rule node processing expects pair values to be collapsed to a
// single value if both halves would be equal, for most but not
@ -4517,6 +4522,11 @@ StyleAnimationValue::operator=(const StyleAnimationValue& aOther)
mValue.mString = aOther.mValue.mString;
mValue.mString->AddRef();
break;
case eUnit_ComplexColor:
MOZ_ASSERT(aOther.mValue.mComplexColor);
mValue.mComplexColor = aOther.mValue.mComplexColor;
mValue.mComplexColor->AddRef();
break;
}
return *this;
@ -4594,6 +4604,27 @@ StyleAnimationValue::SetCurrentColorValue()
mUnit = eUnit_CurrentColor;
}
void
StyleAnimationValue::SetComplexColorValue(const StyleComplexColor& aColor)
{
if (aColor.IsCurrentColor()) {
SetCurrentColorValue();
} else if (aColor.IsNumericColor()) {
SetColorValue(aColor.mColor);
} else {
SetComplexColorValue(do_AddRef(new ComplexColorValue(aColor)));
}
}
void
StyleAnimationValue::SetComplexColorValue(
already_AddRefed<ComplexColorValue> aValue)
{
FreeValue();
mUnit = eUnit_ComplexColor;
mValue.mComplexColor = aValue.take();
}
void
StyleAnimationValue::SetUnparsedStringValue(const nsString& aString)
{
@ -4712,6 +4743,8 @@ StyleAnimationValue::FreeValue()
} else if (IsStringUnit(mUnit)) {
MOZ_ASSERT(mValue.mString, "expecting non-null string");
mValue.mString->Release();
} else if (mUnit == eUnit_ComplexColor) {
mValue.mComplexColor->Release();
}
}
@ -4768,6 +4801,8 @@ StyleAnimationValue::operator==(const StyleAnimationValue& aOther) const
case eUnit_UnparsedString:
return (NS_strcmp(GetStringBufferValue(),
aOther.GetStringBufferValue()) == 0);
case eUnit_ComplexColor:
return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
}
NS_NOTREACHED("incomplete case");

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

@ -320,6 +320,7 @@ public:
eUnit_Color, // nsCSSValue* (never null), always with an nscolor or
// an nsCSSValueFloatColor
eUnit_CurrentColor,
eUnit_ComplexColor, // ComplexColorValue* (never null)
eUnit_Calc, // nsCSSValue* (never null), always with a single
// calc() expression that's either length or length+percent
eUnit_ObjectPosition, // nsCSSValue* (never null), always with a
@ -354,6 +355,7 @@ private:
nsCSSValueSharedList* mCSSValueSharedList;
nsCSSValuePairList* mCSSValuePairList;
nsStringBuffer* mString;
css::ComplexColorValue* mComplexColor;
} mValue;
public:
@ -431,6 +433,14 @@ public:
/// @return the scale for this value, calculated with reference to @aForFrame.
gfxSize GetScaleValue(const nsIFrame* aForFrame) const;
const css::ComplexColorData& GetComplexColorData() const {
MOZ_ASSERT(mUnit == eUnit_ComplexColor, "unit mismatch");
return *mValue.mComplexColor;
}
StyleComplexColor GetStyleComplexColorValue() const {
return GetComplexColorData().ToComplexColor();
}
UniquePtr<nsCSSValueList> TakeCSSValueListValue() {
nsCSSValueList* list = GetCSSValueListValue();
mValue.mCSSValueList = nullptr;
@ -487,6 +497,8 @@ public:
void SetFloatValue(float aFloat);
void SetColorValue(nscolor aColor);
void SetCurrentColorValue();
void SetComplexColorValue(const StyleComplexColor& aColor);
void SetComplexColorValue(already_AddRefed<css::ComplexColorValue> aValue);
void SetUnparsedStringValue(const nsString& aString);
void SetCSSValueArrayValue(nsCSSValue::Array* aValue, Unit aUnit);

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

@ -161,6 +161,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
mValue.mFloatColor = aCopy.mValue.mFloatColor;
mValue.mFloatColor->AddRef();
}
else if (eCSSUnit_ComplexColor == mUnit) {
mValue.mComplexColor = aCopy.mValue.mComplexColor;
mValue.mComplexColor->AddRef();
}
else if (UnitHasArrayValue()) {
mValue.mArray = aCopy.mValue.mArray;
mValue.mArray->AddRef();
@ -271,6 +275,9 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
else if (IsFloatColorUnit()) {
return *mValue.mFloatColor == *aOther.mValue.mFloatColor;
}
else if (eCSSUnit_ComplexColor == mUnit) {
return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
}
else if (UnitHasArrayValue()) {
return *mValue.mArray == *aOther.mValue.mArray;
}
@ -377,6 +384,8 @@ void nsCSSValue::DoReset()
mValue.mString->Release();
} else if (IsFloatColorUnit()) {
mValue.mFloatColor->Release();
} else if (eCSSUnit_ComplexColor == mUnit) {
mValue.mComplexColor->Release();
} else if (UnitHasArrayValue()) {
mValue.mArray->Release();
} else if (eCSSUnit_URL == mUnit) {
@ -485,6 +494,14 @@ nsCSSValue::SetRGBAColorValue(const RGBAColorData& aValue)
aValue.mA, eCSSUnit_PercentageRGBAColor);
}
void
nsCSSValue::SetComplexColorValue(already_AddRefed<ComplexColorValue> aValue)
{
Reset();
mUnit = eCSSUnit_ComplexColor;
mValue.mComplexColor = aValue.take();
}
void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
{
Reset();
@ -1573,6 +1590,18 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
mValue.mFloatColor->AppendToString(unit, aResult);
}
}
else if (eCSSUnit_ComplexColor == unit) {
StyleComplexColor color = GetStyleComplexColorValue();
nsCSSValue serializable;
if (color.IsCurrentColor()) {
serializable.SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
} else if (color.IsNumericColor()) {
serializable.SetColorValue(color.mColor);
} else {
MOZ_ASSERT_UNREACHABLE("Cannot serialize a complex color");
}
serializable.AppendToString(aProperty, aResult, aSerialization);
}
else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
aResult.AppendLiteral("url(");
nsStyleUtil::AppendEscapedCSSString(
@ -1869,6 +1898,7 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
case eCSSUnit_PercentageRGBAColor: break;
case eCSSUnit_HSLColor: break;
case eCSSUnit_HSLAColor: break;
case eCSSUnit_ComplexColor: break;
case eCSSUnit_Percent: aResult.Append(char16_t('%')); break;
case eCSSUnit_Number: break;
case eCSSUnit_Gradient: break;
@ -2056,6 +2086,11 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
n += mValue.mFloatColor->SizeOfIncludingThis(aMallocSizeOf);
break;
// Complex Color
case eCSSUnit_ComplexColor:
n += mValue.mComplexColor->SizeOfIncludingThis(aMallocSizeOf);
break;
// Float: nothing extra to measure.
case eCSSUnit_Percent:
case eCSSUnit_Number:
@ -2784,6 +2819,17 @@ css::ImageValue::~ImageValue()
}
}
size_t
css::ComplexColorValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
// Only measure it if it's unshared, to avoid double-counting.
size_t n = 0;
if (mRefCnt <= 1) {
n += aMallocSizeOf(this);
}
return n;
}
nsCSSValueGradientStop::nsCSSValueGradientStop()
: mLocation(eCSSUnit_None),
mColor(eCSSUnit_Null),

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

@ -13,6 +13,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/SheetType.h"
#include "mozilla/StyleComplexColor.h"
#include "mozilla/UniquePtr.h"
#include "nsIPrincipal.h"
@ -345,6 +346,56 @@ struct RGBAColorData
}
};
struct ComplexColorData
{
RGBAColorData mColor;
float mForegroundRatio;
ComplexColorData() = default;
ComplexColorData(const RGBAColorData& aColor, float aForegroundRatio)
: mColor(aColor), mForegroundRatio(aForegroundRatio) {}
ComplexColorData(nscolor aColor, float aForegroundRatio)
: mColor(aColor), mForegroundRatio(aForegroundRatio) {}
explicit ComplexColorData(const StyleComplexColor& aColor)
: mColor(aColor.mColor)
, mForegroundRatio(aColor.mForegroundRatio * (1.0f / 255.0f)) {}
bool operator==(const ComplexColorData& aOther) const
{
return mForegroundRatio == aOther.mForegroundRatio &&
(IsCurrentColor() || mColor == aOther.mColor);
}
bool operator!=(const ComplexColorData& aOther) const
{
return !(*this == aOther);
}
bool IsCurrentColor() const { return mForegroundRatio >= 1.0f; }
bool IsNumericColor() const { return mForegroundRatio <= 0.0f; }
StyleComplexColor ToComplexColor() const
{
return StyleComplexColor(
mColor.ToColor(), ClampColor(mForegroundRatio * 255.0f));
}
};
struct ComplexColorValue final : public ComplexColorData
{
// Just redirect any parameter to the data struct.
template<typename... Args>
explicit ComplexColorValue(Args&&... aArgs)
: ComplexColorData(Forward<Args>(aArgs)...) {}
ComplexColorValue(const ComplexColorValue&) = delete;
NS_INLINE_DECL_REFCOUNTING(ComplexColorValue)
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
private:
~ComplexColorValue() {}
};
} // namespace css
} // namespace mozilla
@ -439,6 +490,7 @@ enum nsCSSUnit {
// allowed.
eCSSUnit_HSLColor = 89, // (nsCSSValueFloatColor*)
eCSSUnit_HSLAColor = 90, // (nsCSSValueFloatColor*)
eCSSUnit_ComplexColor = 91, // (ComplexColorValue*)
eCSSUnit_Percent = 100, // (float) 1.0 == 100%) value is percentage of something
eCSSUnit_Number = 101, // (float) value is numeric (usually multiplier, different behavior than percent)
@ -687,6 +739,11 @@ public:
nscolor GetColorValue() const;
bool IsNonTransparentColor() const;
mozilla::StyleComplexColor GetStyleComplexColorValue() const
{
MOZ_ASSERT(mUnit == eCSSUnit_ComplexColor);
return mValue.mComplexColor->ToComplexColor();
}
Array* GetArrayValue() const
{
@ -818,6 +875,8 @@ public:
float aComponent3,
float aAlpha, nsCSSUnit aUnit);
void SetRGBAColorValue(const mozilla::css::RGBAColorData& aValue);
void SetComplexColorValue(
already_AddRefed<mozilla::css::ComplexColorValue> aValue);
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage);
@ -925,6 +984,7 @@ protected:
nsCSSValuePairList* mPairListDependent;
nsCSSValueFloatColor* MOZ_OWNING_REF mFloatColor;
mozilla::css::FontFamilyListRefCnt* MOZ_OWNING_REF mFontFamilyList;
mozilla::css::ComplexColorValue* MOZ_OWNING_REF mComplexColor;
} mValue;
};