<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[164929] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/164929">164929</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-03-01 15:28:40 -0800 (Sat, 01 Mar 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Fix srcset related bugs
https://bugs.webkit.org/show_bug.cgi?id=129539
Source/WebCore:
Fixed a bug reported against Blink's srcset implementation at https://code.google.com/p/chromium/issues/detail?id=347998
When both src and srcset had only 1x descriptors and the DPR was higher than 1, the src's resource was picked.
Also fixed the invalid descriptor handling, which wasn't aligned with the spec, and therefore was not as forward compatible as it should be.
Invalid descriptors caused the entire resource to be ignored, rather than just the descriptors themselves.
Patch by Yoav Weiss <yoav@yoav.ws> on 2014-03-01
Reviewed by Andreas Kling.
Tests: fast/hidpi/image-srcset-invalid-descriptor.html
fast/hidpi/image-srcset-src-selection-1x-both.html
* html/parser/HTMLParserIdioms.cpp:
(WebCore::parseDescriptors):
(WebCore::parseImagesWithScaleFromSrcsetAttribute):
(WebCore::bestFitSourceForImageAttributes):
LayoutTests:
These tests make sure that:
1. Invalid srcset descriptors are handled according to the spec. The invalid descriptors are ignored, but the resource is not.
2. When both src and srcset have only 1x descriptors and the DPR is higher than 1, the srcset's resource is picked.
I've also fixed the invalid inputs test, which was faulty.
Patch by Yoav Weiss <yoav@yoav.ws> on 2014-03-01
Reviewed by Andreas Kling.
* fast/hidpi/image-srcset-invalid-descriptor-expected.txt: Added.
* fast/hidpi/image-srcset-invalid-descriptor.html: Added.
* fast/hidpi/image-srcset-invalid-inputs-correct-src.html:
* fast/hidpi/image-srcset-src-selection-1x-both-expected.txt: Added.
* fast/hidpi/image-srcset-src-selection-1x-both.html: Added.
* fast/hidpi/resources/srcset-helper.js:
(runTest):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasthidpiimagesrcsetinvalidinputscorrectsrchtml">trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src.html</a></li>
<li><a href="#trunkLayoutTestsfasthidpiresourcessrcsethelperjs">trunk/LayoutTests/fast/hidpi/resources/srcset-helper.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLParserIdiomscpp">trunk/Source/WebCore/html/parser/HTMLParserIdioms.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasthidpiimagesrcsetinvaliddescriptorexpectedtxt">trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthidpiimagesrcsetinvaliddescriptorhtml">trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor.html</a></li>
<li><a href="#trunkLayoutTestsfasthidpiimagesrcsetsrcselection1xbothexpectedtxt">trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthidpiimagesrcsetsrcselection1xbothhtml">trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (164928 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-03-01 23:22:56 UTC (rev 164928)
+++ trunk/LayoutTests/ChangeLog        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2014-03-01 Yoav Weiss <yoav@yoav.ws>
+
+ Fix srcset related bugs
+ https://bugs.webkit.org/show_bug.cgi?id=129539
+
+ These tests make sure that:
+ 1. Invalid srcset descriptors are handled according to the spec. The invalid descriptors are ignored, but the resource is not.
+ 2. When both src and srcset have only 1x descriptors and the DPR is higher than 1, the srcset's resource is picked.
+
+ I've also fixed the invalid inputs test, which was faulty.
+
+ Reviewed by Andreas Kling.
+
+ * fast/hidpi/image-srcset-invalid-descriptor-expected.txt: Added.
+ * fast/hidpi/image-srcset-invalid-descriptor.html: Added.
+ * fast/hidpi/image-srcset-invalid-inputs-correct-src.html:
+ * fast/hidpi/image-srcset-src-selection-1x-both-expected.txt: Added.
+ * fast/hidpi/image-srcset-src-selection-1x-both.html: Added.
+ * fast/hidpi/resources/srcset-helper.js:
+ (runTest):
+
</ins><span class="cx"> 2014-03-01 Adenilson Cavalcanti <cavalcantii@gmail.com>
</span><span class="cx">
</span><span class="cx"> Set css3/filter/huge-region as skipped
</span></span></pre></div>
<a id="trunkLayoutTestsfasthidpiimagesrcsetinvaliddescriptorexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor-expected.txt (0 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor-expected.txt        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS document.getElementById("foo").clientWidth==100 is true
+PASS document.getElementById("foo2").clientWidth==200 is true
+This test passes if the image below is a 100px blue square when the deviceScaleFactor is 1.
+It tests that even though the 1x resource contains many invalid descriptors, only the invalid descriptors are ignored (according to the spec).
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthidpiimagesrcsetinvaliddescriptorhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor.html (0 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor.html         (rev 0)
+++ trunk/LayoutTests/fast/hidpi/image-srcset-invalid-descriptor.html        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+<html>
+<head>
+<script>
+ window.targetScaleFactor = 1;
+</script>
+<script src="resources/srcset-helper.js"></script>
+<script src="../../resources/js-test.js"></script>
+<script>
+ addEventListener("load", function() {
+ shouldBeTrue('document.getElementById("foo").clientWidth==100');
+ shouldBeTrue('document.getElementById("foo2").clientWidth==200');
+ }, false);
+</script>
+</head>
+
+<body id="body">
+ <div>This test passes if the image below is a 100px blue square when the deviceScaleFactor is 1.</div>
+ <div> It tests that even though the 1x resource contains many invalid descriptors,
+ only the invalid descriptors are ignored (according to the spec).</div>
+ <img id="foo" src="" srcset="resources/blue-100-px-square.png 43q 1x dfs 3dd, resources/green-400-px-square.png 2x">
+ <img id="foo2" src="" srcset="resources/blue-100-px-square.png 300q, resources/green-400-px-square.png 2x">
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthidpiimagesrcsetinvalidinputscorrectsrchtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src.html (164928 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src.html        2014-03-01 23:22:56 UTC (rev 164928)
+++ trunk/LayoutTests/fast/hidpi/image-srcset-invalid-inputs-correct-src.html        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -16,6 +16,6 @@
</span><span class="cx"> <body id="body">
</span><span class="cx"> <div>This test passes if this img tag below is a green square regardless of the scale factor. It ensures that invalid inputs
</span><span class="cx"> from srcset are ignored, and src is selected (since it's the only candidate left)</div>
</span><del>- <img id="foo" src="resources/green-400-px-square.png" srcset="1x,, , , 2x ,,">
</del><ins>+ <img id="foo" src="resources/green-400-px-square.png" srcset="1x 5w,, , , 2x 600h,,">
</ins><span class="cx"> </body>
</span><span class="cx"> </html>
</span></span></pre></div>
<a id="trunkLayoutTestsfasthidpiimagesrcsetsrcselection1xbothexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both-expected.txt (0 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both-expected.txt         (rev 0)
+++ trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both-expected.txt        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS document.getElementById("foo").clientWidth==400 is true
+This test passes if the div below is a blue 100px square when the deviceScaleFactor is 1. It simply ensures that when both src and srcset are specified for the same DPR, srcset wins.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthidpiimagesrcsetsrcselection1xbothhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both.html (0 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both.html         (rev 0)
+++ trunk/LayoutTests/fast/hidpi/image-srcset-src-selection-1x-both.html        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+<html>
+<head>
+<script>
+ window.targetScaleFactor = 2;
+</script>
+<script src="resources/srcset-helper.js"></script>
+<script src="../../resources/js-test.js"></script>
+<script>
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ }
+
+ addEventListener("load", function() {
+ shouldBeTrue('document.getElementById("foo").clientWidth==400');
+ }, false);
+</script>
+</head>
+
+<body id="body">
+ <div>This test passes if the div below is a blue 100px square when the deviceScaleFactor is 1.
+ It simply ensures that when both src and srcset are specified for the same DPR, srcset wins.</div>
+ <img id="foo" src="resources/blue-100-px-square.png" srcset="resources/green-400-px-square.png 1x">
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthidpiresourcessrcsethelperjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/hidpi/resources/srcset-helper.js (164928 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/hidpi/resources/srcset-helper.js        2014-03-01 23:22:56 UTC (rev 164928)
+++ trunk/LayoutTests/fast/hidpi/resources/srcset-helper.js        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -5,6 +5,9 @@
</span><span class="cx"> if (!window.targetScaleFactor)
</span><span class="cx"> window.targetScaleFactor = 2;
</span><span class="cx">
</span><ins>+ if(!sessionStorage.pageReloaded && window.targetScaleFactor == window.deviceScaleFactor)
+ return;
+
</ins><span class="cx"> if (!sessionStorage.scaleFactorIsSet) {
</span><span class="cx"> testRunner.waitUntilDone();
</span><span class="cx"> testRunner.setBackingScaleFactor(targetScaleFactor, scaleFactorIsSet);
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (164928 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-03-01 23:22:56 UTC (rev 164928)
+++ trunk/Source/WebCore/ChangeLog        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2014-03-01 Yoav Weiss <yoav@yoav.ws>
+
+ Fix srcset related bugs
+ https://bugs.webkit.org/show_bug.cgi?id=129539
+
+ Fixed a bug reported against Blink's srcset implementation at https://code.google.com/p/chromium/issues/detail?id=347998
+ When both src and srcset had only 1x descriptors and the DPR was higher than 1, the src's resource was picked.
+
+ Also fixed the invalid descriptor handling, which wasn't aligned with the spec, and therefore was not as forward compatible as it should be.
+ Invalid descriptors caused the entire resource to be ignored, rather than just the descriptors themselves.
+
+ Reviewed by Andreas Kling.
+
+ Tests: fast/hidpi/image-srcset-invalid-descriptor.html
+ fast/hidpi/image-srcset-src-selection-1x-both.html
+
+ * html/parser/HTMLParserIdioms.cpp:
+ (WebCore::parseDescriptors):
+ (WebCore::parseImagesWithScaleFromSrcsetAttribute):
+ (WebCore::bestFitSourceForImageAttributes):
+
</ins><span class="cx"> 2014-03-01 Darin Adler <darin@apple.com>
</span><span class="cx">
</span><span class="cx"> Improve "bad parent" and "bad child list" assertions in line boxes
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLParserIdiomscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLParserIdioms.cpp (164928 => 164929)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLParserIdioms.cpp        2014-03-01 23:22:56 UTC (rev 164928)
+++ trunk/Source/WebCore/html/parser/HTMLParserIdioms.cpp        2014-03-01 23:28:40 UTC (rev 164929)
</span><span class="lines">@@ -302,6 +302,40 @@
</span><span class="cx"> return isHTMLSpace(character) || character == ',';
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static bool parseDescriptors(const String& attribute, size_t start, size_t end, float& imageScaleFactor)
+{
+ size_t descriptorStart;
+ size_t descriptorEnd;
+ size_t position = start;
+ bool isFoundScaleFactor = false;
+ bool isEmptyDescriptor = !(end > start);
+ bool isValid = false;
+
+ while (position < end) {
+ while (isHTMLSpace(attribute[position]) && position < end)
+ ++position;
+ descriptorStart = position;
+ while (isNotHTMLSpace(attribute[position]) && position < end)
+ ++position;
+ descriptorEnd = position;
+
+ ASSERT(descriptorEnd > descriptorStart);
+ --descriptorEnd;
+ // This part differs from the spec as the current implementation only supports pixel density descriptors.
+ if (attribute[descriptorEnd] != 'x')
+ continue;
+
+ if (isFoundScaleFactor)
+ return false;
+
+ imageScaleFactor = charactersToFloat(attribute.deprecatedCharacters() + descriptorStart, descriptorEnd - descriptorStart, &isValid);
+ isFoundScaleFactor = true;
+
+ }
+
+ return isEmptyDescriptor || isValid;
+}
+
</ins><span class="cx"> // See the specifications for more details about the algorithm to follow.
</span><span class="cx"> // http://www.w3.org/TR/2013/WD-html-srcset-20130228/#processing-the-image-candidates.
</span><span class="cx"> static void parseImagesWithScaleFromSrcsetAttribute(const String& srcsetAttribute, ImageCandidates& imageCandidates)
</span><span class="lines">@@ -335,42 +369,15 @@
</span><span class="cx"> } else {
</span><span class="cx"> // 7. Collect a sequence of characters that are not "," (U+002C) characters, and let that be descriptors.
</span><span class="cx"> size_t imageScaleStart = srcsetAttribute.find(isNotHTMLSpace, imageURLEnd + 1);
</span><del>- if (imageScaleStart == notFound)
- separator = srcsetAttributeLength;
- else if (srcsetAttribute[imageScaleStart] == ',')
- separator = imageScaleStart;
- else {
- // This part differs from the spec as the current implementation only supports pixel density descriptors for now.
- size_t imageScaleEnd = srcsetAttribute.find(isHTMLSpaceOrComma, imageScaleStart + 1);
- imageScaleEnd = (imageScaleEnd == notFound) ? srcsetAttributeLength : imageScaleEnd;
- size_t commaPosition = imageScaleEnd;
- // Make sure there are no other descriptors.
- while ((commaPosition < srcsetAttributeLength - 1) && isHTMLSpace(srcsetAttribute[commaPosition]))
- ++commaPosition;
- // If the first not html space character after the scale modifier is not a comma,
- // the current candidate is an invalid input.
- if ((commaPosition < srcsetAttributeLength - 1) && srcsetAttribute[commaPosition] != ',') {
- // Find the nearest comma and skip the input.
- commaPosition = srcsetAttribute.find(',', commaPosition + 1);
- if (commaPosition == notFound)
- break;
- imageCandidateStart = commaPosition + 1;
- continue;
- }
- separator = commaPosition;
- if (srcsetAttribute[imageScaleEnd - 1] != 'x') {
- imageCandidateStart = separator + 1;
- continue;
- }
- bool validScaleFactor = false;
- size_t scaleFactorLengthWithoutUnit = imageScaleEnd - imageScaleStart - 1;
- imageScaleFactor = charactersToFloat(srcsetAttribute.deprecatedCharacters() + imageScaleStart, scaleFactorLengthWithoutUnit, &validScaleFactor);
</del><ins>+ imageScaleStart = (imageScaleStart == notFound) ? srcsetAttributeLength : imageScaleStart;
+ size_t imageScaleEnd = srcsetAttribute.find(',' , imageScaleStart + 1);
+ imageScaleEnd = (imageScaleEnd == notFound) ? srcsetAttributeLength : imageScaleEnd;
</ins><span class="cx">
</span><del>- if (!validScaleFactor) {
- imageCandidateStart = separator + 1;
- continue;
- }
</del><ins>+ if (!parseDescriptors(srcsetAttribute, imageScaleStart, imageScaleEnd, imageScaleFactor)) {
+ imageCandidateStart = imageScaleEnd + 1;
+ continue;
</ins><span class="cx"> }
</span><ins>+ separator = imageScaleEnd;
</ins><span class="cx"> }
</span><span class="cx"> ImageWithScale image(imageURLStart, imageURLEnd - imageURLStart, imageScaleFactor);
</span><span class="cx"> imageCandidates.append(image);
</span><span class="lines">@@ -399,8 +406,16 @@
</span><span class="cx"> if (imageCandidates[i].scaleFactor() >= deviceScaleFactor)
</span><span class="cx"> return imageCandidates[i];
</span><span class="cx"> }
</span><del>- const ImageWithScale& lastCandidate = imageCandidates.last();
- return lastCandidate;
</del><ins>+
+ // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
+ // then remove entry b
+ size_t winner = imageCandidates.size() - 1;
+ size_t previousCandidate = winner;
+ float winningScaleFactor = imageCandidates.last().scaleFactor();
+ while ((previousCandidate > 0) && (imageCandidates[--previousCandidate].scaleFactor() == winningScaleFactor))
+ winner = previousCandidate;
+
+ return imageCandidates[winner];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>