Changeset 163415 in webkit


Ignore:
Timestamp:
Feb 4, 2014 4:09:15 PM (10 years ago)
Author:
commit-queue@webkit.org
Message:

Use srcset's pixel density to determine intrinsic size
https://bugs.webkit.org/show_bug.cgi?id=123832

Patch by Yoav Weiss <yoav@yoav.ws> on 2014-02-04
Reviewed by Dean Jackson.

The patch is a port of a similar Blink patch: https://codereview.chromium.org/25105004
According to the spec "When an img element has a current pixel density that is not 1.0,
the element's image data must be treated as if its resolution, in device pixels per CSS pixels,
was the current pixel density."

Source/WebCore:

I've added that support using the following changes:

  • bestFitSourceForImageAttributes now returns the image candidate to HTMLImageElement.
  • HTMLImageElement passes the devicePixelRatio data to RenderImage, which stores it.
  • Bitmap images are scaled using the devicePixelRatio at RenderImageResource's intrinsicSize() and imageSize().
  • SVG images are scaled using the devicePixelRatio at RenderReplaced::computeAspectRatioInformationForRenderBox.
  • Canvas support added at CanvasRenderingContext2D::size.

Tests: fast/hidpi/image-srcset-intrinsic-size.html

fast/hidpi/image-srcset-png-canvas.html
fast/hidpi/image-srcset-png.html
fast/hidpi/image-srcset-relative-svg-canvas-2x.html
fast/hidpi/image-srcset-relative-svg.html
fast/hidpi/image-srcset-space-left-nomodifier.html
fast/hidpi/image-srcset-svg-canvas-2x.html
fast/hidpi/image-srcset-svg-canvas.html
fast/hidpi/image-srcset-svg.html
fast/hidpi/image-srcset-svg2.html

  • html/HTMLImageElement.cpp:

(WebCore::HTMLImageElement::HTMLImageElement):
(WebCore::HTMLImageElement::parseAttribute):
(WebCore::HTMLImageElement::createRenderer):

  • html/HTMLImageElement.h:
  • html/canvas/CanvasRenderingContext2D.cpp:

(WebCore::size):
(WebCore::CanvasRenderingContext2D::drawImage):

  • html/parser/HTMLParserIdioms.cpp:

(WebCore::compareByScaleFactor):
(WebCore::parseImagesWithScaleFromSrcsetAttribute):
(WebCore::bestFitSourceForImageAttributes):

  • html/parser/HTMLParserIdioms.h:

(WebCore::ImageWithScale::ImageWithScale):
(WebCore::ImageWithScale::imageURL):
(WebCore::ImageWithScale::scaleFactor):

  • html/parser/HTMLPreloadScanner.cpp:

(WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):

  • rendering/RenderImage.cpp:

(WebCore::RenderImage::RenderImage):

  • rendering/RenderImage.h:

(WebCore::RenderImage::setImageDevicePixelRatio):
(WebCore::RenderImage::imageDevicePixelRatio):

  • rendering/RenderImageResource.cpp:

(WebCore::RenderImageResource::imageSize):
(WebCore::RenderImageResource::intrinsicSize):
(WebCore::RenderImageResource::getImageSize):

  • rendering/RenderImageResource.h:
  • rendering/RenderReplaced.cpp:

(WebCore::RenderReplaced::computeAspectRatioInformationForRenderBox):

LayoutTests:

Layout test changes include modifications of existing tests to accomodate the new image dimensions, as well as new tests for this
specific functionality.

  • fast/hidpi/image-srcset-change-dynamically-from-js-2x-expected.txt:
  • fast/hidpi/image-srcset-change-dynamically-from-js-2x.html:
  • fast/hidpi/image-srcset-data-escaped-srcset-expected.txt:
  • fast/hidpi/image-srcset-data-escaped-srcset.html:
  • fast/hidpi/image-srcset-data-src.html:
  • fast/hidpi/image-srcset-data-srcset.html:
  • fast/hidpi/image-srcset-fraction.html:
  • fast/hidpi/image-srcset-intrinsic-size-expected.txt: Added.
  • fast/hidpi/image-srcset-intrinsic-size.html: Added.
  • fast/hidpi/image-srcset-invalid-inputs-correct-src-expected.txt:
  • fast/hidpi/image-srcset-invalid-inputs-correct-src.html:
  • fast/hidpi/image-srcset-invalid-inputs.html:
  • fast/hidpi/image-srcset-invalid-inputs-expected.txt: Added.
  • fast/hidpi/image-srcset-only-src-attribute-expected.txt: Added.
  • fast/hidpi/image-srcset-only-src-attribute.html:
  • fast/hidpi/image-srcset-png-canvas-expected.html: Added.
  • fast/hidpi/image-srcset-png-canvas.html: Added.
  • fast/hidpi/image-srcset-png-expected.html: Added.
  • fast/hidpi/image-srcset-png.html: Added.
  • fast/hidpi/image-srcset-relative-svg-expected.html: Added.
  • fast/hidpi/image-srcset-relative-svg.html: Added.
  • fast/hidpi/image-srcset-remove-dynamically-from-js.html:
  • fast/hidpi/image-srcset-simple-2x-expected.txt:
  • fast/hidpi/image-srcset-simple-2x.html:
  • fast/hidpi/image-srcset-space-left-nomodifier-expected.txt: Added.
  • fast/hidpi/image-srcset-space-left-nomodifier.html: Copied from LayoutTests/fast/hidpi/image-srcset-data-srcset.html.
  • fast/hidpi/image-srcset-svg-expected.html: Added.
  • fast/hidpi/image-srcset-svg.html: Added.
  • fast/hidpi/image-srcset-svg2-expected.html: Added.
  • fast/hidpi/image-srcset-svg2.html: Added.
  • fast/hidpi/resources/green-400-px-square.png: Added.
  • fast/hidpi/resources/relativesrcset.svg: Added.
  • fast/hidpi/resources/srcset-helper.js:

