Bug 1216843 - Part 6: Extend eCSSUnit_PercentageRGBAColor to store values greater than 1.0. r?dholbert draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Tue, 09 Aug 2016 11:20:08 +0900
changeset 398374 5f5fabd8f4a9769d3e4a94e5a87d233cda0147bf
parent 398373 1bdd3e71d87df63bb177c20c5c52c2f1c5720976
child 398375 fe1d2166bc66ceb1708baa138e35a1b87c2b1065
push id25511
push userbmo:hiikezoe@mozilla-japan.org
push dateTue, 09 Aug 2016 02:33:32 +0000
reviewersdholbert
bugs1216843
milestone51.0a1
Bug 1216843 - Part 6: Extend eCSSUnit_PercentageRGBAColor to store values greater than 1.0. r?dholbert GetColorValue() for eCSSUnit_PercentageRGBAColor returns a clamped value, Red/Green/Blue/Alpha() returns a raw value instead. MozReview-Commit-ID: 4fbk3WaJhY
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2871,24 +2871,32 @@ nsCSSValueFloatColor::operator==(nsCSSVa
          mAlpha == aOther.mAlpha;
 }
 
 nscolor
 nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
 {
   MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
 
-  if (aUnit == eCSSUnit_PercentageRGBColor ||
-      aUnit == eCSSUnit_PercentageRGBAColor) {
+  if (aUnit == eCSSUnit_PercentageRGBColor) {
     return NS_RGBA(NSToIntRound(mComponent1 * 255.0f),
                    NSToIntRound(mComponent2 * 255.0f),
                    NSToIntRound(mComponent3 * 255.0f),
                    NSToIntRound(mAlpha * 255.0f));
   }
 
+  // We should clamp each component value since eCSSUnit_PercentageRGBAColor
+  // stores values greater than 1.0.
+  if (aUnit == eCSSUnit_PercentageRGBAColor) {
+    return NS_RGBA(mozilla::clamped(NSToIntRound(mComponent1 * 255.0f), 0, 255),
+                   mozilla::clamped(NSToIntRound(mComponent2 * 255.0f), 0, 255),
+                   mozilla::clamped(NSToIntRound(mComponent3 * 255.0f), 0, 255),
+                   mozilla::clamped(NSToIntRound(mAlpha * 255.0f), 0, 255));
+  }
+
   // 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));
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -370,17 +370,20 @@ enum nsCSSUnit {
   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_HexColorAlpha       = 85,   // (nscolor) an opaque RGBA value specified as #rrggbbaa
   eCSSUnit_ShortHexColorAlpha  = 86,   // (nscolor) an opaque RGBA value specified as #rgba
   eCSSUnit_PercentageRGBColor  = 87,   // (nsCSSValueFloatColor*)
-  eCSSUnit_PercentageRGBAColor = 88,   // (nsCSSValueFloatColor*)
+  eCSSUnit_PercentageRGBAColor = 88,   // (nsCSSValueFloatColor*) Each RGB
+                                       // component stores as percent but it
+                                       // allows overflow values,
+                                       // i.e. over 100%.
   eCSSUnit_HSLColor            = 89,   // (nsCSSValueFloatColor*)
   eCSSUnit_HSLAColor           = 90,   // (nsCSSValueFloatColor*)
 
   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)
 
   // Physical length units
   eCSSUnit_PhysicalMillimeter = 200,   // (float) 1/25.4 inch
@@ -718,16 +721,22 @@ public:
   // Not making this inline because that would force us to include
   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
   // all over.
   imgRequestProxy* GetImageValue(nsIDocument* aDocument) const;
 
   nscoord GetFixedLength(nsPresContext* aPresContext) const;
   nscoord GetPixelLength() const;
 
+  nsCSSValueFloatColor* GetFloatColorValue() const
+  {
+    MOZ_ASSERT(IsFloatColorUnit(), "not a float color value");
+    return mValue.mFloatColor;
+  }
+
   void Reset()  // sets to null
   {
     if (mUnit != eCSSUnit_Null)
       DoReset();
   }
 private:
   void DoReset();
 
@@ -1679,30 +1688,37 @@ private:
   {
     MOZ_COUNT_DTOR(nsCSSValueFloatColor);
   }
 
 public:
   bool operator==(nsCSSValueFloatColor& aOther) const;
 
   nscolor GetColorValue(nsCSSUnit aUnit) const;
+  float Red() const { return mComponent1; }
+  float Green() const { return mComponent2; }
+  float Blue() const { return mComponent3; }
+  float Alpha() const { return mAlpha; }
   bool IsNonTransparentColor() const;
 
   void AppendToString(nsCSSUnit aUnit, nsAString& aResult) 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
+  // eCSSUnit_PercentageRGBAColor allows over 1.0 values to store accumulated
+  // values.
+  float mComponent1;  // [0, 1] for RGBColor, RGBAColor, PercentageRGBColor
+                      // [0, float::max()] for PercentageRGBAColor
+                      // [0, 360] for HSL
+  float mComponent2;  // [0, 1]
+  float mComponent3;  // [0, 1]
+  float mAlpha;       // [0, 1]
 
   nsCSSValueFloatColor(const nsCSSValueFloatColor& aOther) = delete;
   nsCSSValueFloatColor& operator=(const nsCSSValueFloatColor& aOther)
                                                                    = delete;
 };
 
 struct nsCSSCornerSizes {
   nsCSSCornerSizes(void);