Add support for animation of 'visibility' to transitions (but make it a special case for transitions). (Bug 531942) r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Mon, 21 Dec 2009 16:46:25 -0500
changeset 36526 3c8484e98d6290800a1896ecbfc108b6c3d7e56e
parent 36525 bfe4de8f0428de92bdd54c994b8fa321e05fb613
child 36527 eb947f317c42ec7168e44ace57714af65472cfe6
push id10857
push userdbaron@mozilla.com
push dateMon, 21 Dec 2009 21:46:59 +0000
treeherdermozilla-central@48175bb06cb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs531942
milestone1.9.3a1pre
Add support for animation of 'visibility' to transitions (but make it a special case for transitions). (Bug 531942) r=bzbarsky
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleAnimation.h
layout/style/nsTransitionManager.cpp
layout/style/test/test_transitions_per_property.html
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -140,16 +140,24 @@ nsStyleAnimation::ComputeDistance(nsCSSP
           aDistance = PR_ABS(endInt - startInt);
           break;
         }
         default:
           success = PR_FALSE;
           break;
       }
       break;
+   case eUnit_Visibility: {
+      PRInt32 startVal =
+        aStartValue.GetIntValue() == NS_STYLE_VISIBILITY_VISIBLE;
+      PRInt32 endVal =
+        aEndValue.GetIntValue() == NS_STYLE_VISIBILITY_VISIBLE;
+      aDistance = PR_ABS(startVal - endVal);
+      break;
+    }
     case eUnit_Integer: {
       PRInt32 startInt = aStartValue.GetIntValue();
       PRInt32 endInt = aEndValue.GetIntValue();
       aDistance = PR_ABS(endInt - startInt);
       break;
     }
     case eUnit_Coord: {
       nscoord startCoord = aStartValue.GetCoordValue();
@@ -515,16 +523,25 @@ nsStyleAnimation::AddWeighted(nsCSSPrope
           aResultValue.SetIntValue(result, eUnit_Enumerated);
           break;
         }
         default:
           success = PR_FALSE;
           break;
       }
       break;
+    case eUnit_Visibility: {
+      PRInt32 val1 = aValue1.GetIntValue() == NS_STYLE_VISIBILITY_VISIBLE;
+      PRInt32 val2 = aValue2.GetIntValue() == NS_STYLE_VISIBILITY_VISIBLE;
+      double interp = aCoeff1 * val1 + aCoeff2 * val2;
+      PRInt32 result = interp > 0.0 ? NS_STYLE_VISIBILITY_VISIBLE
+                                    : NS_STYLE_VISIBILITY_HIDDEN;
+      aResultValue.SetIntValue(result, eUnit_Visibility);
+      break;
+    }
     case eUnit_Integer: {
       // http://dev.w3.org/csswg/css3-transitions/#animation-of-property-types-
       // says we should use floor
       PRInt32 result = NS_floor(aCoeff1 * double(aValue1.GetIntValue()) +
                                 aCoeff2 * double(aValue2.GetIntValue()));
       if (aProperty == eCSSProperty_font_weight) {
         NS_ASSERTION(result > 0, "unexpected value");
         result -= result % 100;
@@ -964,16 +981,17 @@ nsStyleAnimation::UncomputeValue(nsCSSPr
           SetBothValuesTo(nsCSSValue(eCSSUnit_None));
       } else {
         NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                           "type mismatch");
         static_cast<nsCSSValue*>(aSpecifiedValue)->SetNoneValue();
       }
       break;
     case eUnit_Enumerated:
+    case eUnit_Visibility:
       NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                         "type mismatch");
       static_cast<nsCSSValue*>(aSpecifiedValue)->
         SetIntValue(aComputedValue.GetIntValue(), eCSSUnit_Enumerated);
       break;
     case eUnit_Integer:
       NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
                         "type mismatch");
