2010-11-16 Alexander Pavlov <apavlov@chromium.org>
authorapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Nov 2010 11:39:59 +0000 (11:39 +0000)
committerapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Nov 2010 11:39:59 +0000 (11:39 +0000)
        Reviewed by Simon Fraser.

        CSSPrimitiveValue.getFloatValue does not convert sizes
        https://bugs.webkit.org/show_bug.cgi?id=35770

        Extended getFloatValueForUnit and CSSPrimitiveValue tests. The former has been made text-only,
        which allowed to get rid of a number of unnecessary baselines.

        * fast/css/CSSPrimitiveValue-exceptions-expected.txt:
        * fast/css/getFloatValueForUnit-expected.txt: Added.
        * fast/css/getFloatValueForUnit.html:
        * fast/css/resources/CSSPrimitiveValue-exceptions.js:
        * platform/chromium-linux/fast/css/getFloatValueForUnit-expected.checksum: Removed.
        * platform/chromium-win/fast/css/getFloatValueForUnit-expected.checksum: Removed.
        * platform/chromium-win/fast/css/getFloatValueForUnit-expected.txt: Removed.
        * platform/mac-leopard/fast/css/getFloatValueForUnit-expected.checksum: Removed.
        * platform/mac/fast/css/getFloatValueForUnit-expected.checksum: Removed.
        * platform/mac/fast/css/getFloatValueForUnit-expected.txt: Removed.
        * platform/qt/fast/css/getFloatValueForUnit-expected.txt: Removed.
2010-11-16  Alexander Pavlov  <apavlov@chromium.org>

        Reviewed by Simon Fraser.

        CSSPrimitiveValue.getFloatValue does not convert sizes
        https://bugs.webkit.org/show_bug.cgi?id=35770

        Implemented all same-category unit conversions (length, angle, time, frequency) and retained
        absolute-relative (cm, mm, in, pt, pc) length conversions intact.
        Illegal unit conversion attempts will throw an INVALID_ACCESS_ERR DOMException.

        * css/CSSPrimitiveValue.cpp:
        (WebCore::unitCategory):
        (WebCore::conversionToCanonicalUnitsScaleFactor):
        (WebCore::CSSPrimitiveValue::getDoubleValue):
        (WebCore::CSSPrimitiveValue::canonicalUnitTypeForCategory):
        (WebCore::CSSPrimitiveValue::getDoubleValueInternal):
        (WebCore::CSSPrimitiveValue::getIdent):
        * css/CSSPrimitiveValue.h:
        (WebCore::CSSPrimitiveValue::getFloatValue):
        (WebCore::CSSPrimitiveValue::getIntValue):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@72189 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/CSSPrimitiveValue-exceptions-expected.txt
LayoutTests/fast/css/getFloatValueForUnit-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/getFloatValueForUnit.html
LayoutTests/fast/css/resources/CSSPrimitiveValue-exceptions.js
LayoutTests/platform/chromium-linux/fast/css/getFloatValueForUnit-expected.checksum [deleted file]
LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.checksum [deleted file]
LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.txt [deleted file]
LayoutTests/platform/mac-leopard/fast/css/getFloatValueForUnit-expected.checksum [deleted file]
LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.checksum [deleted file]
LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.txt [deleted file]
LayoutTests/platform/qt/fast/css/getFloatValueForUnit-expected.txt [deleted file]
WebCore/ChangeLog
WebCore/css/CSSPrimitiveValue.cpp
WebCore/css/CSSPrimitiveValue.h

