Bug 1321022 pt 5 - Add support for animating the font-variations-setting property. r=dholbert
authorJonathan Kew <jkew@mozilla.com>
Sat, 03 Dec 2016 12:18:41 +0000
changeset 325216 7878d113285818e7a5ec92e4c43cd43a84728db3
parent 325215 b649cf92aa2d04afbfe454ccf31097eb41216b76
child 325217 870d19bb47592adec25736d9e7260bb0ca917fc0
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersdholbert
bugs1321022
milestone53.0a1
Bug 1321022 pt 5 - Add support for animating the font-variations-setting property. r=dholbert
layout/style/StyleAnimationValue.cpp
layout/style/nsCSSPropList.h
layout/style/test/test_transitions_per_property.html
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -1764,16 +1764,17 @@ StyleAnimationValue::ComputeDistance(nsC
           const nsCSSValue &v2 = list2->*(pairListValues[i]);
           nsCSSUnit unit =
             GetCommonUnit(aProperty, v1.GetUnit(), v2.GetUnit());
           if (unit == eCSSUnit_Null) {
             return false;
           }
           double diffsquared = 0.0;
           switch (unit) {
+            case eCSSUnit_Number:
             case eCSSUnit_Pixel: {
               float diff = v1.GetFloatValue() - v2.GetFloatValue();
               diffsquared = diff * diff;
               break;
             }
             case eCSSUnit_Percent: {
               float diff = v1.GetPercentValue() - v2.GetPercentValue();
               diffsquared = diff * diff;
@@ -2268,19 +2269,23 @@ AddCSSValuePairList(nsCSSPropertyID aPro
       const nsCSSValue& v2 = aList2->*(pairListValues[i]);
 
       nsCSSValue& vr = resultPtr->*(pairListValues[i]);
       nsCSSUnit unit =
         GetCommonUnit(aProperty, v1.GetUnit(), v2.GetUnit());
       if (unit == eCSSUnit_Null) {
         return nullptr;
       }
-      if (!AddCSSValuePixelPercentCalc(restrictions, unit,
-                                       aCoeff1, v1,
-                                       aCoeff2, v2, vr)) {
+      if (unit == eCSSUnit_Number) {
+        AddCSSValueNumber(aCoeff1, v1,
+                          aCoeff2, v2,
+                          vr, restrictions);
+      } else if (!AddCSSValuePixelPercentCalc(restrictions, unit,
+                                              aCoeff1, v1,
+                                              aCoeff2, v2, vr)) {
         if (v1 != v2) {
           return nullptr;
         }
         vr = v1;
       }
     }
     aList1 = aList1->mNext;
     aList2 = aList2->mNext;
@@ -4494,16 +4499,46 @@ StyleAnimationValue::ExtractComputedValu
             result->mValue.SetNoneValue();
           }
 
           aComputedValue.SetTransformValue(
               new nsCSSValueSharedList(result.forget()));
           break;
         }
 
+        case eCSSProperty_font_variation_settings: {
+          const nsStyleFont *font =
+            static_cast<const nsStyleFont*>(styleStruct);
+          nsAutoPtr<nsCSSValuePairList> result;
+          if (!font->mFont.fontVariationSettings.IsEmpty()) {
+            // Make a new list that clones the current settings
+            nsCSSValuePairList **resultTail = getter_Transfers(result);
+            for (auto v : font->mFont.fontVariationSettings) {
+              nsCSSValuePairList *clone = new nsCSSValuePairList;
+              // OpenType font tags are stored in nsFont as 32-bit unsigned
+              // values, but represented in CSS as 4-character ASCII strings,
+              // beginning with the high byte of the value. So to clone the
+              // tag here, we append each of its 4 bytes to a string.
+              nsAutoString tagString;
+              tagString.Append(char(v.mTag >> 24));
+              tagString.Append(char(v.mTag >> 16));
+              tagString.Append(char(v.mTag >> 8));
+              tagString.Append(char(v.mTag));
+              clone->mXValue = nsCSSValue(tagString, eCSSUnit_String);
+              clone->mYValue = nsCSSValue(v.mValue, eCSSUnit_Number);
+              *resultTail = clone;
+              resultTail = &clone->mNext;
+            }
+            aComputedValue.SetAndAdoptCSSValuePairListValue(result.forget());
+          } else {
+            aComputedValue.SetNormalValue();
+          }
+          break;
+        }
+
         default:
           MOZ_ASSERT(false, "missing property implementation");
           return false;
       };
       return true;
     case eStyleAnimType_Coord: {
       const nsStyleCoord& coord =
         StyleDataAtOffset<nsStyleCoord>(styleStruct, ssOffset);
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2044,17 +2044,17 @@ CSS_PROP_FONT(
         CSS_PROPERTY_VALUE_PARSER_FUNCTION |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
     "layout.css.font-variations.enabled",
     0,
     nullptr,
     CSS_PROP_NO_OFFSET,
-    eStyleAnimType_Discrete)
+    eStyleAnimType_Custom)
 CSS_PROP_FONT(
     font-weight,
     font_weight,
     FontWeight,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_VALUE_PARSER_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -300,16 +300,20 @@ if (SupportsMaskShorthand()) {
                                             /* test_length_percent_pair_unclamped */ ];
   supported_properties["mask-size"] = [ test_background_size_transition,
                                      // FIXME: We don't currently test clamping,
                                      // since mask-size uses calc() as an
                                      // intermediate form.
                                      /* test_length_percent_pair_clamped */ ];
 }
 
+if (IsCSSPropertyPrefEnabled("layout.css.font-variations.enabled")) {
+  supported_properties["font-variation-settings"] = [ test_font_variations_transition ];
+}
+
 var div = document.getElementById("display");
 var OMTAdiv = document.getElementById("transformTest");
 var cs = getComputedStyle(div, "");
 var OMTACs = getComputedStyle(OMTAdiv, "");
 var winUtils = SpecialPowers.getDOMWindowUtils(window);
 
 function computeMatrix(v) {
   div.style.setProperty("transform", v, "");
@@ -2447,16 +2451,40 @@ function test_transform_transition(prop)
     }
   }
 
   // FIXME: should perhaps test that no clamping occurs
 
   runOMTATest(runAsyncTests, SimpleTest.finish);
 }
 
