Changeset 168868 in webkit


Ignore:
Timestamp:
May 14, 2014 4:13:52 PM (10 years ago)
Author:
Alan Bujtas
Message:

Subpixel layout: Change Element.offset* client* scroll* return type to double.
https://bugs.webkit.org/show_bug.cgi?id=132895

Reviewed by Simon Fraser.

Source/WebCore:
This patch changes Element.offset*, Element.client* and Element.scroll* APIs return
type from long to double to match the latest CSSOM View Module spec[1].
Element.offset* and Element.client* do return subpixel values from now on.
Element.scroll* still return integral values as the scrolling code hasn't adopted to subpixel rendering yet.

subpixelCSSOMElementMetricsEnabled setting is added to be able to turn this feature on/off
from WK2 preferences. It toggles the return value from subpixel to floored integral.
It does not change layout/rendering behavior.

Reference list of what other browsers do:
IE: http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx
Blink: http://www.chromestatus.com/features/5497402177880064
Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=825607

[1] http://www.w3.org/TR/2013/WD-cssom-view-20131217/

Test: cssom/subpixel-offsetleft-top-width-height-values.html

  • dom/Element.cpp:

(WebCore::localZoomForRenderer):
(WebCore::adjustForLocalZoom):
(WebCore::convertToNonSubpixelValueIfNeeded):
(WebCore::Element::offsetLeft):
(WebCore::Element::offsetTop):
(WebCore::Element::offsetWidth):
(WebCore::Element::offsetHeight):
(WebCore::Element::clientLeft):
(WebCore::Element::clientTop):
(WebCore::Element::clientWidth):
(WebCore::Element::clientHeight):
(WebCore::Element::scrollLeft):
(WebCore::Element::scrollTop):
(WebCore::Element::setScrollLeft):
(WebCore::Element::setScrollTop):
(WebCore::Element::scrollWidth):
(WebCore::Element::scrollHeight):

  • dom/Element.h:
  • dom/Element.idl:
  • html/HTMLBodyElement.cpp:

(WebCore::adjustForZoom):
(WebCore::HTMLBodyElement::scrollLeft):
(WebCore::HTMLBodyElement::setScrollLeft):
(WebCore::HTMLBodyElement::scrollTop):
(WebCore::HTMLBodyElement::setScrollTop):
(WebCore::HTMLBodyElement::scrollHeight):
(WebCore::HTMLBodyElement::scrollWidth):

  • html/HTMLBodyElement.h:
  • page/Settings.in:

Source/WebKit2:
This patch changes Element.offset*, Element.client* and Element.scroll* APIs return
type from long to double to match the latest CSSOM View Module spec[1].
Element.offset* and Element.client* do return subpixel values from now on.
Element.scroll* still return integral values as the scrolling code hasn't adopted to subpixel rendering yet.

subpixelCSSOMElementMetricsEnabled setting is added to be able to turn this feature on/off
from WK2 preferences. It toggles the return value from subpixel to floored integral.
It does not change layout/rendering behavior.

Reference list of what other browsers do:
IE: http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx
Blink: http://www.chromestatus.com/features/5497402177880064
Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=825607

[1] http://www.w3.org/TR/2013/WD-cssom-view-20131217/

  • Shared/WebPreferencesStore.h:
  • UIProcess/API/C/WKPreferences.cpp:

(WKPreferencesSetSubpixelCSSOMElementMetricsEnabled):
(WKPreferencesGetSubpixelCSSOMElementMetricsEnabled):

  • UIProcess/API/C/WKPreferencesRefPrivate.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::updatePreferences):

LayoutTests:
Some test cases expect integral values, so the test content is updated accordingly.
It mostly means adding Math.round() before comparing values in order to match pixelSnappedIntRect()
functionality.

  • css3/calc/simple-calcs-prefixed.html: changed file format from Windows to Unix.
  • css3/calc/simple-calcs.html: changed file format from Windows to Unix.
  • cssom/subpixel-offsetleft-top-width-height-values-expected.txt: Added.
  • cssom/subpixel-offsetleft-top-width-height-values.html: Added.
  • editing/selection/drag-start-event-client-x-y.html: use floor as we compare the return value to a truncated integer.
  • editing/selection/mixed-editability-10.html:
  • fast/css/zoom-in-length-round-trip.html:
  • fast/dom/non-numeric-values-numeric-parameters-expected.txt:
  • fast/dom/script-tests/non-numeric-values-numeric-parameters.js:
  • fast/forms/basic-buttons.html:
  • js/dom/dom-static-property-for-in-iteration-expected.txt:
  • platform/mac/fast/scrolling/scroll-div-latched-div.html:
  • platform/mac/fast/scrolling/scroll-div-latched-mainframe.html:
  • platform/mac/fast/scrolling/scroll-select-bottom-test.html:
  • platform/mac/fast/scrolling/scroll-select-latched-mainframe.html:
  • platform/mac/fast/scrolling/scroll-select-latched-select.html:
  • resources/check-layout.js:
