Implement dppx units [css3-images] for resolution media query. (Bug 741644) r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Sat, 07 Jul 2012 21:41:27 -0700
changeset 98635 a9a5832fc7989042c4d1fe1cb898b8a5a8408f2e
parent 98634 6e509374cbd1e02671455ab3ecdfa94d4e81613b
child 98636 70995c6989e46afe5cb183b66a33ddc640591f2f
push id23066
push userryanvm@gmail.com
push dateSun, 08 Jul 2012 17:48:41 +0000
treeherdermozilla-central@221f1a184f67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs741644
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Implement dppx units [css3-images] for resolution media query. (Bug 741644) r=bzbarsky
layout/style/nsCSSParser.cpp
layout/style/nsCSSStyleSheet.cpp
layout/style/nsMediaFeatures.h
layout/style/test/test_media_queries.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1836,16 +1836,18 @@ CSSParserImpl::ParseMediaQueryExpression
         UngetToken();
         break;
       }
       // No worries about whether unitless zero is allowed, since the
       // value must be positive (and we checked that above).
       NS_ASSERTION(!mToken.mIdent.IsEmpty(), "unit lied");
       if (mToken.mIdent.LowerCaseEqualsLiteral("dpi")) {
         expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Inch);
+      } else if (mToken.mIdent.LowerCaseEqualsLiteral("dppx")) {
+        expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Pixel);
       } else if (mToken.mIdent.LowerCaseEqualsLiteral("dpcm")) {
         expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Centimeter);
       } else {
         rv = false;
       }
       break;
     case nsMediaFeature::eEnumerated:
       rv = ParseVariant(expr->mValue, VARIANT_KEYWORD,
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -245,27 +245,35 @@ nsMediaExpression::Matches(nsPresContext
                 requiredNum = required.GetArrayValue()->Item(0).GetIntValue(),
                 requiredDen = required.GetArrayValue()->Item(1).GetIntValue();
         cmp = DoCompare(actualNum * requiredDen, requiredNum * actualDen);
       }
       break;
     case nsMediaFeature::eResolution:
       {
         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Inch ||
+                     actual.GetUnit() == eCSSUnit_Pixel ||
                      actual.GetUnit() == eCSSUnit_Centimeter,
                      "bad actual value");
         NS_ASSERTION(required.GetUnit() == eCSSUnit_Inch ||
+                     required.GetUnit() == eCSSUnit_Pixel ||
                      required.GetUnit() == eCSSUnit_Centimeter,
                      "bad required value");
         float actualDPI = actual.GetFloatValue();
-        if (actual.GetUnit() == eCSSUnit_Centimeter)
+        if (actual.GetUnit() == eCSSUnit_Centimeter) {
           actualDPI = actualDPI * 2.54f;
+        } else if (actual.GetUnit() == eCSSUnit_Pixel) {
+          actualDPI = actualDPI * 96.0f;
+        }
         float requiredDPI = required.GetFloatValue();
-        if (required.GetUnit() == eCSSUnit_Centimeter)
+        if (required.GetUnit() == eCSSUnit_Centimeter) {
           requiredDPI = requiredDPI * 2.54f;
+        } else if (required.GetUnit() == eCSSUnit_Pixel) {
+          requiredDPI = requiredDPI * 96.0f;
+        }
         cmp = DoCompare(actualDPI, requiredDPI);
       }
       break;
     case nsMediaFeature::eEnumerated:
       {
         NS_ASSERTION(actual.GetUnit() == eCSSUnit_Enumerated,
                      "bad actual value");
         NS_ASSERTION(required.GetUnit() == eCSSUnit_Enumerated,
@@ -427,16 +435,18 @@ nsMediaQuery::AppendToString(nsAString& 
             array->Item(1).AppendToString(eCSSProperty_z_index, aString);
           }
           break;
         case nsMediaFeature::eResolution:
           {
             aString.AppendFloat(expr.mValue.GetFloatValue());
             if (expr.mValue.GetUnit() == eCSSUnit_Inch) {
               aString.AppendLiteral("dpi");
+            } else if (expr.mValue.GetUnit() == eCSSUnit_Pixel) {
+              aString.AppendLiteral("dppx");
             } else {
               NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Centimeter,
                            "bad unit");
               aString.AppendLiteral("dpcm");
             }
           }
           break;
         case nsMediaFeature::eEnumerated:
--- a/layout/style/nsMediaFeatures.h
+++ b/layout/style/nsMediaFeatures.h
@@ -29,17 +29,18 @@ struct nsMediaFeature {
     enum ValueType {
         // All value types allow eCSSUnit_Null to indicate that no value
         // was given (in addition to the types listed below).
         eLength,     // values are such that nsCSSValue::IsLengthUnit() is true
         eInteger,    // values are eCSSUnit_Integer
         eFloat,      // values are eCSSUnit_Number
         eBoolInteger,// values are eCSSUnit_Integer (0, -0, or 1 only)
         eIntRatio,   // values are eCSSUnit_Array of two eCSSUnit_Integer
-        eResolution, // values are in eCSSUnit_Inch (for dpi) or
+        eResolution, // values are in eCSSUnit_Inch (for dpi),
+                     //   eCSSUnit_Pixel (for dppx), or
                      //   eCSSUnit_Centimeter (for dpcm)
         eEnumerated, // values are eCSSUnit_Enumerated (uses keyword table)
         eIdent       // values are eCSSUnit_Ident
         // Note that a number of pieces of code (both for parsing and
         // for matching of valueless expressions) assume that all numeric
         // value types cannot be negative.  The parsing code also does
         // not allow zeros in eIntRatio types.
     };
--- a/layout/style/test/test_media_queries.html
+++ b/layout/style/test/test_media_queries.html
@@ -459,18 +459,22 @@ function run() {
   features = [ "resolution", "min-resolution", "max-resolution" ];
   for (i in features) {
     feature = features[i];
     expression_should_be_parseable(feature + ": 3dpi");
     expression_should_be_parseable(feature + ":3dpi");
     expression_should_be_parseable(feature + ": 3.0dpi");
     expression_should_be_parseable(feature + ": 3.4dpi");
     expression_should_be_parseable(feature + "\t: 120dpcm");
+    expression_should_be_parseable(feature + ": 1dppx");
+    expression_should_be_parseable(feature + ": 1.5dppx");
+    expression_should_be_parseable(feature + ": 2.0dppx");
     expression_should_not_be_parseable(feature + ": 0dpi");
     expression_should_not_be_parseable(feature + ": -3dpi");
+    expression_should_not_be_parseable(feature + ": 0dppx");
   }
 
   // Find the resolution using max-resolution
   var resolution = 0;
   do {
     ++resolution;
     if (resolution > 10000) {
       ok(false, "resolution greater than 10000dpi???");
@@ -480,16 +484,17 @@ function run() {
 
   // resolution should now be Math.ceil() of the actual resolution.
   var dpi_high;
   var dpi_low = resolution - 1;
   if (query_applies("(min-resolution: " + resolution + "dpi)")) {
     // It's exact!
     is(resolution % 96, 0, "resolution should be a multiple of 96dpi");
     should_apply("(resolution: " + resolution + "dpi)");
+    should_apply("(resolution: " + Math.floor(resolution/96) + "dppx)");
     should_not_apply("(resolution: " + (resolution + 1) + "dpi)");
     should_not_apply("(resolution: " + (resolution - 1) + "dpi)");
     dpi_high = resolution + 1;
   } else {
 	// We have no way to test resolution applying since it need not be
 	// an integer.
     ok(false, "resolution should be a multiple of 96dpi");
     should_not_apply("(resolution: " + resolution + "dpi)");