+function test_font_variations_transition(prop) {
+  is(prop, "font-variation-settings", "only designed for one property");
+
+  div.style.setProperty("transition-property", "none", "");
+  div.style.setProperty(prop, "\"wght\" 0, \"wdth\" 1.5", "");
+  is(cs.getPropertyValue(prop), "\"wght\" 0, \"wdth\" 1.5",
+     "font-variation-settings property " + prop + ": computed value before transition");
+  div.style.setProperty("transition-property", prop, "");
+  div.style.setProperty(prop, "\"wght\" 2, \"wdth\" 0.5", "");
+  is(cs.getPropertyValue(prop), "\"wght\" 0.5, \"wdth\" 1.25",
+     "font-variation-settings property " + prop + ": interpolation of font-variation-settings");
+  check_distance(prop, "\"wght\" 0, \"wdth\" 1.5", "\"wght\" 0.5, \"wdth\" 1.25", "\"wght\" 2, \"wdth\" 0.5");
+
+  div.style.setProperty("transition-property", "none", "");
+  div.style.setProperty(prop, "\"wght\" 2, \"wdth\" 0.5", "");
+  is(cs.getPropertyValue(prop), "\"wght\" 2, \"wdth\" 0.5",
+     "font-variation-settings property " + prop + ": computed value before transition");
+  div.style.setProperty("transition-property", prop, "");
+  div.style.setProperty(prop, "\"wght\" 0, \"wdth\" 1.5", "");
+  is(cs.getPropertyValue(prop), "\"wght\" 1.5, \"wdth\" 0.75",
+     "font-variation-settings property " + prop + ": interpolation of font-variation-settings");
+  check_distance(prop, "\"wght\" 2, \"wdth\" 0.5", "\"wght\" 1.5, \"wdth\" 0.75", "\"wght\" 0, \"wdth\" 1.5");
+}
+
 function runAsyncTests() {
   // These tests check the value on the compositor 2/3rds of the way through
   // the transition.
   // For the transform tests we simply compare the value on the compositor
   // with the computed value, but for the opacity test we check the absolute
   // value as well.
   OMTAdiv.style.setProperty("transition-duration", "300s", "");
   OMTAdiv.style.setProperty("transition-timing-function", "linear", "");