index 0878a0e..471b877 100644 (file)
@@ -1,3 +1,25 @@
+2010-11-16  Alexander Pavlov  <apavlov@chromium.org>
+
+        Reviewed by Simon Fraser.
+
+        CSSPrimitiveValue.getFloatValue does not convert sizes
+        https://bugs.webkit.org/show_bug.cgi?id=35770
+
+        Extended getFloatValueForUnit and CSSPrimitiveValue tests. The former has been made text-only,
+        which allowed to get rid of a number of unnecessary baselines.
+
+        * fast/css/CSSPrimitiveValue-exceptions-expected.txt:
+        * fast/css/getFloatValueForUnit-expected.txt: Added.
+        * fast/css/getFloatValueForUnit.html:
+        * fast/css/resources/CSSPrimitiveValue-exceptions.js:
+        * platform/chromium-linux/fast/css/getFloatValueForUnit-expected.checksum: Removed.
+        * platform/chromium-win/fast/css/getFloatValueForUnit-expected.checksum: Removed.
+        * platform/chromium-win/fast/css/getFloatValueForUnit-expected.txt: Removed.
+        * platform/mac-leopard/fast/css/getFloatValueForUnit-expected.checksum: Removed.
+        * platform/mac/fast/css/getFloatValueForUnit-expected.checksum: Removed.
+        * platform/mac/fast/css/getFloatValueForUnit-expected.txt: Removed.
+        * platform/qt/fast/css/getFloatValueForUnit-expected.txt: Removed.
+
 2010-11-17  Anton Muhin  <antonm@chromium.org>
 
         Not reviewed, disabling three layout tests for Chromium.
index 2a2b047..c4e9e82 100644 (file)
@@ -5,6 +5,12 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_UNKNOWN) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
 PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_STRING) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_HZ) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_S) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_RAD) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_PERCENTAGE) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('height').getFloatValue(CSSPrimitiveValue.CSS_PX) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS div.style.getPropertyCSSValue('height').getFloatValue(CSSPrimitiveValue.CSS_DEG) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
 PASS div.style.getPropertyCSSValue('clip').primitiveType is CSSPrimitiveValue.CSS_RECT
 PASS div.style.getPropertyCSSValue('clip').getFloatValue(CSSPrimitiveValue.CSS_PX) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
 PASS div.style.getPropertyCSSValue('clip').getStringValue() threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
diff --git a/LayoutTests/fast/css/getFloatValueForUnit-expected.txt b/LayoutTests/fast/css/getFloatValueForUnit-expected.txt
new file mode 100644 (file)
index 0000000..a7a43fa
--- /dev/null
@@ -0,0 +1,38 @@
+Testing whether CSSPrimitiveValue.getFloatValue() converts units correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_PT) is 10
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_MM) is 3.527778
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_CM) is 0.352778
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_IN) is 0.138889
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_PC) is 0.833333
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_PX) is 13.333333
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_NUMBER) is 13.333333
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_DEG) is 90
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_RAD) is 1.570796
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_GRAD) is 100
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_NUMBER) is 90
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_MS) is 200
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_S) is 0.2
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_NUMBER) is 200
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_PERCENTAGE) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_MS) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_HZ) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_DEG) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('font-size', CSSPrimitiveValue.CSS_RGBCOLOR) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_PERCENTAGE) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_PX) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_MS) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_HZ) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_RGBCOLOR) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_PERCENTAGE) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_PX) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_DEG) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_HZ) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_RGBCOLOR) threw exception Error: INVALID_ACCESS_ERR: DOM Exception 15.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
index 3df6f56..6876017 100644 (file)
@@ -1,9 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
 <body>
-<div id='d' style="font-size: 10pt"></div>
-10pt = 
+<p id="description"></p>
+<div id="test-div" style="font-size: 10pt; -webkit-transform: rotate(100grad); -webkit-animation-delay: 0.2s;"></div>
+<div id="console"></div>
 <script>