(runTest):

  • fast/hidpi/resources/srcset.png: Added.
  • fast/hidpi/resources/srcset.svg: Added.
  • fast/hidpi/resources/srcset_100px.svg: Added.
  • fast/hidpi/resources/svg_canvas_helper.js: Added.

(drawCanvas):

  • fast/hidpi/resources/svg_tests.css: Added.

(.test):
(.test img, .test canvas):
(.test .stats):
(.expected, .actual):

  • platform/mac/fast/hidpi/image-srcset-only-src-attribute-expected.png: Removed.
  • platform/mac/fast/hidpi/image-srcset-only-src-attribute-expected.txt: Removed.

The following tests were added, but skipped, since they reveal an unrelated SVG on canvas rendering issue:

  • fast/hidpi/image-srcset-svg-canvas-2x-expected.html: Added.
  • fast/hidpi/image-srcset-svg-canvas-2x.html: Added.
  • fast/hidpi/image-srcset-svg-canvas-expected.html: Added.
  • fast/hidpi/image-srcset-svg-canvas.html: Added.
  • fast/hidpi/image-srcset-relative-svg-canvas-2x-expected.html: Added.
  • fast/hidpi/image-srcset-relative-svg-canvas-2x.html: Added.
  • fast/hidpi/image-srcset-relative-svg-canvas-expected.html: Added.
  • fast/hidpi/image-srcset-relative-svg-canvas.html: Added.
