Add support for animation of font-weight and font-stretch. (Bug 528234) r=dholbert
authorL. David Baron <dbaron@dbaron.org>
Sat, 14 Nov 2009 19:16:59 -0800
changeset 34870 fa53068a3db579abad0e97249fbded96d8217fae
parent 34869 d49d4151ad1d5e1aa422586d7d0fa09371aab565
child 34871 40713937700b28cba5f732fce3874999cc02031c
push id10315
push userdbaron@mozilla.com
push dateSun, 15 Nov 2009 03:17:29 +0000
treeherdermozilla-central@6af36fcff9bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs528234
milestone1.9.3a1pre
Add support for animation of font-weight and font-stretch. (Bug 528234) r=dholbert
layout/style/nsCSSPropList.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleAnimation.cpp
layout/style/test/test_transitions_per_property.html
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1447,18 +1447,18 @@ CSS_PROP_FONT(
     font-stretch,
     font_stretch,
     FontStretch,
     CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
     Font,
     mStretch,
     eCSSType_Value,
     kFontStretchKTable,
-    CSS_PROP_NO_OFFSET,
-    eStyleAnimType_None)
+    offsetof(nsStyleFont, mFont.stretch),
+    eStyleAnimType_Custom)
 CSS_PROP_FONT(
     font-style,
     font_style,
     FontStyle,
     CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
     Font,
     mStyle,
     eCSSType_Value,
@@ -1480,18 +1480,18 @@ CSS_PROP_FONT(
     font-weight,
     font_weight,
     FontWeight,
     CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
     Font,
     mWeight,
     eCSSType_Value,
     kFontWeightKTable,
-    CSS_PROP_NO_OFFSET,
-    eStyleAnimType_None)
+    offsetof(nsStyleFont, mFont.weight),
+    eStyleAnimType_Custom)
 CSS_PROP_UIRESET(
     -moz-force-broken-image-icon,
     force_broken_image_icon,
     MozForceBrokenImageIcon,
     0,
     UserInterface,
     mForceBrokenImageIcon,
     eCSSType_Value,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1258,16 +1258,18 @@ nsComputedDOMStyle::GetFontWeight(nsIDOM
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   const nsStyleFont* font = GetStyleFont();
 
   // XXX This doesn't deal with bolder/lighter very well.
   const nsCSSKeyword enum_weight =
     nsCSSProps::ValueToKeywordEnum(font->mFont.weight,
                                    nsCSSProps::kFontWeightKTable);
+  // FIXME: Since 'normal' isn't in the keyword table, we serialize 700
+  // to bold but 400 as-is.
   if (enum_weight != eCSSKeyword_UNKNOWN) {
     val->SetIdent(enum_weight);
   } else {
     val->SetNumber(font->mFont.weight);
   }
 
   return CallQueryInterface(val, aValue);
 }
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -123,18 +123,31 @@ nsStyleAnimation::ComputeDistance(nsCSSP
                                   double& aDistance)
 {
   Unit commonUnit = GetCommonUnit(aStartValue.GetUnit(), aEndValue.GetUnit());
 
   PRBool success = PR_TRUE;
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_None:
+      success = PR_FALSE;
+      break;
     case eUnit_Enumerated:
-      success = PR_FALSE;
+      switch (aProperty) {
+        case eCSSProperty_font_stretch: {
+          // just like eUnit_Integer.
+          PRInt32 startInt = aStartValue.GetIntValue();
+          PRInt32 endInt = aEndValue.GetIntValue();
+          aDistance = PR_ABS(endInt - startInt);
+          break;
+        }
+        default:
+          success = PR_FALSE;
+          break;
+      }
       break;
     case eUnit_Integer: {
       PRInt32 startInt = aStartValue.GetIntValue();
       PRInt32 endInt = aEndValue.GetIntValue();
       aDistance = PR_ABS(endInt - startInt);
       break;
     }
     case eUnit_Coord: {
@@ -441,26 +454,42 @@ nsStyleAnimation::AddWeighted(nsCSSPrope
   // unit-type, if they don't already match it. (Or would it make sense to do
   // that in GetCommonUnit? in which case maybe ConvertToCommonUnit would be
   // better.)
 
   PRBool success = PR_TRUE;
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_None:
+      success = PR_FALSE;
+      break;
     case eUnit_Enumerated:
-      success = PR_FALSE;
+      switch (aProperty) {
+        case eCSSProperty_font_stretch: {
+          // Animate just like eUnit_Integer.
+          PRInt32 result = NS_floor(aCoeff1 * double(aValue1.GetIntValue()) +
+                                    aCoeff2 * double(aValue2.GetIntValue()));
+          aResultValue.SetIntValue(result, eUnit_Enumerated);
+          break;
+        }
+        default:
+          success = PR_FALSE;
+          break;
+      }
       break;
     case eUnit_Integer: {
       // http://dev.w3.org/csswg/css3-transitions/#animation-of-property-types-
       // says we should use floor
-      aResultValue.SetIntValue(NS_floor(
-          aCoeff1 * double(aValue1.GetIntValue()) +
-          aCoeff2 * double(aValue2.GetIntValue())),
-        eUnit_Integer);
+      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;
+      }
+      aResultValue.SetIntValue(result, eUnit_Integer);
       break;
     }
     case eUnit_Coord: {
       aResultValue.SetCoordValue(NSToCoordRound(
         aCoeff1 * aValue1.GetCoordValue() +
         aCoeff2 * aValue2.GetCoordValue()));
       break;
     }
@@ -1075,16 +1104,39 @@ nsStyleAnimation::ExtractComputedValue(n
             aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
                                                         eUnit_Dasharray);
           } else {
             aComputedValue.SetNoneValue();
           }
           break;
         }
 
+        case eCSSProperty_font_stretch: {
+          PRInt16 stretch =
+            static_cast<const nsStyleFont*>(styleStruct)->mFont.stretch;
+          PR_STATIC_ASSERT(NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED == -4);
+          PR_STATIC_ASSERT(NS_STYLE_FONT_STRETCH_ULTRA_EXPANDED == 4);
+          if (stretch < NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED ||
+              stretch > NS_STYLE_FONT_STRETCH_ULTRA_EXPANDED) {
+            return PR_FALSE;
+          }
+          aComputedValue.SetIntValue(stretch, eUnit_Enumerated);
+          return PR_TRUE;
+        }
+
+        case eCSSProperty_font_weight: {
+          PRUint16 weight =
+            static_cast<const nsStyleFont*>(styleStruct)->mFont.weight;
+          if (weight % 100 != 0) {
+            return PR_FALSE;
+          }
+          aComputedValue.SetIntValue(weight, eUnit_Integer);
+          return PR_TRUE;
+        }
+
         default:
           NS_ABORT_IF_FALSE(PR_FALSE, "missing property implementation");
           return PR_FALSE;
       };
       return PR_TRUE;
     case eStyleAnimType_Coord:
       return StyleCoordToValue(*static_cast<const nsStyleCoord*>(
         StyleDataAtOffset(styleStruct, ssOffset)), aComputedValue);
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -72,16 +72,18 @@ var supported_properties = {
     "color": [ test_color_transition ],
     "fill": [ test_color_transition ],
     "fill-opacity" : [ test_float_zeroToOne_transition ],
     "flood-color": [ test_color_transition ],
     "flood-opacity" : [ test_float_zeroToOne_transition ],
     "font-size": [ test_length_transition, test_percent_transition ],
     "font-size-adjust": [ test_float_zeroToOne_transition,
                           test_float_aboveOne_transition ],
+    "font-stretch": [ test_font_stretch ],
+    "font-weight": [ test_font_weight ],
     "height": [ test_length_transition, test_percent_transition ],
     "left": [ test_length_transition, test_percent_transition ],
     "letter-spacing": [ test_length_transition ],
     "lighting-color": [ test_color_transition ],
     "line-height": [ test_length_transition, test_percent_transition ],
     "margin-bottom": [ test_length_transition, test_percent_transition ],
     "margin-left": [ test_length_transition, test_percent_transition ],
     "margin-right": [ test_length_transition, test_percent_transition ],
@@ -426,12 +428,61 @@ function test_zindex_transition(prop) {
   div.style.setProperty(prop, "-4", "");
   is(cs.getPropertyValue(prop), "-4",
      "integer-valued property " + prop + ": computed value before transition");
   div.style.setProperty(prop, "8", "");
   is(cs.getPropertyValue(prop), "2",
      "integer-valued property " + prop + ": interpolation of lengths");
 }
 
+function test_font_stretch(prop) {
+  is(prop, "font-stretch", "only designed for one property");
+
+  div.style.setProperty("-moz-transition-property", "none", "");
+  div.style.setProperty(prop, "normal", "");
+  is(cs.getPropertyValue(prop), "normal",
+     "font-stretch property " + prop + ": computed value before transition");
+  div.style.setProperty("-moz-transition-property", prop, "");
+  div.style.setProperty(prop, "ultra-expanded", "");
+  is(cs.getPropertyValue(prop), "expanded",
+     "font-stretch property " + prop + ": interpolation of font-stretches");
+  div.style.setProperty(prop, "wider", "");
+  is(cs.getPropertyValue(prop), "wider",
+     "font-stretch property " + prop + ": can't interpolate wider/narrower");
+  div.style.setProperty(prop, "expanded", "");
+  is(cs.getPropertyValue(prop), "expanded",
+     "font-stretch property " + prop + ": computed value before transition");
+  div.style.setProperty(prop, "extra-condensed", "");
+  is(cs.getPropertyValue(prop), "semi-condensed",
+     "font-stretch property " + prop + ": interpolation of font-stretches");
+}
+
+function test_font_weight(prop) {
+  is(prop, "font-weight", "only designed for one property");
+
+  div.style.setProperty("-moz-transition-property", "none", "");
+  div.style.setProperty(prop, "normal", "");
+  // FIXME: Why does this give 400 but bold gives bold?
+  // (Yes, it's normal not being in the prop table...)
+  is(cs.getPropertyValue(prop), "400",
+     "font-weight property " + prop + ": computed value before transition");
+  div.style.setProperty("-moz-transition-property", prop, "");
+  div.style.setProperty(prop, "900", "");
+  is(cs.getPropertyValue(prop), "600",
+     "font-weight property " + prop + ": interpolation of font-weights");
+  div.style.setProperty(prop, "lighter", "");
+  // We currently get 399; mark this as todo.
+  todo_is(cs.getPropertyValue(prop), "lighter",
+     "font-weight property " + prop + ": can't interpolate bolder/lighter");
+  div.style.setProperty(prop, "700", "");
+  is(cs.getPropertyValue(prop), "bold",
+     "font-weight property " + prop + ": computed value before transition");
+  div.style.setProperty(prop, "100", "");
+  // FIXME: Why does this give 400 but bold gives bold?
+  // (Yes, it's normal not being in the prop table...)
+  is(cs.getPropertyValue(prop), "400",
+     "font-weight property " + prop + ": interpolation of font-weights");
+}
+
 </script>
 </pre>
 </body>
 </html>