-//CSSPrimitiveValue.CSS_MM
-document.write(document.defaultView.getComputedStyle(document.getElementById('d'), '').getPropertyCSSValue('font-size').getFloatValue(7));
-document.write("mm (should be 3.4395833015441895)");
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var invalidAccessError = "Error: INVALID_ACCESS_ERR: DOM Exception 15";
+
+description("Testing whether CSSPrimitiveValue.getFloatValue() converts units correctly.");
+
+function getFloatValue(propertyName, unit)
+{
+    var result = document.getElementById("test-div").style.getPropertyCSSValue(propertyName).getFloatValue(unit);
+    return Number(result.toFixed(6));
+}
+
+function getFirstFloatValueInList(propertyName, unit)
+{
+    var result = document.getElementById("test-div").style.getPropertyCSSValue(propertyName)[0][0].getFloatValue(unit);
+    return Number(result.toFixed(6));
+}
+
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_PT)", "10");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_MM)", "3.527778");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_CM)", "0.352778");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_IN)", "0.138889");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_PC)", "0.833333");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_PX)", "13.333333");
+shouldBe("getFloatValue('font-size', CSSPrimitiveValue.CSS_NUMBER)", "13.333333");
+shouldBe("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_DEG)", "90");
+shouldBe("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_RAD)", "1.570796");
+shouldBe("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_GRAD)", "100");
+shouldBe("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_NUMBER)", "90");
+shouldBe("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_MS)", "200");
+shouldBe("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_S)", "0.2");
+shouldBe("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_NUMBER)", "200");
+
+shouldThrow("getFloatValue('font-size', CSSPrimitiveValue.CSS_PERCENTAGE)", "invalidAccessError");
+shouldThrow("getFloatValue('font-size', CSSPrimitiveValue.CSS_MS)", "invalidAccessError");
+shouldThrow("getFloatValue('font-size', CSSPrimitiveValue.CSS_HZ)", "invalidAccessError");
+shouldThrow("getFloatValue('font-size', CSSPrimitiveValue.CSS_DEG)", "invalidAccessError");
+shouldThrow("getFloatValue('font-size', CSSPrimitiveValue.CSS_RGBCOLOR)", "invalidAccessError");
+
+shouldThrow("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_PERCENTAGE)", "invalidAccessError");
+shouldThrow("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_PX)", "invalidAccessError");
+shouldThrow("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_MS)", "invalidAccessError");
+shouldThrow("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_HZ)", "invalidAccessError");
+shouldThrow("getFirstFloatValueInList('-webkit-transform', CSSPrimitiveValue.CSS_RGBCOLOR)", "invalidAccessError");
+
+shouldThrow("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_PERCENTAGE)", "invalidAccessError");
+shouldThrow("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_PX)", "invalidAccessError");
+shouldThrow("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_DEG)", "invalidAccessError");
+shouldThrow("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_HZ)", "invalidAccessError");
+shouldThrow("getFloatValue('-webkit-animation-delay', CSSPrimitiveValue.CSS_RGBCOLOR)", "invalidAccessError");
+
+var successfullyParsed = true;
 </script>
+<script src="../js/resources/js-test-post.js"></script>
 </body>
index e196e17..0814727 100644 (file)
@@ -2,6 +2,7 @@ description("This tests that the methods on CSSPrimitiveValue throw exceptions "
 
 div = document.createElement('div');
 div.style.width = "10px";
+div.style.height = "90%";
 div.style.content = "counter(dummy, square)";
 div.style.clip = "rect(0, 0, 1, 1)";
 div.style.color = "rgb(0, 0, 0)";
@@ -12,6 +13,14 @@ var invalidAccessError = "Error: INVALID_ACCESS_ERR: DOM Exception 15";
 shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_UNKNOWN)", "invalidAccessError");
 shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_STRING)", "invalidAccessError");
 