@@ -1589,16 +1607,17 @@ nsStyleAnimation::Value::operator=(const
   mUnit = aOther.mUnit;
   switch (mUnit) {
     case eUnit_Null:
     case eUnit_Normal:
     case eUnit_Auto:
     case eUnit_None:
       break;
     case eUnit_Enumerated:
+    case eUnit_Visibility:
     case eUnit_Integer:
       mValue.mInt = aOther.mValue.mInt;
       break;
     case eUnit_Coord:
       mValue.mCoord = aOther.mValue.mCoord;
       break;
     case eUnit_Percent:
     case eUnit_Float:
@@ -1777,16 +1796,17 @@ nsStyleAnimation::Value::operator==(cons
 
   switch (mUnit) {
     case eUnit_Null:
     case eUnit_Normal:
     case eUnit_Auto:
     case eUnit_None:
       return PR_TRUE;
     case eUnit_Enumerated:
+    case eUnit_Visibility:
     case eUnit_Integer:
       return mValue.mInt == aOther.mValue.mInt;
     case eUnit_Coord:
       return mValue.mCoord == aOther.mValue.mCoord;
     case eUnit_Percent:
     case eUnit_Float:
       return mValue.mFloat == aOther.mValue.mFloat;
     case eUnit_Color:
--- a/layout/style/nsStyleAnimation.h
+++ b/layout/style/nsStyleAnimation.h
@@ -224,16 +224,18 @@ public:
    * The types and values for the values that we extract and animate.
    */
   enum Unit {
     eUnit_Null, // not initialized
     eUnit_Normal,
     eUnit_Auto,
     eUnit_None,
     eUnit_Enumerated,
+    eUnit_Visibility, // special case for transitions (which converts
+                      // Enumerated to Visibility as needed)
     eUnit_Integer,
     eUnit_Coord,
     eUnit_Percent,
     eUnit_Float,
     eUnit_Color,
     eUnit_CSSValuePair, // nsCSSValuePair* (never null)
     eUnit_CSSRect, // nsCSSRect* (never null)
     eUnit_Dasharray, // nsCSSValueList* (never null)
@@ -354,17 +356,18 @@ public:
   private:
     void FreeValue();
 
     static const PRUnichar* GetBufferValue(nsStringBuffer* aBuffer) {
       return static_cast<PRUnichar*>(aBuffer->Data());
     }
 
     static PRBool IsIntUnit(Unit aUnit) {
-      return aUnit == eUnit_Enumerated || aUnit == eUnit_Integer;
+      return aUnit == eUnit_Enumerated || aUnit == eUnit_Visibility ||
+             aUnit == eUnit_Integer;
     }
     static PRBool IsCSSValuePairUnit(Unit aUnit) {
       return aUnit == eUnit_CSSValuePair;
     }
     static PRBool IsCSSRectUnit(Unit aUnit) {
       return aUnit == eUnit_CSSRect;
     }
     static PRBool IsCSSValueListUnit(Unit aUnit) {
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -518,16 +518,34 @@ nsTransitionManager::StyleContextChanged
       coverRule->CoverValue(pt.mProperty, pt.mStartValue);
     }
   }
 
   return already_AddRefed<nsIStyleRule>(
            static_cast<nsIStyleRule*>(coverRule.forget().get()));
 }
 
+static PRBool
+TransExtractComputedValue(nsCSSProperty aProperty,
+                          nsStyleContext* aStyleContext,
+                          nsStyleAnimation::Value& aComputedValue)
+{
+  PRBool result =
+    nsStyleAnimation::ExtractComputedValue(aProperty, aStyleContext,
+                                           aComputedValue);
+  if (aProperty == eCSSProperty_visibility) {
+    NS_ABORT_IF_FALSE(aComputedValue.GetUnit() ==
+                        nsStyleAnimation::eUnit_Enumerated,
+                      "unexpected unit");
+    aComputedValue.SetIntValue(aComputedValue.GetIntValue(),
+                               nsStyleAnimation::eUnit_Visibility);
+  }
+  return result;
+}
+
 void
 nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
                        const nsTransition& aTransition,
                        nsIContent *aElement,
                        ElementTransitions *&aElementTransitions,
                        nsStyleContext *aOldStyleContext,
                        nsStyleContext *aNewStyleContext,
                        PRBool *aStartedAny,
@@ -547,20 +565,18 @@ nsTransitionManager::ConsiderStartingTra
 
   if (nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) {
     return;
   }
 
   ElementPropertyTransition pt;
   nsStyleAnimation::Value dummyValue;
   PRBool shouldAnimate =
-    nsStyleAnimation::ExtractComputedValue(aProperty, aOldStyleContext,
-                                           pt.mStartValue) &&
-    nsStyleAnimation::ExtractComputedValue(aProperty, aNewStyleContext,
-                                           pt.mEndValue) &&
+    TransExtractComputedValue(aProperty, aOldStyleContext, pt.mStartValue) &&
+    TransExtractComputedValue(aProperty, aNewStyleContext, pt.mEndValue) &&
     pt.mStartValue != pt.mEndValue &&
     // Check that we can interpolate between these values
     // (If this is ever a performance problem, we could add a
     // CanInterpolate method, but it seems fine for now.)
     nsStyleAnimation::Interpolate(aProperty, pt.mStartValue, pt.mEndValue,
                                   0.5, dummyValue);
 
   PRUint32 currentIndex = nsTArray<ElementPropertyTransition>::NoIndex;
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -118,16 +118,17 @@ var supported_properties = {
     "stroke-dashoffset": [ test_length_transition, test_percent_transition ],
     "stroke-miterlimit": [ test_float_aboveOne_transition ],
     "stroke-opacity" : [ test_float_zeroToOne_transition ],
     "stroke-width": [ test_length_transition, test_percent_transition ],
     "text-indent": [ test_length_transition, test_percent_transition ],
     "text-shadow": [ test_shadow_transition ],
     "top": [ test_length_transition, test_percent_transition ],
     "vertical-align": [ test_length_transition, test_percent_transition ],
+    "visibility": [ test_visibility_transition ],
     "width": [ test_length_transition, test_percent_transition ],
     "word-spacing": [ test_length_transition ],
     "z-index": [ test_zindex_transition, test_pos_integer_or_auto_transition ],
 };
 
 var div = document.getElementById("display");
 var cs = getComputedStyle(div, "");
 
@@ -543,12 +544,23 @@ function test_rect_transition(prop) {
        "rect-valued property " + prop + ": can't interpolate auto components");
     div.style.setProperty(prop, "rect(0px, 6px, 4px, 2px)", "");
   }
   div.style.setProperty(prop, "auto", "");
   is(cs.getPropertyValue(prop), "auto",
      "rect-valued property " + prop + ": can't interpolate auto components");
 }
 
+function test_visibility_transition(prop) {
+  div.style.setProperty("-moz-transition-property", "none", "");
+  div.style.setProperty(prop, "visible", "");
+  is(cs.getPropertyValue(prop), "visible",
+     "visibility property " + prop + ": computed value before transition");
+  div.style.setProperty("-moz-transition-property", prop, "");
+  div.style.setProperty(prop, "hidden", "");
+  is(cs.getPropertyValue(prop), "visible",
+     "visibility property " + prop + ": interpolation of visibility");
+}
+
 </script>
 </pre>
 </body>
 </html>