Location:
trunk
Files:
2 added
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r168865 r168868  
     12014-05-14  Zalan Bujtas  <zalan@apple.com>
     2
     3        Subpixel layout: Change Element.offset* client* scroll* return type to double.
     4        https://bugs.webkit.org/show_bug.cgi?id=132895
     5
     6        Reviewed by Simon Fraser.
     7
     8        Some test cases expect integral values, so the test content is updated accordingly.
     9        It mostly means adding Math.round() before comparing values in order to match pixelSnappedIntRect()
     10        functionality.
     11
     12        * css3/calc/simple-calcs-prefixed.html: changed file format from Windows to Unix.
     13        * css3/calc/simple-calcs.html: changed file format from Windows to Unix.
     14        * cssom/subpixel-offsetleft-top-width-height-values-expected.txt: Added.
     15        * cssom/subpixel-offsetleft-top-width-height-values.html: Added.
     16        * editing/selection/drag-start-event-client-x-y.html: use floor as we compare the return value to a truncated integer.
     17        * editing/selection/mixed-editability-10.html:
     18        * fast/css/zoom-in-length-round-trip.html:
     19        * fast/dom/non-numeric-values-numeric-parameters-expected.txt:
     20        * fast/dom/script-tests/non-numeric-values-numeric-parameters.js:
     21        * fast/forms/basic-buttons.html:
     22        * js/dom/dom-static-property-for-in-iteration-expected.txt:
     23        * platform/mac/fast/scrolling/scroll-div-latched-div.html:
     24        * platform/mac/fast/scrolling/scroll-div-latched-mainframe.html:
     25        * platform/mac/fast/scrolling/scroll-select-bottom-test.html:
     26        * platform/mac/fast/scrolling/scroll-select-latched-mainframe.html:
     27        * platform/mac/fast/scrolling/scroll-select-latched-select.html:
     28        * resources/check-layout.js:
     29
    1302014-05-14  Carlos Alberto Lopez Perez  <clopez@igalia.com>
    231
  • trunk/LayoutTests/css3/calc/simple-calcs-prefixed.html

    r168838 r168868  
    105105        var zoom = zoomLevels[z];
    106106        document.body.style.zoom = zoom;
    107         var width = element.offsetWidth;
     107        var width = Math.round(element.offsetWidth);
    108108        if (width != 100)
    109109            error.push("@zoom=" + zoom + " expected width of 100, but was " + width);
    110         var height = element.offsetHeight;
     110        var height = Math.round(element.offsetHeight);
    111111        if (height != 100)
    112112            error.push("@zoom=" + zoom + " expected height of 100, but was " + height);
  • trunk/LayoutTests/css3/calc/simple-calcs.html

    r168840 r168868  
    102102        var zoom = zoomLevels[z];
    103103        document.body.style.zoom = zoom;
    104         var width = element.offsetWidth;
     104        var width = Math.round(element.offsetWidth);
    105105        if (width != 100)
    106106            error.push("@zoom=" + zoom + " expected width of 100, but was " + width);
    107         var height = element.offsetHeight;
     107        var height = Math.round(element.offsetHeight);
    108108        if (height != 100)
    109109            error.push("@zoom=" + zoom + " expected height of 100, but was " + height);
  • trunk/LayoutTests/editing/selection/drag-start-event-client-x-y.html

    r168846 r168868  
    4444            dragStartHandler: function(dragStart, dragDistance) {
    4545                var resultElement = document.getElementById("result");
    46                 shouldBe(resultElement, "clientX", dragStart.x, event.clientX);
    47                 shouldBe(resultElement, "clientY", dragStart.y, event.clientY);
    48                 shouldBe(resultElement, "pageX", dragStart.x, event.pageX);
    49                 shouldBe(resultElement, "pageY", dragStart.y, event.pageY);
     46                shouldBe(resultElement, "clientX", Math.floor(dragStart.x), event.clientX);
     47                shouldBe(resultElement, "clientY", Math.floor(dragStart.y), event.clientY);
     48                shouldBe(resultElement, "pageX", Math.floor(dragStart.x), event.pageX);
     49                shouldBe(resultElement, "pageY", Math.floor(dragStart.y), event.pageY);
    5050            },
    5151
     
    5858               
    5959                var element = document.getElementById("draggable");
    60                 var dragStart = { x: element.offsetLeft + element.offsetWidth / 2, y:  element.offsetTop + 1.0 };
     60                var dragStart = { x: Math.round(element.offsetLeft) + Math.round(element.offsetWidth) / 2, y:  Math.round(element.offsetTop) + 1.0 };
    6161                var dragDistance = 10.0;
    6262                element.ondragstart = this.dragStartHandler.bind(this, dragStart, dragDistance);
  • trunk/LayoutTests/editing/selection/mixed-editability-10.html

    r120173 r168868  
    5656
    5757    var coord = caretCoordinates();
    58     var anchorString = "Anchor (" + anchorNode + ", " + anchorOffset + " caret[" + coord.x + "," + coord.y + "] refpos=" + refpos + ")";
    59     var anchorCorrect = anchorNode == elem && anchorOffset == offset && coord.x == refpos;
     58    var anchorString = "Anchor (" + anchorNode + ", " + anchorOffset + " caret[" + coord.x + "," + coord.y + "] refpos=" + Math.round(refpos) + ")";
     59    var anchorCorrect = anchorNode == elem && anchorOffset == offset && coord.x == Math.round(refpos);
    6060    if (anchorCorrect)
    6161        log(anchorString + " is correct.");
  • trunk/LayoutTests/fast/css/zoom-in-length-round-trip.html

    r120683 r168868  
    3030    for (zoom = 100; zoom <= 200; zoom += 1) {
    3131        containerStyle.setProperty("zoom", zoom / 100);
    32         if (target.offsetWidth != 1 || target.offsetHeight != 10) {
    33             if (hasSubpixelSupport && (target.offsetWidth == 1 || target.offsetWidth == 2) && (target.offsetHeight == 10 || target.offsetHeight == 11))
     32        if (Math.round(target.offsetWidth) != 1 || Math.round(target.offsetHeight) != 10) {
     33            if (hasSubpixelSupport && (Math.round(target.offsetWidth) == 1 || Math.round(target.offsetWidth) == 2) && (Math.round(target.offsetHeight) == 10 || Math.round(target.offsetHeight) == 11))
    3434                continue; // With subpixel layout and pixel snapping we extend the box with one pixel at certain zoom levels.
    3535            failed = true;
  • trunk/LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt

    r154012 r168868  
    2424PASS nonNumericPolicy('document.body.scrollByLines(x)') is 'any type allowed'
    2525PASS nonNumericPolicy('document.body.scrollByPages(x)') is 'any type allowed'
    26 PASS nonNumericPolicy('document.body.scrollLeft = x') is 'any type allowed'
    27 PASS nonNumericPolicy('document.body.scrollTop = x') is 'any type allowed'
     26PASS nonNumericPolicy('document.body.scrollLeft = x') is 'mixed'
     27PASS nonNumericPolicy('document.body.scrollTop = x') is 'mixed'
    2828PASS nonNumericPolicy('document.images.item(x)') is 'any type allowed'
    2929PASS nonNumericPolicy('document.createElement("input").setSelectionRange(x, 0)') is 'any type allowed'
  • trunk/LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js

    r154012 r168868  
    227227shouldBe("nonNumericPolicy('document.body.scrollByLines(x)')", "'any type allowed'");
    228228shouldBe("nonNumericPolicy('document.body.scrollByPages(x)')", "'any type allowed'");
    229 shouldBe("nonNumericPolicy('document.body.scrollLeft = x')", "'any type allowed'");
    230 shouldBe("nonNumericPolicy('document.body.scrollTop = x')", "'any type allowed'");
     229shouldBe("nonNumericPolicy('document.body.scrollLeft = x')", "'mixed'");
     230shouldBe("nonNumericPolicy('document.body.scrollTop = x')", "'mixed'");
    231231
    232232// History
     
    393393../../../../WebCore/html/HTMLAreaElement.idl:        attribute long tabIndex;
    394394../../../../WebCore/html/HTMLBaseFontElement.idl:        attribute long size;
    395 ../../../../WebCore/html/HTMLBodyElement.idl:                 attribute long scrollLeft;
    396 ../../../../WebCore/html/HTMLBodyElement.idl:                 attribute long scrollTop;
     395../../../../WebCore/html/HTMLBodyElement.idl:                 attribute float scrollLeft;
     396../../../../WebCore/html/HTMLBodyElement.idl:                 attribute float scrollTop;
    397397../../../../WebCore/html/HTMLButtonElement.idl:                 attribute  long                 tabIndex;
    398398../../../../WebCore/html/HTMLCanvasElement.idl:        attribute long width;
  • trunk/LayoutTests/fast/forms/basic-buttons.html

    r48690 r168868  
    4444
    4545        button.parentNode.nextSibling.innerHTML =
    46             "(" + button.offsetHeight + ", " + button.offsetWidth + ") " +
    47             "(" + button.clientHeight + ", " + button.clientWidth + ")";
     46            "(" + Math.round(button.offsetHeight) + ", " + Math.round(button.offsetWidth) + ") " +
     47            "(" + Math.round(button.clientHeight) + ", " + Math.round(button.clientWidth) + ")";
    4848    }
    4949}
  • trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt

    r165603 r168868  
    5353PASS a["offsetWidth"] is 39
    5454PASS a["offsetHeight"] is 18
    55 PASS a["offsetParent"] is [object HTMLBodyElement]
    5655PASS a["clientLeft"] is 0
    5756PASS a["clientTop"] is 0
     
    6261PASS a["scrollWidth"] is 0
    6362PASS a["scrollHeight"] is 0
     63PASS a["offsetParent"] is [object HTMLBodyElement]
    6464PASS a["className"] is
    6565PASS a["classList"] is
  • trunk/LayoutTests/platform/mac/fast/scrolling/scroll-div-latched-div.html

    r166960 r168868  
    7070    var startPosX = divTarget.offsetLeft + 20;
    7171    debug("div display height = " + divTarget.clientHeight);
    72     var startPosY = divTarget.offsetTop + divTarget.clientHeight - 42; // One wheel turn before end.
     72    var startPosY = Math.round(divTarget.offsetTop) + Math.round(divTarget.clientHeight) - 42; // One wheel turn before end.
    7373    eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame
    7474    debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
  • trunk/LayoutTests/platform/mac/fast/scrolling/scroll-div-latched-mainframe.html

    r166960 r168868  
    6767
    6868    // Scroll the #source until we reach the #target.
    69     var startPosX = divTarget.offsetLeft + 20;
    70     var startPosY = divTarget.offsetTop - 42; // Slightly more than one wheel scroll away from the IFrame
     69    var startPosX = Math.round(divTarget.offsetLeft) + 20;
     70    var startPosY = Math.round(divTarget.offsetTop) - 42; // Slightly more than one wheel scroll away from the IFrame
    7171    eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame
    7272    debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
  • trunk/LayoutTests/platform/mac/fast/scrolling/scroll-select-bottom-test.html

    r167807 r168868  
    7272    var startPosX = selectTarget.offsetLeft + 20;
    7373    debug("div display height = " + selectTarget.clientHeight);
    74     var startPosY = selectTarget.offsetTop + selectTarget.clientHeight + clientInset - 2; // Very near top (accounting for top content inset).
     74    var startPosY = Math.round(selectTarget.offsetTop) + Math.round(selectTarget.clientHeight) + clientInset - 2; // Very near top (accounting for top content inset).
    7575    eventSender.mouseMoveTo(startPosX, startPosY);
    7676    debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
  • trunk/LayoutTests/platform/mac/fast/scrolling/scroll-select-latched-mainframe.html

    r166960 r168868  
    6767
    6868    // Scroll the #source until we reach the #target.
    69     var startPosX = selectTarget.offsetLeft + 20;
    70     var startPosY = selectTarget.offsetTop - 42; // Slightly more than one wheel scroll away from the IFrame
     69    var startPosX = Math.round(selectTarget.offsetLeft) + 20;
     70    var startPosY = Math.round(selectTarget.offsetTop) - 42; // Slightly more than one wheel scroll away from the IFrame
    7171    eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame
    7272    debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
  • trunk/LayoutTests/platform/mac/fast/scrolling/scroll-select-latched-select.html

    r166960 r168868  
    6868
    6969    // Scroll the #source until we reach the #target.
    70     var startPosX = selectTarget.offsetLeft + 20;
     70    var startPosX = Math.round(selectTarget.offsetLeft) + 20;
    7171    debug("div display height = " + selectTarget.clientHeight);
    72     var startPosY = selectTarget.offsetTop + selectTarget.clientHeight - 42; // One wheel turn before end.
     72    var startPosY = Math.round(selectTarget.offsetTop) + Math.round(selectTarget.clientHeight) - 42; // One wheel turn before end.
    7373    eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame
    7474    debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
  • trunk/LayoutTests/resources/check-layout.js

    r150067 r168868  
    3838    var expectedWidth = checkAttribute(output, node, "data-expected-width");
    3939    if (expectedWidth) {
    40         if (node.offsetWidth != parseInt(expectedWidth))
     40        if (Math.round(node.offsetWidth) != parseInt(expectedWidth))
    4141            failures.push("Expected " + expectedWidth + " for width, but got " + node.offsetWidth + ". ");
    4242    }
     
    4444    var expectedHeight = checkAttribute(output, node, "data-expected-height");
    4545    if (expectedHeight) {
    46         if (node.offsetHeight != parseInt(expectedHeight))
     46        if (Math.round(node.offsetHeight) != parseInt(expectedHeight))
    4747            failures.push("Expected " + expectedHeight + " for height, but got " + node.offsetHeight + ". ");
    4848    }
     
    5050    var expectedOffset = checkAttribute(output, node, "data-offset-x");
    5151    if (expectedOffset) {
    52         if (node.offsetLeft != parseInt(expectedOffset))
     52        if (Math.round(node.offsetLeft) != parseInt(expectedOffset))
    5353            failures.push("Expected " + expectedOffset + " for offsetLeft, but got " + node.offsetLeft + ". ");
    5454    }
     
    5656    var expectedOffset = checkAttribute(output, node, "data-offset-y");
    5757    if (expectedOffset) {
    58         if (node.offsetTop != parseInt(expectedOffset))
     58        if (Math.round(node.offsetTop) != parseInt(expectedOffset))
    5959            failures.push("Expected " + expectedOffset + " for offsetTop, but got " + node.offsetTop + ". ");
    6060    }
     
    6262    var expectedWidth = checkAttribute(output, node, "data-expected-client-width");
    6363    if (expectedWidth) {
    64         if (node.clientWidth != parseInt(expectedWidth))
     64        if (Math.round(node.clientWidth) != parseInt(expectedWidth))
    6565            failures.push("Expected " + expectedWidth + " for clientWidth, but got " + node.clientWidth + ". ");
    6666    }
     
    6868    var expectedHeight = checkAttribute(output, node, "data-expected-client-height");
    6969    if (expectedHeight) {
    70         if (node.clientHeight != parseInt(expectedHeight))
     70        if (Math.round(node.clientHeight) != parseInt(expectedHeight))
    7171            failures.push("Expected " + expectedHeight + " for clientHeight, but got " + node.clientHeight + ". ");
    7272    }
     
    7474    var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width");
    7575    if (expectedWidth) {
    76         if (node.scrollWidth != parseInt(expectedWidth))
     76        if (Math.round(node.scrollWidth) != parseInt(expectedWidth))
    7777            failures.push("Expected " + expectedWidth + " for scrollWidth, but got " + node.scrollWidth + ". ");
    7878    }
     
    8080    var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height");
    8181    if (expectedHeight) {
    82         if (node.scrollHeight != parseInt(expectedHeight))
     82        if (Math.round(node.scrollHeight) != parseInt(expectedHeight))
    8383            failures.push("Expected " + expectedHeight + " for scrollHeight, but got " + node.scrollHeight + ". ");
    8484    }
     
    8787    if (expectedOffset) {
    8888        var totalLeft = node.clientLeft + node.offsetLeft;
    89         if (totalLeft != parseInt(expectedOffset))
     89        if (Math.round(totalLeft) != parseInt(expectedOffset))
    9090            failures.push("Expected " + expectedOffset + " for clientLeft+offsetLeft, but got " + totalLeft + ", clientLeft: " + node.clientLeft + ", offsetLeft: " + node.offsetLeft + ". ");
    9191    }
     
    9494    if (expectedOffset) {
    9595        var totalTop = node.clientTop + node.offsetTop;
    96         if (totalTop != parseInt(expectedOffset))
     96        if (Math.round(totalTop) != parseInt(expectedOffset))
    9797            failures.push("Expected " + expectedOffset + " for clientTop+offsetTop, but got " + totalTop + ", clientTop: " + node.clientTop + ", + offsetTop: " + node.offsetTop + ". ");
    9898    }
  • trunk/Source/WebCore/ChangeLog

    r168859 r168868  
     12014-05-14  Zalan Bujtas  <zalan@apple.com>
     2
     3        Subpixel layout: Change Element.offset* client* scroll* return type to double.
     4        https://bugs.webkit.org/show_bug.cgi?id=132895
     5
     6        Reviewed by Simon Fraser.
     7
     8        This patch changes Element.offset*, Element.client* and Element.scroll* APIs return
     9        type from long to double to match the latest CSSOM View Module spec[1].
     10        Element.offset* and Element.client* do return subpixel values from now on.
     11        Element.scroll* still return integral values as the scrolling code hasn't adopted to subpixel rendering yet.
     12
     13        subpixelCSSOMElementMetricsEnabled setting is added to be able to turn this feature on/off
     14        from WK2 preferences. It toggles the return value from subpixel to floored integral.
     15        It does not change layout/rendering behavior.
     16
     17        Reference list of what other browsers do:
     18        IE: http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx
     19        Blink: http://www.chromestatus.com/features/5497402177880064
     20        Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=825607
     21
     22        [1] http://www.w3.org/TR/2013/WD-cssom-view-20131217/
     23
     24        Test: cssom/subpixel-offsetleft-top-width-height-values.html
     25
     26        * dom/Element.cpp:
     27        (WebCore::localZoomForRenderer):
     28        (WebCore::adjustForLocalZoom):
     29        (WebCore::convertToNonSubpixelValueIfNeeded):
     30        (WebCore::Element::offsetLeft):
     31        (WebCore::Element::offsetTop):
     32        (WebCore::Element::offsetWidth):
     33        (WebCore::Element::offsetHeight):
     34        (WebCore::Element::clientLeft):
     35        (WebCore::Element::clientTop):
     36        (WebCore::Element::clientWidth):
     37        (WebCore::Element::clientHeight):
     38        (WebCore::Element::scrollLeft):
     39        (WebCore::Element::scrollTop):
     40        (WebCore::Element::setScrollLeft):
     41        (WebCore::Element::setScrollTop):
     42        (WebCore::Element::scrollWidth):
     43        (WebCore::Element::scrollHeight):
     44        * dom/Element.h:
     45        * dom/Element.idl:
     46        * html/HTMLBodyElement.cpp:
     47        (WebCore::adjustForZoom):
     48        (WebCore::HTMLBodyElement::scrollLeft):
     49        (WebCore::HTMLBodyElement::setScrollLeft):
     50        (WebCore::HTMLBodyElement::scrollTop):
     51        (WebCore::HTMLBodyElement::setScrollTop):
     52        (WebCore::HTMLBodyElement::scrollHeight):
     53        (WebCore::HTMLBodyElement::scrollWidth):
     54        * html/HTMLBodyElement.h:
     55        * page/Settings.in:
     56
    1572014-05-14  Brady Eidson  <beidson@apple.com>
    258
  • trunk/Source/WebCore/dom/Element.cpp

    r168339 r168868  
    622622}
    623623
    624 static float localZoomForRenderer(RenderElement* renderer)
     624static double localZoomForRenderer(const RenderElement& renderer)
    625625{
    626626    // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
    627627    // other out, but the alternative is that we'd have to crawl up the whole render tree every
    628628    // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
    629     float zoomFactor = 1;
    630     if (renderer->style().effectiveZoom() != 1) {
     629    double zoomFactor = 1;
     630    if (renderer.style().effectiveZoom() != 1) {
    631631        // Need to find the nearest enclosing RenderElement that set up
    632632        // a differing zoom, and then we divide our result by it to eliminate the zoom.
    633         RenderElement* prev = renderer;
     633        const RenderElement* prev = &renderer;
    634634        for (RenderElement* curr = prev->parent(); curr; curr = curr->parent()) {
    635635            if (curr->style().effectiveZoom() != prev->style().effectiveZoom()) {
     
    645645}
    646646
    647 static int adjustForLocalZoom(LayoutUnit value, RenderElement* renderer)
    648 {
    649     float zoomFactor = localZoomForRenderer(renderer);
     647static double adjustForLocalZoom(LayoutUnit value, const RenderElement& renderer)
     648{
     649    double zoomFactor = localZoomForRenderer(renderer);
    650650    if (zoomFactor == 1)
    651         return value;
     651        return value.toDouble();
    652652#if ENABLE(SUBPIXEL_LAYOUT)
    653     return lroundf(value / zoomFactor);
     653    return value.toDouble() / zoomFactor;
    654654#else
    655655    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
    656656    if (zoomFactor > 1)
    657657        ++value;
    658     return static_cast<int>(value / zoomFactor);
     658    return value.toDouble() / zoomFactor;
    659659#endif
    660660}
    661661
    662 int Element::offsetLeft()
     662static double convertToNonSubpixelValueIfNeeded(double value, const Document& document)
     663{
     664    return document.settings() && !document.settings()->subpixelCSSOMElementMetricsEnabled() ? floor(value) : value;
     665}
     666
     667double Element::offsetLeft()
    663668{
    664669    document().updateLayoutIgnorePendingStylesheets();
    665670    if (RenderBoxModelObject* renderer = renderBoxModelObject())
    666         return adjustForLocalZoom(renderer->pixelSnappedOffsetLeft(), renderer);
     671        return convertToNonSubpixelValueIfNeeded(adjustForLocalZoom(renderer->offsetLeft(), *renderer), renderer->document());
    667672    return 0;
    668673}
    669674
    670 int Element::offsetTop()
     675double Element::offsetTop()
    671676{
    672677    document().updateLayoutIgnorePendingStylesheets();
    673678    if (RenderBoxModelObject* renderer = renderBoxModelObject())
    674         return adjustForLocalZoom(renderer->pixelSnappedOffsetTop(), renderer);
     679        return convertToNonSubpixelValueIfNeeded(adjustForLocalZoom(renderer->offsetTop(), *renderer), renderer->document());
    675680    return 0;
    676681}
    677682
    678 int Element::offsetWidth()
     683double Element::offsetWidth()
     684{
     685    document().updateLayoutIgnorePendingStylesheets();
     686    if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
     687#if ENABLE(SUBPIXEL_LAYOUT)
     688        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->offsetWidth(), *renderer).toDouble(), renderer->document());
     689#else
     690        return adjustForAbsoluteZoom(renderer->offsetWidth(), *renderer);
     691#endif
     692    }
     693    return 0;
     694}
     695
     696double Element::offsetHeight()
    679697{
    680698    document().updateLayoutIgnorePendingStylesheets();
    681699    if (RenderBoxModelObject* renderer = renderBoxModelObject())
    682700#if ENABLE(SUBPIXEL_LAYOUT)
    683         return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), *renderer).round();
     701        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->offsetHeight(), *renderer).toDouble(), renderer->document());
    684702#else
    685         return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), *renderer);
    686 #endif
    687     return 0;
    688 }
    689 
    690 int Element::offsetHeight()
    691 {
    692     document().updateLayoutIgnorePendingStylesheets();
    693     if (RenderBoxModelObject* renderer = renderBoxModelObject())
    694 #if ENABLE(SUBPIXEL_LAYOUT)
    695         return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), *renderer).round();
    696 #else
    697         return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), *renderer);
     703        return adjustForAbsoluteZoom(renderer->offsetHeight(), *renderer);
    698704#endif
    699705    return 0;
     
    720726}
    721727
    722 int Element::clientLeft()
     728double Element::clientLeft()
    723729{
    724730    document().updateLayoutIgnorePendingStylesheets();
    725731
    726732    if (RenderBox* renderer = renderBox())
    727         return adjustForAbsoluteZoom(roundToInt(renderer->clientLeft()), *renderer);
     733#if ENABLE(SUBPIXEL_LAYOUT)
     734        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->clientLeft(), *renderer).toDouble(), renderer->document());
     735#else
     736        return adjustForAbsoluteZoom(renderer->clientLeft(), *renderer);
     737#endif
    728738    return 0;
    729739}
    730740
    731 int Element::clientTop()
     741double Element::clientTop()
    732742{
    733743    document().updateLayoutIgnorePendingStylesheets();
    734744
    735745    if (RenderBox* renderer = renderBox())
    736         return adjustForAbsoluteZoom(roundToInt(renderer->clientTop()), *renderer);
     746#if ENABLE(SUBPIXEL_LAYOUT)
     747        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->clientTop(), *renderer).toDouble(), renderer->document());
     748#else
     749        return adjustForAbsoluteZoom(renderer->clientTop(), *renderer);
     750#endif
    737751    return 0;
    738752}
    739753
    740 int Element::clientWidth()
     754double Element::clientWidth()
    741755{
    742756    document().updateLayoutIgnorePendingStylesheets();
     
    754768    if (RenderBox* renderer = renderBox())
    755769#if ENABLE(SUBPIXEL_LAYOUT)
    756         return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientWidth(), *renderer).round();
     770        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->clientWidth(), *renderer).toDouble(), renderer->document());
    757771#else
    758         return adjustForAbsoluteZoom(renderer->pixelSnappedClientWidth(), *renderer);
     772        return adjustForAbsoluteZoom(renderer->clientWidth(), *renderer);
    759773#endif
    760774    return 0;
    761775}
    762776
    763 int Element::clientHeight()
     777double Element::clientHeight()
    764778{
    765779    document().updateLayoutIgnorePendingStylesheets();
     
    777791    if (RenderBox* renderer = renderBox())
    778792#if ENABLE(SUBPIXEL_LAYOUT)
    779         return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientHeight(), *renderer).round();
     793        return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(renderer->clientHeight(), *renderer).toDouble(), renderer->document());
    780794#else
    781         return adjustForAbsoluteZoom(renderer->pixelSnappedClientHeight(), *renderer);
     795        return adjustForAbsoluteZoom(renderer->clientHeight(), *renderer);
    782796#endif
    783797    return 0;
    784798}
    785799
    786 int Element::scrollLeft()
     800double Element::scrollLeft()
    787801{
    788802    document().updateLayoutIgnorePendingStylesheets();
     
    793807}
    794808
    795 int Element::scrollTop()
     809double Element::scrollTop()
    796810{
    797811    document().updateLayoutIgnorePendingStylesheets();
     
    802816}
    803817
    804 void Element::setScrollLeft(int newLeft)
     818void Element::setScrollLeft(double newLeft)
    805819{
    806820    document().updateLayoutIgnorePendingStylesheets();
    807821
    808822    if (RenderBox* renderer = renderBox()) {
    809         renderer->setScrollLeft(static_cast<int>(newLeft * renderer->style().effectiveZoom()));
     823        renderer->setScrollLeft(round(newLeft * renderer->style().effectiveZoom()));
    810824        if (auto* scrollableArea = renderer->layer())
    811825            scrollableArea->setScrolledProgrammatically(true);
     
    813827}
    814828
    815 void Element::setScrollTop(int newTop)
     829void Element::setScrollTop(double newTop)
    816830{
    817831    document().updateLayoutIgnorePendingStylesheets();
    818832
    819833    if (RenderBox* renderer = renderBox()) {
    820         renderer->setScrollTop(static_cast<int>(newTop * renderer->style().effectiveZoom()));
     834        renderer->setScrollTop(round(newTop * renderer->style().effectiveZoom()));
    821835        if (auto* scrollableArea = renderer->layer())
    822836            scrollableArea->setScrolledProgrammatically(true);
     
    824838}
    825839
    826 int Element::scrollWidth()
     840double Element::scrollWidth()
    827841{
    828842    document().updateLayoutIgnorePendingStylesheets();
     
    832846}
    833847
    834 int Element::scrollHeight()
     848double Element::scrollHeight()
    835849{
    836850    document().updateLayoutIgnorePendingStylesheets();
  • trunk/Source/WebCore/dom/Element.h

    r168339 r168868  
    207207    void scrollByPages(int pages);
    208208
    209     int offsetLeft();
    210     int offsetTop();
    211     int offsetWidth();
    212     int offsetHeight();
     209    double offsetLeft();
     210    double offsetTop();
     211    double offsetWidth();
     212    double offsetHeight();
    213213
    214214    // FIXME: Replace uses of offsetParent in the platform with calls
     
    217217
    218218    Element* offsetParent();
    219     int clientLeft();
    220     int clientTop();
    221     int clientWidth();
    222     int clientHeight();
    223     virtual int scrollLeft();
    224     virtual int scrollTop();
    225     virtual void setScrollLeft(int);
    226     virtual void setScrollTop(int);
    227     virtual int scrollWidth();
    228     virtual int scrollHeight();
     219    double clientLeft();
     220    double clientTop();
     221    double clientWidth();
     222    double clientHeight();
     223    virtual double scrollLeft();
     224    virtual double scrollTop();
     225    virtual void setScrollLeft(double);
     226    virtual void setScrollTop(double);
     227    virtual double scrollWidth();
     228    virtual double scrollHeight();
    229229
    230230    IntRect boundsInRootViewSpace();
  • trunk/Source/WebCore/dom/Element.idl

    r167631 r168868  
    7070    // Common extensions
    7171
     72#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
    7273    readonly attribute long offsetLeft;
    7374    readonly attribute long offsetTop;
    7475    readonly attribute long offsetWidth;
    7576    readonly attribute long offsetHeight;
    76     [ImplementedAs=bindingsOffsetParent] readonly attribute Element offsetParent;
    7777    readonly attribute long clientLeft;
    7878    readonly attribute long clientTop;
     
    8383    readonly attribute long scrollWidth;
    8484    readonly attribute long scrollHeight;
     85#else
     86    readonly attribute double offsetLeft;
     87    readonly attribute double offsetTop;
     88    readonly attribute double offsetWidth;
     89    readonly attribute double offsetHeight;
     90    readonly attribute double clientLeft;
     91    readonly attribute double clientTop;
     92    readonly attribute double clientWidth;
     93    readonly attribute double clientHeight;
     94    attribute double scrollLeft;
     95    attribute double scrollTop;
     96    readonly attribute double scrollWidth;
     97    readonly attribute double scrollHeight;
     98#endif
     99
     100    [ImplementedAs=bindingsOffsetParent] readonly attribute Element offsetParent;
    85101
    86102    void focus();
  • trunk/Source/WebCore/html/HTMLBodyElement.cpp

    r167503 r168868  
    199199}
    200200
    201 static int adjustForZoom(int value, Frame& frame)
    202 {
    203     float zoomFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
     201static double adjustForZoom(int value, const Frame& frame)
     202{
     203    double zoomFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
    204204    if (zoomFactor == 1)
    205205        return value;
     
    207207    if (zoomFactor > 1)
    208208        value++;
    209     return static_cast<int>(value / zoomFactor);
    210 }
    211 
    212 int HTMLBodyElement::scrollLeft()
    213 {
    214     document().updateLayoutIgnorePendingStylesheets();
    215     Frame* frame = document().frame();
    216     if (!frame)
    217         return 0;
    218     FrameView* view = frame->view();
    219     if (!view)
    220         return 0;
    221     return adjustForZoom(view->contentsScrollPosition().x(), *frame);
    222 }
    223 
    224 void HTMLBodyElement::setScrollLeft(int scrollLeft)
     209    return value / zoomFactor;
     210}
     211
     212double HTMLBodyElement::scrollLeft()
     213{
     214    document().updateLayoutIgnorePendingStylesheets();
     215    Frame* frame = document().frame();
     216    if (!frame)
     217        return 0;
     218    FrameView* view = frame->view();
     219    if (!view)
     220        return 0;
     221    return floor(adjustForZoom(view->contentsScrollPosition().x(), *frame));
     222}
     223
     224void HTMLBodyElement::setScrollLeft(double scrollLeft)
    225225{
    226226    document().updateLayoutIgnorePendingStylesheets();
     
    234234}
    235235
    236 int HTMLBodyElement::scrollTop()
    237 {
    238     document().updateLayoutIgnorePendingStylesheets();
    239     Frame* frame = document().frame();
    240     if (!frame)
    241         return 0;
    242     FrameView* view = frame->view();
    243     if (!view)
    244         return 0;
    245     return adjustForZoom(view->contentsScrollPosition().y(), *frame);
    246 }
    247 
    248 void HTMLBodyElement::setScrollTop(int scrollTop)
     236double HTMLBodyElement::scrollTop()
     237{
     238    document().updateLayoutIgnorePendingStylesheets();
     239    Frame* frame = document().frame();
     240    if (!frame)
     241        return 0;
     242    FrameView* view = frame->view();
     243    if (!view)
     244        return 0;
     245    return floor(adjustForZoom(view->contentsScrollPosition().y(), *frame));
     246}
     247
     248void HTMLBodyElement::setScrollTop(double scrollTop)
    249249{
    250250    document().updateLayoutIgnorePendingStylesheets();
     
    258258}
    259259
    260 int HTMLBodyElement::scrollHeight()
     260double HTMLBodyElement::scrollHeight()
    261261{
    262262    // Update the document's layout.
     
    268268    if (!view)
    269269        return 0;
    270     return adjustForZoom(view->contentsHeight(), *frame);
    271 }
    272 
    273 int HTMLBodyElement::scrollWidth()
     270    return floor(adjustForZoom(view->contentsHeight(), *frame));
     271}
     272
     273double HTMLBodyElement::scrollWidth()
    274274{
    275275    // Update the document's layout.
     
    281281    if (!view)
    282282        return 0;
    283     return adjustForZoom(view->contentsWidth(), *frame);
     283    return floor(adjustForZoom(view->contentsWidth(), *frame));
    284284}
    285285
  • trunk/Source/WebCore/html/HTMLBodyElement.h

    r162180 r168868  
    7070    virtual bool supportsFocus() const override;
    7171
    72     virtual int scrollLeft() override;
    73     virtual void setScrollLeft(int scrollLeft) override;
     72    virtual double scrollLeft() override;
     73    virtual void setScrollLeft(double) override;
    7474   
    75     virtual int scrollTop() override;
    76     virtual void setScrollTop(int scrollTop) override;
     75    virtual double scrollTop() override;
     76    virtual void setScrollTop(double) override;
    7777   
    78     virtual int scrollHeight() override;
    79     virtual int scrollWidth() override;
     78    virtual double scrollHeight() override;
     79    virtual double scrollWidth() override;
    8080   
    8181    virtual void addSubresourceAttributeURLs(ListHashSet<URL>&) const override;
  • trunk/Source/WebCore/page/Settings.in

    r168726 r168868  
    195195simpleLineLayoutDebugBordersEnabled initial=false, setNeedsStyleRecalcInAllFrames=1
    196196
     197subpixelCSSOMElementMetricsEnabled initial=true
     198
    197199mediaSourceEnabled initial=true, conditional=MEDIA_SOURCE
    198200
  • trunk/Source/WebKit2/ChangeLog

    r168866 r168868  
     12014-05-14  Zalan Bujtas  <zalan@apple.com>
     2
     3        Subpixel layout: Change Element.offset* client* scroll* return type to double.
     4        https://bugs.webkit.org/show_bug.cgi?id=132895
     5
     6        Reviewed by Simon Fraser.
     7
     8        This patch changes Element.offset*, Element.client* and Element.scroll* APIs return
     9        type from long to double to match the latest CSSOM View Module spec[1].
     10        Element.offset* and Element.client* do return subpixel values from now on.
     11        Element.scroll* still return integral values as the scrolling code hasn't adopted to subpixel rendering yet.
     12
     13        subpixelCSSOMElementMetricsEnabled setting is added to be able to turn this feature on/off
     14        from WK2 preferences. It toggles the return value from subpixel to floored integral.
     15        It does not change layout/rendering behavior.
     16
     17        Reference list of what other browsers do:
     18        IE: http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx
     19        Blink: http://www.chromestatus.com/features/5497402177880064
     20        Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=825607
     21
     22        [1] http://www.w3.org/TR/2013/WD-cssom-view-20131217/
     23
     24        * Shared/WebPreferencesStore.h:
     25        * UIProcess/API/C/WKPreferences.cpp:
     26        (WKPreferencesSetSubpixelCSSOMElementMetricsEnabled):
     27        (WKPreferencesGetSubpixelCSSOMElementMetricsEnabled):
     28        * UIProcess/API/C/WKPreferencesRefPrivate.h:
     29        * WebProcess/WebPage/WebPage.cpp:
     30        (WebKit::WebPage::updatePreferences):
     31
    1322014-05-14  Benjamin Poulain  <bpoulain@apple.com>
    233
  • trunk/Source/WebKit2/Shared/WebPreferencesStore.h

    r168416 r168868  
    204204    macro(SimpleLineLayoutEnabled, simpleLineLayoutEnabled, Bool, bool, true) \
    205205    macro(SimpleLineLayoutDebugBordersEnabled, simpleLineLayoutDebugBordersEnabled, Bool, bool, false) \
     206    macro(SubpixelCSSOMElementMetricsEnabled, subpixelCSSOMElementMetricsEnabled, Bool, bool, true) \
    206207    macro(BackgroundShouldExtendBeyondPage, backgroundShouldExtendBeyondPage, Bool, bool, false) \
    207208    macro(MediaStreamEnabled, mediaStreamEnabled, Bool, bool, false) \
  • trunk/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp

    r168416 r168868  
    11871187}
    11881188
     1189void WKPreferencesSetSubpixelCSSOMElementMetricsEnabled(WKPreferencesRef preferencesRef, bool flag)
     1190{
     1191    toImpl(preferencesRef)->setSubpixelCSSOMElementMetricsEnabled(flag);
     1192}
     1193
     1194bool WKPreferencesGetSubpixelCSSOMElementMetricsEnabled(WKPreferencesRef preferencesRef)
     1195{
     1196    return toImpl(preferencesRef)->subpixelCSSOMElementMetricsEnabled();
     1197}
     1198
    11891199void WKPreferencesSetMediaStreamEnabled(WKPreferencesRef preferencesRef, bool enabled)
    11901200{
  • trunk/Source/WebKit2/UIProcess/API/C/WKPreferencesRefPrivate.h

    r168541 r168868  
    297297WK_EXPORT bool WKPreferencesGetSimpleLineLayoutDebugBordersEnabled(WKPreferencesRef);
    298298
     299// Defaults to true.
     300WK_EXPORT void WKPreferencesSetSubpixelCSSOMElementMetricsEnabled(WKPreferencesRef, bool);
     301WK_EXPORT bool WKPreferencesGetSubpixelCSSOMElementMetricsEnabled(WKPreferencesRef);
     302
    299303WK_EXPORT void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef);
    300304
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp

    r168763 r168868  
    26892689    settings.setSimpleLineLayoutDebugBordersEnabled(store.getBoolValueForKey(WebPreferencesKey::simpleLineLayoutDebugBordersEnabledKey()));
    26902690
     2691    settings.setSubpixelCSSOMElementMetricsEnabled(store.getBoolValueForKey(WebPreferencesKey::subpixelCSSOMElementMetricsEnabledKey()));
     2692
    26912693    settings.setUseLegacyTextAlignPositionedElementBehavior(store.getBoolValueForKey(WebPreferencesKey::useLegacyTextAlignPositionedElementBehaviorKey()));
    26922694
Note: See TracChangeset for help on using the changeset viewer.