+// Test invalid unit conversions in getFloatValue
+shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_HZ)", "invalidAccessError");
+shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_S)", "invalidAccessError");
+shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_RAD)", "invalidAccessError");
+shouldThrow("div.style.getPropertyCSSValue('width').getFloatValue(CSSPrimitiveValue.CSS_PERCENTAGE)", "invalidAccessError");
+shouldThrow("div.style.getPropertyCSSValue('height').getFloatValue(CSSPrimitiveValue.CSS_PX)", "invalidAccessError");
+shouldThrow("div.style.getPropertyCSSValue('height').getFloatValue(CSSPrimitiveValue.CSS_DEG)", "invalidAccessError");
+
 // Test calling get*Value for CSSPrimitiveValue of the wrong type
 shouldBe("div.style.getPropertyCSSValue('clip').primitiveType", "CSSPrimitiveValue.CSS_RECT");
 shouldThrow("div.style.getPropertyCSSValue('clip').getFloatValue(CSSPrimitiveValue.CSS_PX)", "invalidAccessError");
diff --git a/LayoutTests/platform/chromium-linux/fast/css/getFloatValueForUnit-expected.checksum b/LayoutTests/platform/chromium-linux/fast/css/getFloatValueForUnit-expected.checksum
deleted file mode 100644 (file)
index 7420480..0000000
+++ /dev/null
@@ -1 +0,0 @@
-581af578cc2c940e807aaadba07ae3a8
\ No newline at end of file
diff --git a/LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.checksum b/LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.checksum
deleted file mode 100644 (file)
index ba6d051..0000000
+++ /dev/null
@@ -1 +0,0 @@
-678cf9aeea5f13b68bc3eb6a29242667
\ No newline at end of file
diff --git a/LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.txt b/LayoutTests/platform/chromium-win/fast/css/getFloatValueForUnit-expected.txt
deleted file mode 100644 (file)
index 3af8635..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  RenderBlock {HTML} at (0,0) size 800x600
-    RenderBody {BODY} at (8,8) size 784x584
-      RenderBlock {DIV} at (0,0) size 784x0
-      RenderBlock (anonymous) at (0,0) size 784x20
-        RenderText {#text} at (0,0) size 45x19
-          text run at (0,0) width 45: "10pt = "
-        RenderText {#text} at (45,0) size 378x19
-          text run at (45,0) width 378: "3.4395833015441895mm (should be 3.4395833015441895)"
diff --git a/LayoutTests/platform/mac-leopard/fast/css/getFloatValueForUnit-expected.checksum b/LayoutTests/platform/mac-leopard/fast/css/getFloatValueForUnit-expected.checksum
deleted file mode 100644 (file)
index 16a85b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-f1d7564dc23eb3b50b81971e79a86718
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.checksum b/LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.checksum
deleted file mode 100644 (file)
index 9989872..0000000
+++ /dev/null
@@ -1 +0,0 @@
-345a9be992dbb83badcc86ead2d90ebf
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.txt b/LayoutTests/platform/mac/fast/css/getFloatValueForUnit-expected.txt
deleted file mode 100644 (file)
index 0f81a2c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  RenderBlock {HTML} at (0,0) size 800x600
-    RenderBody {BODY} at (8,8) size 784x584
-      RenderBlock {DIV} at (0,0) size 784x0
-      RenderBlock (anonymous) at (0,0) size 784x18
-        RenderText {#text} at (0,0) size 45x18
-          text run at (0,0) width 45: "10pt = "
-        RenderText {#text} at (45,0) size 383x18
-          text run at (45,0) width 383: "3.4395833015441895mm (should be 3.4395833015441895)"
diff --git a/LayoutTests/platform/qt/fast/css/getFloatValueForUnit-expected.txt b/LayoutTests/platform/qt/fast/css/getFloatValueForUnit-expected.txt
deleted file mode 100644 (file)
index 5d4e470..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  RenderBlock {HTML} at (0,0) size 800x600
-    RenderBody {BODY} at (8,8) size 784x584
-      RenderBlock {DIV} at (0,0) size 784x0
-      RenderBlock (anonymous) at (0,0) size 784x19
-        RenderText {#text} at (0,0) size 44x19
-          text run at (0,0) width 44: "10pt = "
-        RenderText {#text} at (44,0) size 384x19
-          text run at (44,0) width 384: "3.4395833015441895mm (should be 3.4395833015441895)"
-        RenderText {#text} at (0,0) size 0x0
index a3c8abe..7b2a69c 100644 (file)
@@ -1,3 +1,25 @@
+2010-11-16  Alexander Pavlov  <apavlov@chromium.org>
+
+        Reviewed by Simon Fraser.
+
+        CSSPrimitiveValue.getFloatValue does not convert sizes
+        https://bugs.webkit.org/show_bug.cgi?id=35770
+
+        Implemented all same-category unit conversions (length, angle, time, frequency) and retained
+        absolute-relative (cm, mm, in, pt, pc) length conversions intact.
+        Illegal unit conversion attempts will throw an INVALID_ACCESS_ERR DOMException.
+
+        * css/CSSPrimitiveValue.cpp:
+        (WebCore::unitCategory):
+        (WebCore::conversionToCanonicalUnitsScaleFactor):
+        (WebCore::CSSPrimitiveValue::getDoubleValue):
+        (WebCore::CSSPrimitiveValue::canonicalUnitTypeForCategory):
+        (WebCore::CSSPrimitiveValue::getDoubleValueInternal):
+        (WebCore::CSSPrimitiveValue::getIdent):
+        * css/CSSPrimitiveValue.h:
+        (WebCore::CSSPrimitiveValue::getFloatValue):
+        (WebCore::CSSPrimitiveValue::getIntValue):
+
 2010-11-17  Ademar de Souza Reis Jr.  <ademar.reis@openbossa.org>
 
         Reviewed by Andreas Kling.
index 032eb7e..4fc062c 100644 (file)
@@ -36,6 +36,7 @@
 #include "RenderStyle.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/DecimalNumber.h>
+#include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/StringBuffer.h>
 
@@ -47,6 +48,38 @@ using namespace WTF;
 
 namespace WebCore {
 
+static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
+{
+    // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
+    // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
+    switch (type) {
+    case CSSPrimitiveValue::CSS_NUMBER:
+        return CSSPrimitiveValue::UNumber;
+    case CSSPrimitiveValue::CSS_PERCENTAGE:
+        return CSSPrimitiveValue::UPercent;
+    case CSSPrimitiveValue::CSS_PX:
+    case CSSPrimitiveValue::CSS_CM:
+    case CSSPrimitiveValue::CSS_MM:
+    case CSSPrimitiveValue::CSS_IN:
+    case CSSPrimitiveValue::CSS_PT:
+    case CSSPrimitiveValue::CSS_PC:
+        return CSSPrimitiveValue::ULength;
+    case CSSPrimitiveValue::CSS_MS:
+    case CSSPrimitiveValue::CSS_S:
+        return CSSPrimitiveValue::UTime;
+    case CSSPrimitiveValue::CSS_DEG:
+    case CSSPrimitiveValue::CSS_RAD:
+    case CSSPrimitiveValue::CSS_GRAD:
+    case CSSPrimitiveValue::CSS_TURN:
+        return CSSPrimitiveValue::UAngle;
+    case CSSPrimitiveValue::CSS_HZ:
+    case CSSPrimitiveValue::CSS_KHZ:
+        return CSSPrimitiveValue::UFrequency;
+    default:
+        return CSSPrimitiveValue::UOther;
+    }
+}
+
 typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
 static CSSTextCache& cssTextCache()
 {
@@ -55,7 +88,7 @@ static CSSTextCache& cssTextCache()
 }
 
 // A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,
-// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits 
+// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits
 // with less need for refactoring.
 
 inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedIdentifier(int identifier)
@@ -415,11 +448,16 @@ void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
     ec = NO_MODIFICATION_ALLOWED_ERR;
 }
 
-static double scaleFactorForConversion(unsigned short unitType)
+static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
 {
     double factor = 1.0;
+    // FIXME: the switch can be replaced by an array of scale factors.
     switch (unitType) {
+        // These are "canonical" units in their respective categories.
         case CSSPrimitiveValue::CSS_PX:
+        case CSSPrimitiveValue::CSS_DEG:
+        case CSSPrimitiveValue::CSS_MS:
+        case CSSPrimitiveValue::CSS_HZ:
             break;
         case CSSPrimitiveValue::CSS_CM:
             factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
@@ -436,6 +474,19 @@ static double scaleFactorForConversion(unsigned short unitType)
         case CSSPrimitiveValue::CSS_PC:
             factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
             break;
+        case CSSPrimitiveValue::CSS_RAD:
+            factor = 180 / piDouble;
+            break;
+        case CSSPrimitiveValue::CSS_GRAD:
+            factor = 0.9;
+            break;
+        case CSSPrimitiveValue::CSS_TURN:
+            factor = 360;
+            break;
+        case CSSPrimitiveValue::CSS_S:
+        case CSSPrimitiveValue::CSS_KHZ:
+            factor = 1000;
+            break;
         default:
             break;
     }
@@ -443,52 +494,97 @@ static double scaleFactorForConversion(unsigned short unitType)
     return factor;
 }
 
-double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec)
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const
 {
-    ec = 0;
-    if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
+    double result;
+    bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+    if (!success) {
         ec = INVALID_ACCESS_ERR;
         return 0.0;
     }
 
-    if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
-        return m_value.num;
+    ec = 0;
+    return result;
+}
+
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
+{
+    double result;
+    getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+    return result;
+}
+
+CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
+{
+    // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
+    // in each category (based on unitflags).
+    switch (category) {
+    case UNumber:
+        return CSS_NUMBER;
+    case ULength:
+        return CSS_PX;
+    case UPercent:
+        return CSS_UNKNOWN; // Cannot convert between numbers and percent.
+    case UTime:
+        return CSS_MS;
+    case UAngle:
+        return CSS_DEG;
+    case UFrequency:
+        return CSS_HZ;
+    default:
+        return CSS_UNKNOWN;
+    }
+}
 
-    double convertedValue = m_value.num;
+bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
+{
+    if (m_type < CSS_NUMBER || (m_type > CSS_DIMENSION && m_type < CSS_TURN) || requestedUnitType < CSS_NUMBER || (requestedUnitType > CSS_DIMENSION && requestedUnitType < CSS_TURN))
+        return false;
+    if (requestedUnitType == m_type || requestedUnitType == CSS_DIMENSION) {
+        *result = m_value.num;
+        return true;
+    }
 
-    // First convert the value from m_type into CSSPixels
-    double factor = scaleFactorForConversion(m_type);
-    convertedValue *= factor;
+    UnitTypes sourceUnitType = static_cast<UnitTypes>(m_type);
+    UnitCategory sourceCategory = unitCategory(sourceUnitType);
+    ASSERT(sourceCategory != UOther);
 
-    // Now convert from CSSPixels to the specified unitType
-    factor = scaleFactorForConversion(unitType);
-    convertedValue /= factor;
+    UnitTypes targetUnitType = requestedUnitType;
+    UnitCategory targetCategory = unitCategory(targetUnitType);
+    ASSERT(targetCategory != UOther);
 
-    return convertedValue;
-}
+    // Cannot convert between unrelated unit categories if one of them is not UNumber.
+    if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
+        return false;
 
-double CSSPrimitiveValue::getDoubleValue(unsigned short unitType)
-{
-    if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION)
-        return 0;
+    if (targetCategory == UNumber) {
+        // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
+        targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
+        if (targetUnitType == CSS_UNKNOWN)
+            return false;
+    }
 
-    if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
-        return m_value.num;
+    if (sourceUnitType == CSS_NUMBER) {
+        // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
+        sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
+        if (sourceUnitType == CSS_UNKNOWN)
+            return false;
+    }
 
     double convertedValue = m_value.num;
 
-    // First convert the value from m_type into CSSPixels
-    double factor = scaleFactorForConversion(m_type);
+    // First convert the value from m_type to canonical type.
+    double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
     convertedValue *= factor;
 
-    // Now convert from CSSPixels to the specified unitType
-    factor = scaleFactorForConversion(unitType);
+    // Now convert from canonical type to the target unitType.
+    factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
     convertedValue /= factor;
 
-    return convertedValue;
+    *result = convertedValue;
+    return true;
 }
 
-
 void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec)
 {
     // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. 
@@ -587,7 +683,7 @@ bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/)
     return false;
 }
 
-int CSSPrimitiveValue::getIdent()
+int CSSPrimitiveValue::getIdent() const
 {
     if (m_type != CSS_IDENT)
         return 0;
index f3da873..e12cd4c 100644 (file)
@@ -93,6 +93,17 @@ public:
         CSS_REMS = 108
     };
     
+    // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies.
+    enum UnitCategory {
+        UNumber,
+        UPercent,
+        ULength,
+        UAngle,
+        UTime,
+        UFrequency,
+        UOther
+    };
+
     static bool isUnitTypeLength(int type) { return (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) ||
                                                     type == CSSPrimitiveValue::CSS_REMS; }
 
@@ -135,17 +146,17 @@ public:
     // use with care!!!
     void setPrimitiveType(unsigned short type) { m_type = type; }
     
-    double getDoubleValue(unsigned short unitType, ExceptionCode&);
-    double getDoubleValue(unsigned short unitType);
+    double getDoubleValue(unsigned short unitType, ExceptionCode&) const;
+    double getDoubleValue(unsigned short unitType) const;
     double getDoubleValue() const { return m_value.num; }
 
     void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&);
-    float getFloatValue(unsigned short unitType, ExceptionCode& ec) { return static_cast<float>(getDoubleValue(unitType, ec)); }
-    float getFloatValue(unsigned short unitType) { return static_cast<float>(getDoubleValue(unitType)); }
+    float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return static_cast<float>(getDoubleValue(unitType, ec)); }
+    float getFloatValue(unsigned short unitType) const { return static_cast<float>(getDoubleValue(unitType)); }
     float getFloatValue() const { return static_cast<float>(m_value.num); }
 
-    int getIntValue(unsigned short unitType, ExceptionCode& ec) { return static_cast<int>(getDoubleValue(unitType, ec)); }
-    int getIntValue(unsigned short unitType) { return static_cast<int>(getDoubleValue(unitType)); }
+    int getIntValue(unsigned short unitType, ExceptionCode& ec) const { return static_cast<int>(getDoubleValue(unitType, ec)); }
+    int getIntValue(unsigned short unitType) const { return static_cast<int>(getDoubleValue(unitType)); }
     int getIntValue() const { return static_cast<int>(m_value.num); }
 
     void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&);
@@ -166,7 +177,7 @@ public:
 
     DashboardRegion* getDashboardRegionValue() const { return m_type != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
 
-    int getIdent();
+    int getIdent() const;
     template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
 
     virtual bool parseString(const String&, bool = false);
@@ -201,10 +212,13 @@ private:
     static PassRefPtr<CSSPrimitiveValue> createUncachedColor(unsigned rgbValue);
     static PassRefPtr<CSSPrimitiveValue> createUncached(double value, UnitTypes type);
 
+    static UnitTypes canonicalUnitTypeForCategory(UnitCategory category);
+
     void init(PassRefPtr<Counter>);
     void init(PassRefPtr<Rect>);
     void init(PassRefPtr<Pair>);
     void init(PassRefPtr<DashboardRegion>); // FIXME: Dashboard region should not be a primitive value.
+    bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const;
 
     virtual bool isPrimitiveValue() const { return true; }