Bug 1294614 - Part 3: Add DiluteColor(). r?dholbert. draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 26 Aug 2016 09:10:25 +0900
changeset 405879 b73a978b6e424530173f1e061b0cb506f2b60c4d
parent 405878 0a9fae49472c5f04be62d5b8e40d220e8b7935bf
child 529526 cbdd5997e11489603f6394000efdae181c0a2c54
push id27583
push userhiikezoe@mozilla-japan.org
push dateFri, 26 Aug 2016 01:48:04 +0000
reviewersdholbert
bugs1294614
milestone51.0a1
Bug 1294614 - Part 3: Add DiluteColor(). r?dholbert. MozReview-Commit-ID: A82Oesv8aor
layout/style/StyleAnimationValue.cpp
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -1191,16 +1191,42 @@ AddWeightedColors(double aCoeff1, nscolo
   double factor = 1.0 / Aresf;
   uint8_t Ares = NSToIntRound(Aresf * 255.0);
   uint8_t Rres = ClampColor((R1 * aCoeff1 + R2 * aCoeff2) * factor);
   uint8_t Gres = ClampColor((G1 * aCoeff1 + G2 * aCoeff2) * factor);
   uint8_t Bres = ClampColor((B1 * aCoeff1 + B2 * aCoeff2) * factor);
   return NS_RGBA(Rres, Gres, Bres, Ares);
 }
 
+// Multiplies |aColor| by |aDilutionRatio| with premultiplication.
+// (The logic here should pretty closely match AddWeightedColors()' logic.)
+static nscolor
+DiluteColor(nscolor aColor, double aDilutionRatio)
+{
+  MOZ_ASSERT(aDilutionRatio >= 0.0 && aDilutionRatio <= 1.0,
+             "Dilution ratio should be in [0, 1]");
+
+  double A = NS_GET_A(aColor) * (1.0 / 255.0);
+  double Aresf = A * aDilutionRatio;
+  if (Aresf <= 0.0) {
+    return NS_RGBA(0, 0, 0, 0);
+  }
+
+  // Premultiplication
+  double R = NS_GET_R(aColor) * A;
+  double G = NS_GET_G(aColor) * A;
+  double B = NS_GET_B(aColor) * A;
+
+  double factor = 1.0 / Aresf;
+  return NS_RGBA(ClampColor(R * aDilutionRatio * factor),
+                 ClampColor(G * aDilutionRatio * factor),
+                 ClampColor(B * aDilutionRatio * factor),
+                 NSToIntRound(Aresf * 255.0));
+}
+
 static bool
 AddShadowItems(double aCoeff1, const nsCSSValue &aValue1,
                double aCoeff2, const nsCSSValue &aValue2,
                nsCSSValueList **&aResultTail)
 {
   // X, Y, Radius, Spread, Color, Inset
   MOZ_ASSERT(aValue1.GetUnit() == eCSSUnit_Array,
              "wrong unit");
@@ -2379,18 +2405,28 @@ StyleAnimationValue::AddWeighted(nsCSSPr
       aResultValue.SetFloatValue(RestrictValue(aProperty,
         aCoeff1 * aValue1.GetFloatValue() +
         aCoeff2 * aValue2.GetFloatValue()));
       return true;
     }
     case eUnit_Color: {
       nscolor color1 = aValue1.GetColorValue();
       nscolor color2 = aValue2.GetColorValue();
-      nscolor resultColor =
-        AddWeightedColors(aCoeff1, color1, aCoeff2, color2);
+      nscolor resultColor;
+
+      // We are using AddWeighted() with a zero aCoeff2 for colors to
+      // pretend AddWeighted() against transparent color, i.e. rgba(0, 0, 0, 0).
+      // But unpremultiplication in AddWeightedColors() does not work well
+      // for such cases, so we use another function named DiluteColor() which
+      // has a similar logic to AddWeightedColors().
+      if (aCoeff2 == 0.0) {
+        resultColor = DiluteColor(color1, aCoeff1);
+      } else {
+        resultColor = AddWeightedColors(aCoeff1, color1, aCoeff2, color2);
+      }
       aResultValue.SetColorValue(resultColor);
       return true;
     }
     case eUnit_Calc: {
       PixelCalcValue v1 = ExtractCalcValue(aValue1);
       PixelCalcValue v2 = ExtractCalcValue(aValue2);
       double len = aCoeff1 * v1.mLength + aCoeff2 * v2.mLength;
       double pct = aCoeff1 * v1.mPercent + aCoeff2 * v2.mPercent;