Location:
trunk
Files:
32 added
6 deleted
32 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r163413 r163415  
     12014-02-04  Yoav Weiss  <yoav@yoav.ws>
     2
     3        Use srcset's pixel density to determine intrinsic size
     4        https://bugs.webkit.org/show_bug.cgi?id=123832
     5
     6        Reviewed by Dean Jackson.
     7
     8        The patch is a port of a similar Blink patch: https://codereview.chromium.org/25105004
     9        According to the spec "When an img element has a current pixel density that is not 1.0,
     10        the element's image data must be treated as if its resolution, in device pixels per CSS pixels,
     11        was the current pixel density."
     12
     13        Layout test changes include modifications of existing tests to accomodate the new image dimensions, as well as new tests for this
     14        specific functionality.
     15
     16        * fast/hidpi/image-srcset-change-dynamically-from-js-2x-expected.txt:
     17        * fast/hidpi/image-srcset-change-dynamically-from-js-2x.html:
     18        * fast/hidpi/image-srcset-data-escaped-srcset-expected.txt:
     19        * fast/hidpi/image-srcset-data-escaped-srcset.html:
     20        * fast/hidpi/image-srcset-data-src.html:
     21        * fast/hidpi/image-srcset-data-srcset.html:
     22        * fast/hidpi/image-srcset-fraction.html:
     23        * fast/hidpi/image-srcset-intrinsic-size-expected.txt: Added.
     24        * fast/hidpi/image-srcset-intrinsic-size.html: Added.
     25        * fast/hidpi/image-srcset-invalid-inputs-correct-src-expected.txt:
     26        * fast/hidpi/image-srcset-invalid-inputs-correct-src.html:
     27        * fast/hidpi/image-srcset-invalid-inputs.html:
     28        * fast/hidpi/image-srcset-invalid-inputs-expected.txt: Added.
     29        * fast/hidpi/image-srcset-only-src-attribute-expected.txt: Added.
     30        * fast/hidpi/image-srcset-only-src-attribute.html:
     31        * fast/hidpi/image-srcset-png-canvas-expected.html: Added.
     32        * fast/hidpi/image-srcset-png-canvas.html: Added.
     33        * fast/hidpi/image-srcset-png-expected.html: Added.
     34        * fast/hidpi/image-srcset-png.html: Added.
     35        * fast/hidpi/image-srcset-relative-svg-expected.html: Added.
     36        * fast/hidpi/image-srcset-relative-svg.html: Added.
     37        * fast/hidpi/image-srcset-remove-dynamically-from-js.html:
     38        * fast/hidpi/image-srcset-simple-2x-expected.txt:
     39        * fast/hidpi/image-srcset-simple-2x.html:
     40        * fast/hidpi/image-srcset-space-left-nomodifier-expected.txt: Added.
     41        * fast/hidpi/image-srcset-space-left-nomodifier.html: Copied from LayoutTests/fast/hidpi/image-srcset-data-srcset.html.
     42        * fast/hidpi/image-srcset-svg-expected.html: Added.
     43        * fast/hidpi/image-srcset-svg.html: Added.
     44        * fast/hidpi/image-srcset-svg2-expected.html: Added.
     45        * fast/hidpi/image-srcset-svg2.html: Added.
     46        * fast/hidpi/resources/green-400-px-square.png: Added.
     47        * fast/hidpi/resources/relativesrcset.svg: Added.
     48        * fast/hidpi/resources/srcset-helper.js:
     49        (runTest):
     50        * fast/hidpi/resources/srcset.png: Added.
     51        * fast/hidpi/resources/srcset.svg: Added.
     52        * fast/hidpi/resources/srcset_100px.svg: Added.
     53        * fast/hidpi/resources/svg_canvas_helper.js: Added.
     54        (drawCanvas):
     55        * fast/hidpi/resources/svg_tests.css: Added.
     56        (.test):
     57        (.test img, .test canvas):
     58        (.test .stats):
     59        (.expected, .actual):
     60        * platform/mac/fast/hidpi/image-srcset-only-src-attribute-expected.png: Removed.
     61        * platform/mac/fast/hidpi/image-srcset-only-src-attribute-expected.txt: Removed.
     62
     63        The following tests were added, but skipped, since they reveal an unrelated SVG on canvas rendering issue:
     64        * fast/hidpi/image-srcset-svg-canvas-2x-expected.html: Added.
     65        * fast/hidpi/image-srcset-svg-canvas-2x.html: Added.
     66        * fast/hidpi/image-srcset-svg-canvas-expected.html: Added.
     67        * fast/hidpi/image-srcset-svg-canvas.html: Added.
     68        * fast/hidpi/image-srcset-relative-svg-canvas-2x-expected.html: Added.
     69        * fast/hidpi/image-srcset-relative-svg-canvas-2x.html: Added.
     70        * fast/hidpi/image-srcset-relative-svg-canvas-expected.html: Added.
     71        * fast/hidpi/image-srcset-relative-svg-canvas.html: Added.
     72
    1732014-02-04  Geoffrey Garen  <ggaren@apple.com>
    274
  • trunk/LayoutTests/TestExpectations

    r163329 r163415  
    5959webkit.org/b/120148 [ Debug ] webaudio/javascriptaudionode-downmix8-2channel-input.html [ Pass Crash ]
    6060
     61webkit.org/b/124342 fast/hidpi/image-srcset-svg-canvas.html [ Failure ]
     62webkit.org/b/124342 fast/hidpi/image-srcset-svg-canvas-2x.html [ Failure ]
     63webkit.org/b/124349 fast/hidpi/image-srcset-relative-svg-canvas-2x.html [ Failure ]
     64webkit.org/b/124349 fast/hidpi/image-srcset-relative-svg-canvas.html [ Failure ]
     65
    6166webaudio/javascriptaudionode-downmix8-2channel-input.html
    6267
  • trunk/LayoutTests/fast/hidpi/image-srcset-change-dynamically-from-js-2x-expected.txt

    r154582 r163415  
    1 PASS internals.isPreloaded("resources/blue-100-px-square.png") is false
     1blue-100-px-square.png has MIME type image/png
     2image-srcset-change-dynamically-from-js-2x.html has MIME type text/html
     3srcset-helper.js has MIME type text/javascript
     4js-test-pre.js has MIME type text/javascript
     5green-400-px-square.png has MIME type image/png
    26PASS document.getElementById("foo").clientWidth==200 is true
    37This test passes if this img tag below is a green square when the scale factor is 2. It ensures that attributes can be changed dynamically from javascript, and that only the correct resource is loaded.
  • trunk/LayoutTests/fast/hidpi/image-srcset-change-dynamically-from-js-2x.html

    r155269 r163415  
    66    if (window.testRunner) {
    77        testRunner.dumpAsText();
     8        testRunner.dumpResourceResponseMIMETypes();
    89    }
    910
     
    1112        var img = document.getElementById("foo");
    1213        // srcset must be set first, otherwise 'src' is loaded as well
    13         img.srcset = "resources/green-200-px-square.png 2x";
     14        img.srcset = "resources/blue-100-px-square.png 1x, resources/green-400-px-square.png 2x";
    1415        img.src = "resources/blue-100-px-square.png"
    1516    }
     
    1920    }, false);
    2021    addEventListener("load", function() {
    21         if (internals)
    22             shouldBeFalse('internals.isPreloaded("resources/blue-100-px-square.png")');
    2322        shouldBeTrue('document.getElementById("foo").clientWidth==200');
    2423    }, false);
  • trunk/LayoutTests/fast/hidpi/image-srcset-data-escaped-srcset-expected.txt

    r155988 r163415  
    1 PASS document.getElementById("foo").clientWidth==100 is true
     1PASS document.getElementById("foo").clientWidth==50 is true
    22This test passes if the image below is not empty. It ensures that the srcset attribute support data URI schemes with escaped characters.
    33
  • trunk/LayoutTests/fast/hidpi/image-srcset-data-escaped-srcset.html

    r155988 r163415  
    88
    99    addEventListener("load", function() {
    10         shouldBeTrue('document.getElementById("foo").clientWidth==100');
     10        shouldBeTrue('document.getElementById("foo").clientWidth==50');
    1111    }, false);
    1212</script>
  • trunk/LayoutTests/fast/hidpi/image-srcset-data-src.html

    r155269 r163415  
    33<script src="../../resources/js-test-pre.js"></script>
    44<script>
    5     if (window.testRunner) {
    6         testRunner.dumpAsText();
    7     }
    8 
    95    addEventListener("load", function() {
    106        shouldBeTrue('document.getElementById("foo").clientWidth==150');
  • trunk/LayoutTests/fast/hidpi/image-srcset-data-srcset.html

    r155988 r163415  
    33<script src="../../resources/js-test-pre.js"></script>
    44<script>
    5     if (window.testRunner) {
    6         testRunner.dumpAsText();
    7     }
    8 
    95    addEventListener("load", function() {
    106        shouldBeTrue('document.getElementById("foo").clientWidth==150');
  • trunk/LayoutTests/fast/hidpi/image-srcset-fraction-1.5x.html

    r155988 r163415  
    1919<body>
    2020<div>This test passes if the srcset resource is loaded and displayed as the image</div>
    21 <img src="resources/blue-100-px-square.png" srcset="resources/green-200-px-square.png 2x" id="testimg">
     21<img src="resources/blue-100-px-square.png" srcset="resources/green-400-px-square.png 2x" id="testimg">
    2222</body>
    2323</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-fraction.html

    r155269 r163415  
    77<script src="../../resources/js-test-pre.js"></script>
    88<script>
    9     if (window.testRunner) {
    10         testRunner.dumpAsText();
    11     }
    12 
    139    addEventListener("load", function() {
    1410        if (internals)
     
    1915<body>
    2016<div>This test passes if the srcset resource is loaded and displayed as the image</div>
    21 <img src="resources/blue-100-px-square.png" srcset="resources/green-200-px-square.png 2x" id="testimg">
     17<img src="resources/blue-100-px-square.png" srcset="resources/green-400-px-square.png 2x" id="testimg">
    2218</body>
    2319</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src-expected.txt

    r154582 r163415  
    1 PASS document.getElementById("foo").clientWidth==200 is true
     1PASS document.getElementById("foo").clientWidth==400 is true
    22This test passes if this img tag below is a green square regardless of the scale factor. It ensures that invalid inputs from srcset are ignored, and src is selected (since it's the only candidate left)
    33
  • trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src.html

    r155269 r163415  
    99
    1010    addEventListener("load", function() {
    11         shouldBeTrue('document.getElementById("foo").clientWidth==200');
     11        shouldBeTrue('document.getElementById("foo").clientWidth==400');
    1212    }, false);
    1313</script>
     
    1717    <div>This test passes if this img tag below is a green square regardless of the scale factor. It ensures that invalid inputs
    1818    from srcset are ignored, and src is selected (since it's the only candidate left)</div>
    19     <img id="foo" src="resources/green-200-px-square.png" srcset="1x,,  ,      , 2x ,,">
     19    <img id="foo" src="resources/green-400-px-square.png" srcset="1x,,  ,      , 2x ,,">
    2020</body>
    2121</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-except-one.html

    r155988 r163415  
    1717    <div>This test passes if the img tag below is a green square regardless of the scale factor. It ensures that invalid inputs are
    1818    ignored and well-formed images are chosen regardless of their qualifiers, once they are the only candidate left</div>
    19     <img id="foo" src="" srcset="1x,,  ,   x    ,2x  , foo.jpg, 3x, bar.jpg 4x 100h, foo.jpg 5, bar.jpg dx, resources/green-200-px-square.png   2x ,"></img>
     19    <img id="foo" src="" srcset="1x,,  ,   x    ,2x  , foo.jpg, 3x, bar.jpg 4x 100h, foo.jpg 5, bar.jpg dx, resources/green-400-px-square.png   2x ,"></img>
    2020</body>
    2121</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs.html

    r155988 r163415  
    11<html>
    22<head>
    3 <script src="resources/srcset-helper.js"></script>
     3<script src="../../resources/js-test-pre.js"></script>
    44</head>
    55
    66<body id="body">
    77    <div>This test passes if this img tag below is empty and displays nothing. It ensures that the srcset attribute supports invalid inputs</div>
    8     <img height="100" width="100" src="" srcset="1x,,  ,   x    ,2x  , foo.jpg, 3x, bar.jpg 4x 100h, foo.jpg 5, bar.jpg dx,foo.jpg,bar.jpg,"></img>
     8    <img id="foo" src="" srcset="1x,,  ,   x    ,2x  " onerror="testPassed('did not load invalid inputs')" onload="testFailed('Loaded
     9    invalid inputs')"></img>
    910</body>
    1011</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-only-src-attribute.html

    r153625 r163415  
     1<head>
    12<html>
    2 <head>
    33<script src="resources/srcset-helper.js"></script>
     4<script src="../../resources/js-test-pre.js"></script>
     5<script>
     6    if (window.testRunner) {
     7        testRunner.dumpAsText();
     8    }
     9    addEventListener("load", function() {
     10        shouldBeTrue('document.getElementById("foo").clientWidth==200');
     11    }, false);
     12</script>
    413</head>
    5 
    614<body id="body">
    715    <div>This test passes if this img tag below is a green square when the scale factor is 2. It ensures that the selection algorithm does not change the behavior of the src attribute, even with a scale factor greater than 1</div>
    8     <img height="100" width="100" src="resources/green-200-px-square.png"></img>
     16    <img id="foo" src="resources/green-200-px-square.png"></img>
    917</body>
    1018</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-remove-dynamically-from-js.html

    r155269 r163415  
    2727<body id="body">
    2828    <div>This test passes if this img tag below is a green square. It ensures that attributes can be removed dynamically from javascript</div>
    29     <img id="foo" src="resources/blue-100-px-square.png" srcset="resources/green-200-px-square.png 2x">
     29    <img id="foo" src="resources/blue-100-px-square.png" srcset="resources/green-400-px-square.png 2x">
    3030</body>
    3131</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-simple-2x-expected.txt

    r154582 r163415  
    1 PASS document.getElementById("foo").clientWidth==800 is true
     1PASS document.getElementById("foo").clientWidth==200 is true
    22This test passes if the image below says 1x with a reddish background when the deviceScaleFactor is 1, and if says 2x with a greenish background when the deviceScaleFactor is 2.
    33
  • trunk/LayoutTests/fast/hidpi/image-srcset-simple-2x.html

    r155269 r163415  
    77<script src="../../resources/js-test-pre.js"></script>
    88<script>
    9     if (window.testRunner) {
    10         testRunner.dumpAsText();
    11     }
    12 
    139    addEventListener("load", function() {
    14         shouldBeTrue('document.getElementById("foo").clientWidth==800');
     10        shouldBeTrue('document.getElementById("foo").clientWidth==200');
    1511    }, false);
    1612</script>
     
    1915<body id="body">
    2016    <div>This test passes if the image below says 1x with a reddish background when the deviceScaleFactor is 1, and if says 2x with a greenish background when the deviceScaleFactor is 2.</div>
    21     <img id="foo" src="" srcset="resources/image-set-1x.png 1x, resources/deleteButton.png 3x, resources/image-set-2x.png 2x">
     17    <img id="foo" src="" srcset="resources/blue-100-px-square.png 1x, resources/deleteButton.png 3x, resources/green-400-px-square.png 2x">
    2218</body>
    2319</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-space-left-nomodifier.html

    r163413 r163415  
    11<html>
    22<head>
     3<script src="resources/srcset-helper.js"></script>
    34<script src="../../resources/js-test-pre.js"></script>
    45<script>
     
    1213</script>
    1314</head>
     15
    1416<body id="body">
    15     <div>This test passes if the image below looks like a 2x2 grid (yellow, gray, light green, dark green). In this case the srcset attribute has a base64 url.</div>
    16     <img id="foo" src="" srcset="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAA8CAIAAAAL5NQ9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2woaBQc4oLEFpAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACMSURBVHja7dNBEYAgFEVRPhHMYgAzUIsmVnFvB/fsoQb+ObfBmzMvxneW1D1vzz2wFiEUQiFEKIRCKIQIhVAIhRChEAqhECIUQiEUQoRCKIRCiFAIhVAIEep3xTWTLzzu5oVCKIRCiFAIhVAIEQqhEAohQiEUQiFEKIRCKIQIhVAIhRChEAqhECLUZi3VEwcBMGr1NgAAAABJRU5ErkJggg== 2x, data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAA8CAIAAAAL5NQ9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2woaBQc4oLEFpAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACMSURBVHja7dNBEYAgFEVRPhHMYgAzUIsmVnFvB/fsoQb+ObfBmzMvxneW1D1vzz2wFiEUQiFEKIRCKIQIhVAIhRChEAqhECIUQiEUQoRCKIRCiFAIhVAIEep3xTWTLzzu5oVCKIRCiFAIhVAIEQqhEAohQiEUQiFEKIRCKIQIhVAIhRChEAqhECLUZi3VEwcBMGr1NgAAAABJRU5ErkJggg== 1x">
     17    <div>This test passes if the image below is not empty. It ensures that a candidate without scale modifier get a default one, even with space left at the end.</div>
     18    <img id="foo" src="" srcset="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAA8CAIAAAAL5NQ9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH2woaBQc4oLEFpAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACMSURBVHja7dNBEYAgFEVRPhHMYgAzUIsmVnFvB/fsoQb+ObfBmzMvxneW1D1vzz2wFiEUQiFEKIRCKIQIhVAIhRChEAqhECIUQiEUQoRCKIRCiFAIhVAIEep3xTWTLzzu5oVCKIRCiFAIhVAIEQqhEAohQiEUQiFEKIRCKIQIhVAIhRChEAqhECLUZi3VEwcBMGr1NgAAAABJRU5ErkJggg==  ">
    1719</body>
    1820</html>
  • trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-2x.html

    r155269 r163415  
    1919<body id="body">
    2020    <div>This test passes if the div below is a green 200px square when the deviceScaleFactor is 2. It simply ensures that the src attribute is taken into account by the selection algorithm when this one is processing the images candidates</div>
    21     <img id="foo" src="resources/blue-100-px-square.png" srcset="resources/green-200-px-square.png 2x">
     21    <img id="foo" src="resources/blue-100-px-square.png" srcset="resources/green-400-px-square.png 2x">
    2222</body>
    2323</html>
  • trunk/LayoutTests/fast/hidpi/resources/srcset-helper.js

    r153625 r163415  
    1414        delete sessionStorage.pageReloaded;
    1515        delete sessionStorage.scaleFactorIsSet;
    16         testRunner.notifyDone();
     16        if (!window.manualNotifyDone)
     17            testRunner.notifyDone();
    1718    } else {
    1819        // Right now there is a bug that srcset does not properly deal with dynamic changes to the scale factor,
  • trunk/Source/WebCore/ChangeLog

    r163413 r163415  
     12014-02-04  Yoav Weiss  <yoav@yoav.ws>
     2
     3        Use srcset's pixel density to determine intrinsic size
     4        https://bugs.webkit.org/show_bug.cgi?id=123832
     5
     6        Reviewed by Dean Jackson.
     7
     8        The patch is a port of a similar Blink patch: https://codereview.chromium.org/25105004
     9        According to the spec "When an img element has a current pixel density that is not 1.0,
     10        the element's image data must be treated as if its resolution, in device pixels per CSS pixels,
     11        was the current pixel density."
     12
     13        I've added that support using the following changes:
     14        - bestFitSourceForImageAttributes now returns the image candidate to HTMLImageElement.
     15        - HTMLImageElement passes the devicePixelRatio data to RenderImage, which stores it.
     16        - Bitmap images are scaled using the devicePixelRatio at RenderImageResource's intrinsicSize() and imageSize().
     17        - SVG images are scaled using the devicePixelRatio at RenderReplaced::computeAspectRatioInformationForRenderBox.
     18        - Canvas support added at CanvasRenderingContext2D::size.
     19
     20        Tests: fast/hidpi/image-srcset-intrinsic-size.html
     21               fast/hidpi/image-srcset-png-canvas.html
     22               fast/hidpi/image-srcset-png.html
     23               fast/hidpi/image-srcset-relative-svg-canvas-2x.html
     24               fast/hidpi/image-srcset-relative-svg.html
     25               fast/hidpi/image-srcset-space-left-nomodifier.html
     26               fast/hidpi/image-srcset-svg-canvas-2x.html
     27               fast/hidpi/image-srcset-svg-canvas.html
     28               fast/hidpi/image-srcset-svg.html
     29               fast/hidpi/image-srcset-svg2.html
     30
     31        * html/HTMLImageElement.cpp:
     32        (WebCore::HTMLImageElement::HTMLImageElement):
     33        (WebCore::HTMLImageElement::parseAttribute):
     34        (WebCore::HTMLImageElement::createRenderer):
     35        * html/HTMLImageElement.h:
     36        * html/canvas/CanvasRenderingContext2D.cpp:
     37        (WebCore::size):
     38        (WebCore::CanvasRenderingContext2D::drawImage):
     39        * html/parser/HTMLParserIdioms.cpp:
     40        (WebCore::compareByScaleFactor):
     41        (WebCore::parseImagesWithScaleFromSrcsetAttribute):
     42        (WebCore::bestFitSourceForImageAttributes):
     43        * html/parser/HTMLParserIdioms.h:
     44        (WebCore::ImageWithScale::ImageWithScale):
     45        (WebCore::ImageWithScale::imageURL):
     46        (WebCore::ImageWithScale::scaleFactor):
     47        * html/parser/HTMLPreloadScanner.cpp:
     48        (WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
     49        * rendering/RenderImage.cpp:
     50        (WebCore::RenderImage::RenderImage):
     51        * rendering/RenderImage.h:
     52        (WebCore::RenderImage::setImageDevicePixelRatio):
     53        (WebCore::RenderImage::imageDevicePixelRatio):
     54        * rendering/RenderImageResource.cpp:
     55        (WebCore::RenderImageResource::imageSize):
     56        (WebCore::RenderImageResource::intrinsicSize):
     57        (WebCore::RenderImageResource::getImageSize):
     58        * rendering/RenderImageResource.h:
     59        * rendering/RenderReplaced.cpp:
     60        (WebCore::RenderReplaced::computeAspectRatioInformationForRenderBox):
     61
    1622014-02-04  Geoffrey Garen  <ggaren@apple.com>
    263
  • trunk/Source/WebCore/html/HTMLImageElement.cpp

    r162679 r163415  
    4646    , m_form(form)
    4747    , m_compositeOperator(CompositeSourceOver)
     48    , m_imageDevicePixelRatio(1.0f)
    4849{
    4950    ASSERT(hasTagName(imgTag));
     
    119120            toRenderImage(renderer())->updateAltText();
    120121    } else if (name == srcAttr || name == srcsetAttr) {
    121         m_bestFitImageURL = bestFitSourceForImageAttributes(document().deviceScaleFactor(), fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr));
     122        ImageWithScale candidate = bestFitSourceForImageAttributes(document().deviceScaleFactor(), fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr));
     123        m_bestFitImageURL = candidate.imageURL(fastGetAttribute(srcAttr), fastGetAttribute(srcsetAttr));
     124        float candidateScaleFactor = candidate.scaleFactor();
     125        if (candidateScaleFactor > 0)
     126            m_imageDevicePixelRatio = 1 / candidateScaleFactor;
     127        if (renderer() && renderer()->isImage())
     128            toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRatio);
    122129        m_imageLoader.updateFromElementIgnoringPreviousError();
    123130    } else if (name == usemapAttr) {
     
    180187        return RenderElement::createFor(*this, std::move(style));
    181188
    182     return createRenderer<RenderImage>(*this, std::move(style));
     189    return createRenderer<RenderImage>(*this, std::move(style), nullptr, m_imageDevicePixelRatio);
    183190}
    184191
  • trunk/Source/WebCore/html/HTMLImageElement.h

    r162158 r163415  
    122122    AtomicString m_bestFitImageURL;
    123123    AtomicString m_lowercasedUsemap;
     124    float m_imageDevicePixelRatio;
    124125};
    125126
  • trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp

    r163079 r163415  
    4949#include "ImageData.h"
    5050#include "RenderElement.h"
     51#include "RenderImage.h"
    5152#include "RenderLayer.h"
    5253#include "SecurityOrigin.h"
     
    11971198}
    11981199
    1199 static LayoutSize size(HTMLImageElement* image)
    1200 {
    1201     if (CachedImage* cachedImage = image->cachedImage())
    1202         return cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this.
    1203     return IntSize();
     1200enum ImageSizeType {
     1201    ImageSizeAfterDevicePixelRatio,
     1202    ImageSizeBeforeDevicePixelRatio
     1203};
     1204
     1205static LayoutSize size(HTMLImageElement* image, ImageSizeType sizeType)
     1206{
     1207    LayoutSize size;
     1208    if (CachedImage* cachedImage = image->cachedImage()) {
     1209        size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this.
     1210
     1211        if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && image->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image()->hasRelativeWidth())
     1212            size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio());
     1213    }
     1214    return size;
    12041215}
    12051216
     
    12271238        return;
    12281239    }
    1229     LayoutSize s = size(image);
    1230     drawImage(image, x, y, s.width(), s.height(), ec);
     1240    LayoutSize destRectSize = size(image, ImageSizeAfterDevicePixelRatio);
     1241    drawImage(image, x, y, destRectSize.width(), destRectSize.height(), ec);
    12311242}
    12321243
     
    12381249        return;
    12391250    }
    1240     LayoutSize s = size(image);
    1241     drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec);
     1251    LayoutSize sourceRectSize = size(image, ImageSizeBeforeDevicePixelRatio);
     1252    drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.height()), FloatRect(x, y, width, height), ec);
    12421253}
    12431254
     
    12761287    FloatRect normalizedDstRect = normalizeRect(dstRect);
    12771288
    1278     FloatRect imageRect = FloatRect(FloatPoint(), size(image));
     1289    FloatRect imageRect = FloatRect(FloatPoint(), size(image, ImageSizeBeforeDevicePixelRatio));
    12791290    if (!srcRect.width() || !srcRect.height()) {
    12801291        ec = INDEX_SIZE_ERR;
  • trunk/Source/WebCore/html/parser/HTMLParserIdioms.cpp

    r163398 r163415  
    291291}
    292292
    293 struct ImageWithScale {
    294     unsigned imageURLStart;
    295     unsigned imageURLLength;
    296     float scaleFactor;
    297 
    298     ImageWithScale()
    299         : imageURLStart(0)
    300         , imageURLLength(0)
    301         , scaleFactor(1)
    302     {
    303     }
    304 
    305     bool hasImageURL() const
    306     {
    307         return imageURLLength;
    308     }
    309 };
    310293typedef Vector<ImageWithScale> ImageCandidates;
    311294
    312295static inline bool compareByScaleFactor(const ImageWithScale& first, const ImageWithScale& second)
    313296{
    314     return first.scaleFactor < second.scaleFactor;
     297    return first.scaleFactor() < second.scaleFactor();
    315298}
    316299
     
    390373            }
    391374        }
    392         ImageWithScale image;
    393         image.imageURLStart = imageURLStart;
    394         image.imageURLLength = imageURLEnd - imageURLStart;
    395         image.scaleFactor = imageScaleFactor;
    396 
     375        ImageWithScale image(imageURLStart, imageURLEnd - imageURLStart, imageScaleFactor);
    397376        imageCandidates.append(image);
    398377        // 11. Return to the step labeled splitting loop.
     
    401380}
    402381
    403 String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute)
     382ImageWithScale bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& srcsetAttribute)
    404383{
    405384    ImageCandidates imageCandidates;
     
    413392
    414393    if (imageCandidates.isEmpty())
    415         return String();
     394        return ImageWithScale();
    416395
    417396    std::stable_sort(imageCandidates.begin(), imageCandidates.end(), compareByScaleFactor);
    418397
    419398    for (size_t i = 0; i < imageCandidates.size() - 1; ++i) {
    420         if (imageCandidates[i].scaleFactor >= deviceScaleFactor)
    421             return imageCandidates[i].hasImageURL() ? srcsetAttribute.substringSharingImpl(imageCandidates[i].imageURLStart, imageCandidates[i].imageURLLength) : srcAttribute;
     399        if (imageCandidates[i].scaleFactor() >= deviceScaleFactor)
     400            return imageCandidates[i];
    422401    }
    423402    const ImageWithScale& lastCandidate = imageCandidates.last();
    424     return lastCandidate.hasImageURL() ? srcsetAttribute.substringSharingImpl(lastCandidate.imageURLStart, lastCandidate.imageURLLength) : srcAttribute;
    425 }
    426 
    427 }
     403    return lastCandidate;
     404}
     405
     406}
  • trunk/Source/WebCore/html/parser/HTMLParserIdioms.h

    r162258 r163415  
    3333
    3434class Decimal;
     35
     36class ImageWithScale {
     37public:
     38    ImageWithScale()
     39        : m_imageURLStart(0)
     40        , m_imageURLLength(0)
     41        , m_scaleFactor(1)
     42    {
     43    }
     44
     45    ImageWithScale(unsigned start, unsigned length, float scaleFactor)
     46        : m_imageURLStart(start)
     47        , m_imageURLLength(length)
     48        , m_scaleFactor(scaleFactor)
     49    {
     50    }
     51
     52    String imageURL(const String& srcAttribute, const String& srcsetAttribute) const
     53    {
     54        return m_imageURLLength ? srcsetAttribute.substringSharingImpl(m_imageURLStart, m_imageURLLength) : srcAttribute;
     55    }
     56
     57    float scaleFactor() const
     58    {
     59        return m_scaleFactor;
     60    }
     61
     62private:
     63    unsigned m_imageURLStart;
     64    unsigned m_imageURLLength;
     65    float m_scaleFactor;
     66};
    3567
    3668// Space characters as defined by the HTML specification.
     
    100132bool threadSafeMatch(const QualifiedName&, const QualifiedName&);
    101133
    102 String bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& sourceSetAttribute);
     134ImageWithScale bestFitSourceForImageAttributes(float deviceScaleFactor, const String& srcAttribute, const String& sourceSetAttribute);
    103135
    104136}
  • trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp

    r162275 r163415  
    105105        // Resolve between src and srcSet if we have them.
    106106        if (!m_srcSetAttribute.isEmpty()) {
    107             String srcMatchingScale = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute);
     107            ImageWithScale imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, m_urlToLoad, m_srcSetAttribute);
     108            String srcMatchingScale = imageCandidate.imageURL(m_urlToLoad, m_srcSetAttribute);
    108109            setUrlToLoad(srcMatchingScale, true);
    109110        }
  • trunk/Source/WebCore/rendering/RenderImage.cpp

    r163079 r163415  
    117117using namespace HTMLNames;
    118118
    119 RenderImage::RenderImage(Element& element, PassRef<RenderStyle> style, StyleImage* styleImage)
     119RenderImage::RenderImage(Element& element, PassRef<RenderStyle> style, StyleImage* styleImage, const float imageDevicePixelRatio)
    120120    : RenderReplaced(element, std::move(style), IntSize())
    121121    , m_imageResource(styleImage ? std::make_unique<RenderImageResourceStyleImage>(*styleImage) : std::make_unique<RenderImageResource>())
     
    123123    , m_didIncrementVisuallyNonEmptyPixelCount(false)
    124124    , m_isGeneratedContent(false)
     125    , m_imageDevicePixelRatio(imageDevicePixelRatio)
    125126{
    126127    updateAltText();
     
    134135    , m_didIncrementVisuallyNonEmptyPixelCount(false)
    135136    , m_isGeneratedContent(false)
     137    , m_imageDevicePixelRatio(1.0f)
    136138{
    137139    imageResource().initialize(this);
  • trunk/Source/WebCore/rendering/RenderImage.h

    r162972 r163415  
    3636class RenderImage : public RenderReplaced {
    3737public:
    38     RenderImage(Element&, PassRef<RenderStyle>, StyleImage* = nullptr);
     38    RenderImage(Element&, PassRef<RenderStyle>, StyleImage* = nullptr, const float = 1.0f);
    3939    RenderImage(Document&, PassRef<RenderStyle>, StyleImage* = nullptr);
    4040    virtual ~RenderImage();
     
    6363    const String& altText() const { return m_altText; }
    6464    void setAltText(const String& altText) { m_altText = altText; }
    65    
     65
     66    inline void setImageDevicePixelRatio(float factor) { m_imageDevicePixelRatio = factor; }
     67    float imageDevicePixelRatio() const { return m_imageDevicePixelRatio; }
     68
    6669protected:
    6770    virtual bool needsPreferredWidthsRecalculation() const override final;
     
    114117    bool m_didIncrementVisuallyNonEmptyPixelCount;
    115118    bool m_isGeneratedContent;
     119    float m_imageDevicePixelRatio;
    116120
    117121    friend class RenderImageScaleObserver;
  • trunk/Source/WebCore/rendering/RenderImageResource.cpp

    r160478 r163415  
    3232#include "Image.h"
    3333#include "RenderElement.h"
     34#include "RenderImage.h"
    3435#include "RenderImageResourceStyleImage.h"
    3536
     
    119120LayoutSize RenderImageResource::imageSize(float multiplier) const
    120121{
    121     return m_cachedImage ? m_cachedImage->imageSizeForRenderer(m_renderer, multiplier) : LayoutSize();
     122    return getImageSize(multiplier, CachedImage::UsedSize);
    122123}
    123124
    124125LayoutSize RenderImageResource::intrinsicSize(float multiplier) const
    125126{
    126     return m_cachedImage ? m_cachedImage->imageSizeForRenderer(m_renderer, multiplier, CachedImage::IntrinsicSize) : LayoutSize();
     127    return getImageSize(multiplier, CachedImage::IntrinsicSize);
     128}
     129
     130LayoutSize RenderImageResource::getImageSize(float multiplier, CachedImage::SizeType type) const
     131{
     132    if (!m_cachedImage)
     133        return LayoutSize();
     134    LayoutSize size = m_cachedImage->imageSizeForRenderer(m_renderer, multiplier, type);
     135    if (m_renderer && m_renderer->isRenderImage())
     136        size.scale(toRenderImage(m_renderer)->imageDevicePixelRatio());
     137    return size;
    127138}
    128139
  • trunk/Source/WebCore/rendering/RenderImageResource.h

    r162356 r163415  
    2727#define RenderImageResource_h
    2828
     29#include "CachedImage.h"
    2930#include "CachedResourceHandle.h"
    3031#include "StyleImage.h"
     
    6667    RenderElement* m_renderer;
    6768    CachedResourceHandle<CachedImage> m_cachedImage;
     69
     70private:
     71    LayoutSize getImageSize(float multiplier, CachedImage::SizeType) const;
    6872};
    6973
  • trunk/Source/WebCore/rendering/RenderReplaced.cpp

    r162907 r163415  
    3232#include "RenderBlock.h"
    3333#include "RenderFlowThread.h"
     34#include "RenderImage.h"
    3435#include "RenderLayer.h"
    3536#include "RenderRegion.h"
     
    271272
    272273        // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
    273         if (!isPercentageIntrinsicSize)
     274        if (!isPercentageIntrinsicSize) {
    274275            intrinsicSize.scale(style().effectiveZoom());
     276            if (isRenderImage())
     277                intrinsicSize.scale(toRenderImage(this)->imageDevicePixelRatio());
     278        }
    275279
    276280        if (hasAspectRatio() && isPercentageIntrinsicSize)
Note: See TracChangeset for help on using the changeset viewer.