<!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>[160121] 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/160121">160121</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2013-12-04 13:35:38 -0800 (Wed, 04 Dec 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>Allow ImageBuffer to use an IOSurface that is larger than necessary
https://bugs.webkit.org/show_bug.cgi?id=124626
Patch by Myles C. Maxfield <mmaxfield@apple.com> on 2013-12-04
Reviewed by Simon Fraser.
Source/WebCore:
Because creating ImageBuffer's backing store can be so expensive, it
would be beneficial to have a pool of pre-created backing stores
available. However, this means that ImageBuffer might have to use a
backing store that is larger than the exact dimensions that it needs.
This patch adds a field, m_backingStoreSize, to CG's ImageBufferData
class, and uses this new field when performing ImageBuffer operations
to allow for larger-than-necessary backing stores. Content is always
drawn in the top left corner of the backing store.
No new tests are necessary because there is no behavior change.
* platform/graphics/ImageBuffer.h:
(WebCore::ImageBuffer::baseTransform): The base transform has to put
content at the top left corner instead of bottom left
* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::createCroppedImageIfNecessary): Convenience function to figure out
the dimensions of the backing texture in user space
(WebCore::ImageBuffer::ImageBuffer): Set up new m_backingStoreSize member
(WebCore::maybeCropToBounds): Some ImageBuffer API functions require
outputting an image with logical size. This function performs the cropping
(WebCore::ImageBuffer::copyImage): Updated for larger-than-necessary
backing stores
(WebCore::ImageBuffer::copyNativeImage): Ditto
(WebCore::ImageBuffer::draw): Ditto
(WebCore::ImageBuffer::clip): Ditto
(WebCore::ImageBuffer::putByteArray): Ditto
(WebCore::ImageBuffer::toDataURL): Ditto
* platform/graphics/cg/ImageBufferDataCG.cpp:
(WebCore::ImageBufferData::getData): Ditto
(WebCore::ImageBufferData::putData): Ditto
* platform/graphics/cg/ImageBufferDataCG.h: New m_backingStoreSize field
LayoutTests:
Update tests to be more robust with respect to accelerated vs
non-accelerated ImageBuffers.
* fast/canvas/script-tests/canvas-fillPath-shadow.js: Don't sample a canvas at exactly
the corner of a drawn shape (because the corner might be antialiased). Instead, sample
a single pixel inside the shape
* fast/canvas/script-tests/canvas-scale-shadowBlur.js: Don't sample a canvas at exactly
the edge of the blur radius. Instead, sample a single pixel past the blur radius.
* fast/canvas/script-tests/canvas-scale-strokePath-shadow.js:
(shouldBeAround): Allow this test to be less strict when sampling inside a blurred region
* platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt: Matching update w/r/t
canvas-scale-shadowBlur.js</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcanvasscripttestscanvasfillPathshadowjs">trunk/LayoutTests/fast/canvas/script-tests/canvas-fillPath-shadow.js</a></li>
<li><a href="#trunkLayoutTestsfastcanvasscripttestscanvasscaleshadowBlurjs">trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js</a></li>
<li><a href="#trunkLayoutTestsfastcanvasscripttestscanvasscalestrokePathshadowjs">trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastcanvascanvasscaleshadowBlurexpectedtxt">trunk/LayoutTests/platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageBufferh">trunk/Source/WebCore/platform/graphics/ImageBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageBufferCGcpp">trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageBufferDataCGcpp">trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageBufferDataCGh">trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/LayoutTests/ChangeLog        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2013-12-04 Myles C. Maxfield <mmaxfield@apple.com>
+
+ Allow ImageBuffer to use an IOSurface that is larger than necessary
+ https://bugs.webkit.org/show_bug.cgi?id=124626
+
+ Reviewed by Simon Fraser.
+
+ Update tests to be more robust with respect to accelerated vs
+ non-accelerated ImageBuffers.
+
+ * fast/canvas/script-tests/canvas-fillPath-shadow.js: Don't sample a canvas at exactly
+ the corner of a drawn shape (because the corner might be antialiased). Instead, sample
+ a single pixel inside the shape
+ * fast/canvas/script-tests/canvas-scale-shadowBlur.js: Don't sample a canvas at exactly
+ the edge of the blur radius. Instead, sample a single pixel past the blur radius.
+ * fast/canvas/script-tests/canvas-scale-strokePath-shadow.js:
+ (shouldBeAround): Allow this test to be less strict when sampling inside a blurred region
+ * platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt: Matching update w/r/t
+ canvas-scale-shadowBlur.js
+
</ins><span class="cx"> 2013-12-03 Dean Jackson <dino@apple.com>
</span><span class="cx">
</span><span class="cx"> [WebGL] Support for texImage2D/texSubImage2D of type HALF_FLOAT_OES
</span></span></pre></div>
<a id="trunkLayoutTestsfastcanvasscripttestscanvasfillPathshadowjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/canvas/script-tests/canvas-fillPath-shadow.js (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/script-tests/canvas-fillPath-shadow.js        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/LayoutTests/fast/canvas/script-tests/canvas-fillPath-shadow.js        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -70,7 +70,7 @@
</span><span class="cx"> shouldBe('data[1]', '20');
</span><span class="cx"> shouldBe('data[2]', '0');
</span><span class="cx">
</span><del>-imageData = ctx.getImageData(380, 30, 1, 1);
</del><ins>+imageData = ctx.getImageData(381, 31, 1, 1);
</ins><span class="cx"> data = imageData.data;
</span><span class="cx"> shouldBe('data[0]', '255');
</span><span class="cx"> shouldBe('data[1]', '20');
</span></span></pre></div>
<a id="trunkLayoutTestsfastcanvasscripttestscanvasscaleshadowBlurjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="cx"> shouldBeAround('d[3]', '255');
</span><span class="cx">
</span><del>-d = ctx.getImageData(250, 175, 1, 1).data;
</del><ins>+d = ctx.getImageData(250, 174, 1, 1).data;
</ins><span class="cx"> shouldBe('d[0]', '0');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="cx"> shouldBe('d[3]', '0');
</span><span class="cx">
</span><del>-d = ctx.getImageData(175, 250, 1, 1).data;
</del><ins>+d = ctx.getImageData(174, 250, 1, 1).data;
</ins><span class="cx"> shouldBe('d[0]', '0');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="cx"> shouldBeAround('d[3]', '255');
</span><span class="cx">
</span><del>-d = ctx.getImageData(450, 175, 1, 1).data;
</del><ins>+d = ctx.getImageData(450, 174, 1, 1).data;
</ins><span class="cx"> shouldBe('d[0]', '0');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> shouldBe('d[2]', '0');
</span><span class="cx"> shouldBe('d[3]', '0');
</span><span class="cx">
</span><del>-d = ctx.getImageData(375, 250, 1, 1).data;
</del><ins>+d = ctx.getImageData(374, 250, 1, 1).data;
</ins><span class="cx"> shouldBe('d[0]', '0');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span></span></pre></div>
<a id="trunkLayoutTestsfastcanvasscripttestscanvasscalestrokePathshadowjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/LayoutTests/fast/canvas/script-tests/canvas-scale-strokePath-shadow.js        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -10,7 +10,7 @@
</span><span class="cx"> document.getElementById("console").appendChild(paragraph);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function shouldBeAround(a, b)
</del><ins>+function shouldBeAround(a, b, argdelta)
</ins><span class="cx"> {
</span><span class="cx"> var evalA;
</span><span class="cx"> try {
</span><span class="lines">@@ -19,7 +19,11 @@
</span><span class="cx"> evalA = e;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (Math.abs(evalA - b) < 20)
</del><ins>+ var delta = 20;
+ if (typeof argdelta != "undefined")
+ delta = argdelta;
+
+ if (Math.abs(evalA - b) < delta)
</ins><span class="cx"> print("PASS " + a + " is around " + b , "green")
</span><span class="cx"> else
</span><span class="cx"> print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red");
</span><span class="lines">@@ -119,7 +123,7 @@
</span><span class="cx"> shouldBe('d[0]', '255');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span><del>-shouldBeAround('d[3]', '200');
</del><ins>+shouldBeAround('d[3]', '200', 25);
</ins><span class="cx">
</span><span class="cx"> d = ctx.getImageData(508, 250, 1, 1).data;
</span><span class="cx"> shouldBe('d[0]', '255');
</span><span class="lines">@@ -131,7 +135,7 @@
</span><span class="cx"> shouldBe('d[0]', '255');
</span><span class="cx"> shouldBe('d[1]', '0');
</span><span class="cx"> shouldBe('d[2]', '0');
</span><del>-shouldBeAround('d[3]', '199');
</del><ins>+shouldBeAround('d[3]', '199', 25);
</ins><span class="cx">
</span><span class="cx"> // Verify blurry alpha shadow.
</span><span class="cx"> d = ctx.getImageData(505, 450, 1, 1).data;
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastcanvascanvasscaleshadowBlurexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/LayoutTests/platform/mac/fast/canvas/canvas-scale-shadowBlur-expected.txt        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -10,7 +10,7 @@
</span><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><del>-FAIL d[3] should be 0. Was 6.
</del><ins>+FAIL d[3] should be 0. Was 5.
</ins><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><del>-FAIL d[3] should be 0. Was 6.
</del><ins>+FAIL d[3] should be 0. Was 5.
</ins><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><del>-FAIL d[3] should be 0. Was 6.
</del><ins>+FAIL d[3] should be 0. Was 5.
</ins><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span><del>-FAIL d[3] should be 0. Was 6.
</del><ins>+FAIL d[3] should be 0. Was 5.
</ins><span class="cx"> FAIL d[0] should be 0. Was 255.
</span><span class="cx"> PASS d[1] is 0
</span><span class="cx"> PASS d[2] is 0
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/Source/WebCore/ChangeLog        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2013-12-04 Myles C. Maxfield <mmaxfield@apple.com>
+
+ Allow ImageBuffer to use an IOSurface that is larger than necessary
+ https://bugs.webkit.org/show_bug.cgi?id=124626
+
+ Reviewed by Simon Fraser.
+
+ Because creating ImageBuffer's backing store can be so expensive, it
+ would be beneficial to have a pool of pre-created backing stores
+ available. However, this means that ImageBuffer might have to use a
+ backing store that is larger than the exact dimensions that it needs.
+ This patch adds a field, m_backingStoreSize, to CG's ImageBufferData
+ class, and uses this new field when performing ImageBuffer operations
+ to allow for larger-than-necessary backing stores. Content is always
+ drawn in the top left corner of the backing store.
+
+ No new tests are necessary because there is no behavior change.
+
+ * platform/graphics/ImageBuffer.h:
+ (WebCore::ImageBuffer::baseTransform): The base transform has to put
+ content at the top left corner instead of bottom left
+ * platform/graphics/cg/ImageBufferCG.cpp:
+ (WebCore::createCroppedImageIfNecessary): Convenience function to figure out
+ the dimensions of the backing texture in user space
+ (WebCore::ImageBuffer::ImageBuffer): Set up new m_backingStoreSize member
+ (WebCore::maybeCropToBounds): Some ImageBuffer API functions require
+ outputting an image with logical size. This function performs the cropping
+ (WebCore::ImageBuffer::copyImage): Updated for larger-than-necessary
+ backing stores
+ (WebCore::ImageBuffer::copyNativeImage): Ditto
+ (WebCore::ImageBuffer::draw): Ditto
+ (WebCore::ImageBuffer::clip): Ditto
+ (WebCore::ImageBuffer::putByteArray): Ditto
+ (WebCore::ImageBuffer::toDataURL): Ditto
+ * platform/graphics/cg/ImageBufferDataCG.cpp:
+ (WebCore::ImageBufferData::getData): Ditto
+ (WebCore::ImageBufferData::putData): Ditto
+ * platform/graphics/cg/ImageBufferDataCG.h: New m_backingStoreSize field
+
</ins><span class="cx"> 2013-12-03 Dean Jackson <dino@apple.com>
</span><span class="cx">
</span><span class="cx"> [WebGL] Support for texImage2D of type HALF_FLOAT_OES
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -117,7 +117,7 @@
</span><span class="cx"> void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
</span><span class="cx"> void platformTransformColorSpace(const Vector<int>&);
</span><span class="cx"> #else
</span><del>- AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, internalSize().height()); }
</del><ins>+ AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_data.m_backingStoreSize.height()); }
</ins><span class="cx"> #endif
</span><span class="cx"> #if USE(ACCELERATED_COMPOSITING)
</span><span class="cx"> PlatformLayer* platformLayer() const;
</span><span class="lines">@@ -135,6 +135,8 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> #if USE(CG)
</span><ins>+ // The returned image might be larger than the internalSize(). If you want the smaller
+ // image, crop the result.
</ins><span class="cx"> RetainPtr<CGImageRef> copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
</span><span class="cx"> void flushContext() const;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageBufferCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -98,6 +98,13 @@
</span><span class="cx"> fastFree(const_cast<void*>(data));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static FloatSize scaleSizeToUserSpace(const FloatSize& logicalSize, const IntSize& backingStoreSize, const IntSize& internalSize)
+{
+ float xMagnification = static_cast<float>(backingStoreSize.width()) / internalSize.width();
+ float yMagnification = static_cast<float>(backingStoreSize.height()) / internalSize.height();
+ return FloatSize(logicalSize.width() * xMagnification, logicalSize.height() * yMagnification);
+}
+
</ins><span class="cx"> ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success)
</span><span class="cx"> : m_data(size) // NOTE: The input here isn't important as ImageBufferDataCG's constructor just ignores it.
</span><span class="cx"> , m_logicalSize(size)
</span><span class="lines">@@ -111,6 +118,7 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> m_size = IntSize(scaledWidth, scaledHeight);
</span><ins>+ m_data.m_backingStoreSize = m_size;
</ins><span class="cx">
</span><span class="cx"> success = false; // Make early return mean failure.
</span><span class="cx"> bool accelerateRendering = renderingMode == Accelerated;
</span><span class="lines">@@ -121,8 +129,8 @@
</span><span class="cx"> Checked<int, RecordOverflow> height = m_size.height();
</span><span class="cx">
</span><span class="cx"> // Prevent integer overflows
</span><del>- m_data.m_bytesPerRow = 4 * width;
- Checked<size_t, RecordOverflow> numBytes = height * m_data.m_bytesPerRow;
</del><ins>+ m_data.m_bytesPerRow = 4 * Checked<unsigned, RecordOverflow>(m_data.m_backingStoreSize.width());
+ Checked<size_t, RecordOverflow> numBytes = Checked<unsigned, RecordOverflow>(m_data.m_backingStoreSize.height()) * m_data.m_bytesPerRow;
</ins><span class="cx"> if (numBytes.hasOverflowed())
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="lines">@@ -148,20 +156,21 @@
</span><span class="cx"> RetainPtr<CGContextRef> cgContext;
</span><span class="cx"> if (accelerateRendering) {
</span><span class="cx"> #if USE(IOSURFACE_CANVAS_BACKING_STORE)
</span><del>- m_data.m_surface = createIOSurface(m_size);
- cgContext = adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), width.unsafeGet(), height.unsafeGet(), m_data.m_colorSpace));
</del><ins>+ m_data.m_surface = createIOSurface(m_data.m_backingStoreSize);
+ FloatSize userBounds = scaleSizeToUserSpace(FloatSize(width.unsafeGet(), height.unsafeGet()), m_data.m_backingStoreSize, m_size);
+ cgContext = adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), userBounds.width(), userBounds.height(), m_data.m_colorSpace));
</ins><span class="cx"> #endif
</span><span class="cx"> if (!cgContext)
</span><span class="cx"> accelerateRendering = false; // If allocation fails, fall back to non-accelerated path.
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (!accelerateRendering) {
</span><del>- if (!tryFastCalloc(height.unsafeGet(), m_data.m_bytesPerRow.unsafeGet()).getValue(m_data.m_data))
</del><ins>+ if (!tryFastCalloc(m_data.m_backingStoreSize.height(), m_data.m_bytesPerRow.unsafeGet()).getValue(m_data.m_data))
</ins><span class="cx"> return;
</span><span class="cx"> ASSERT(!(reinterpret_cast<intptr_t>(m_data.m_data) & 3));
</span><span class="cx">
</span><span class="cx"> m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast;
</span><del>- cgContext = adoptCF(CGBitmapContextCreate(m_data.m_data, width.unsafeGet(), height.unsafeGet(), 8, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo));
</del><ins>+ cgContext = adoptCF(CGBitmapContextCreate(m_data.m_data, m_data.m_backingStoreSize.width(), m_data.m_backingStoreSize.height(), 8, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo));
</ins><span class="cx"> // Create a live image that wraps the data.
</span><span class="cx"> m_data.m_dataProvider = adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, numBytes.unsafeGet(), releaseImageData));
</span><span class="cx"> }
</span><span class="lines">@@ -170,9 +179,9 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> m_context = adoptPtr(new GraphicsContext(cgContext.get()));
</span><ins>+ m_context->scale(FloatSize(1, -1));
+ m_context->translate(0, -m_data.m_backingStoreSize.height());
</ins><span class="cx"> m_context->applyDeviceScaleFactor(m_resolutionScale);
</span><del>- m_context->scale(FloatSize(1, -1));
- m_context->translate(0, -size.height());
</del><span class="cx"> m_context->setIsAcceleratedContext(accelerateRendering);
</span><span class="cx"> success = true;
</span><span class="cx"> }
</span><span class="lines">@@ -191,6 +200,15 @@
</span><span class="cx"> CGContextFlush(m_context->platformContext());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static RetainPtr<CGImageRef> createCroppedImageIfNecessary(CGImageRef image, const IntSize& bounds)
+{
+ if (image && (CGImageGetWidth(image) != static_cast<size_t>(bounds.width())
+ || CGImageGetHeight(image) != static_cast<size_t>(bounds.height()))) {
+ return adoptCF(CGImageCreateWithImageInRect(image, CGRectMake(0, static_cast<int>(CGImageGetHeight(image)) - bounds.height(), bounds.width(), bounds.height())));
+ }
+ return image;
+}
+
</ins><span class="cx"> PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior scaleBehavior) const
</span><span class="cx"> {
</span><span class="cx"> RetainPtr<CGImageRef> image;
</span><span class="lines">@@ -200,13 +218,18 @@
</span><span class="cx"> image = copyNativeImage(DontCopyBackingStore);
</span><span class="cx"> RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast));
</span><span class="cx"> CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
</span><del>- CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get());
</del><ins>+ CGContextDrawImage(context.get(), CGRectMake(0, 0, m_data.m_backingStoreSize.width(), m_data.m_backingStoreSize.height()), image.get());
</ins><span class="cx"> image = adoptCF(CGBitmapContextCreateImage(context.get()));
</span><span class="cx"> }
</span><ins>+
+ image = createCroppedImageIfNecessary(image.get(), internalSize());
</ins><span class="cx">
</span><span class="cx"> if (!image)
</span><span class="cx"> return 0;
</span><span class="cx">
</span><ins>+ ASSERT(CGImageGetWidth(image.get()) == static_cast<size_t>(m_logicalSize.width()));
+ ASSERT(CGImageGetHeight(image.get()) == static_cast<size_t>(m_logicalSize.height()));
+
</ins><span class="cx"> RefPtr<BitmapImage> bitmapImage = BitmapImage::create(image.get());
</span><span class="cx"> bitmapImage->setSpaceSize(spaceSize());
</span><span class="cx">
</span><span class="lines">@@ -224,7 +247,7 @@
</span><span class="cx"> if (!m_context->isAcceleratedContext()) {
</span><span class="cx"> switch (copyBehavior) {
</span><span class="cx"> case DontCopyBackingStore:
</span><del>- image = CGImageCreate(internalSize().width(), internalSize().height(), 8, 32, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo, m_data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
</del><ins>+ image = CGImageCreate(m_data.m_backingStoreSize.width(), m_data.m_backingStoreSize.height(), 8, 32, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo, m_data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
</ins><span class="cx"> break;
</span><span class="cx"> case CopyBackingStore:
</span><span class="cx"> image = CGBitmapContextCreateImage(context()->platformContext());
</span><span class="lines">@@ -279,12 +302,15 @@
</span><span class="cx">
</span><span class="cx"> void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) const
</span><span class="cx"> {
</span><ins>+ FloatSize backingStoreSizeInUserSpace = scaleSizeToUserSpace(rect.size(), m_data.m_backingStoreSize, internalSize());
+
</ins><span class="cx"> CGContextRef platformContextToClip = contextToClip->platformContext();
</span><span class="cx"> // FIXME: This image needs to be grayscale to be used as an alpha mask here.
</span><span class="cx"> RetainPtr<CGImageRef> image = copyNativeImage(DontCopyBackingStore);
</span><del>- CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + rect.height());
</del><ins>+ CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + backingStoreSizeInUserSpace.height());
</ins><span class="cx"> CGContextScaleCTM(platformContextToClip, 1, -1);
</span><del>- CGContextClipToMask(platformContextToClip, FloatRect(FloatPoint(), rect.size()), image.get());
</del><ins>+ CGContextClipToRect(platformContextToClip, FloatRect(FloatPoint(0, backingStoreSizeInUserSpace.height() - rect.height()), rect.size()));
+ CGContextClipToMask(platformContextToClip, FloatRect(FloatPoint(), backingStoreSizeInUserSpace), image.get());
</ins><span class="cx"> CGContextScaleCTM(platformContextToClip, 1, -1);
</span><span class="cx"> CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height());
</span><span class="cx"> }
</span><span class="lines">@@ -335,10 +361,14 @@
</span><span class="cx"> CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0);
</span><span class="cx">
</span><span class="cx"> // Draw the image in CG coordinate space
</span><del>- IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), (coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize()).height() - (destPoint.y() + sourceRect.y()) - sourceRect.height());
</del><ins>+ FloatSize scaledDestSize = scaleSizeToUserSpace(coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize(), m_data.m_backingStoreSize, internalSize());
+ IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), scaledDestSize.height() - (destPoint.y() + sourceRect.y()) - sourceRect.height());
</ins><span class="cx"> IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize);
</span><ins>+ CGContextClipToRect(destContext, destRectInCGCoords);
+
</ins><span class="cx"> RetainPtr<CGImageRef> sourceCopyImage = sourceCopy->copyNativeImage();
</span><del>- CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get());
</del><ins>+ FloatRect backingStoreInDestRect = FloatRect(FloatPoint(destPointInCGCoords.x(), destPointInCGCoords.y() + sourceCopySize.height() - (int)CGImageGetHeight(sourceCopyImage.get())), FloatSize(CGImageGetWidth(sourceCopyImage.get()), CGImageGetHeight(sourceCopyImage.get())));
+ CGContextDrawImage(destContext, backingStoreInDestRect, sourceCopyImage.get());
</ins><span class="cx"> CGContextRestoreGState(destContext);
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="lines">@@ -442,13 +472,16 @@
</span><span class="cx"> image = adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(),
</span><span class="cx"> deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast,
</span><span class="cx"> dataProvider.get(), 0, false, kCGRenderingIntentDefault));
</span><del>- } else if (m_resolutionScale == 1)
</del><ins>+ } else if (m_resolutionScale == 1) {
</ins><span class="cx"> image = copyNativeImage(CopyBackingStore);
</span><del>- else {
</del><ins>+ image = createCroppedImageIfNecessary(image.get(), internalSize());
+ } else {
</ins><span class="cx"> image = copyNativeImage(DontCopyBackingStore);
</span><span class="cx"> RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast));
</span><span class="cx"> CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
</span><del>- CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get());
</del><ins>+ CGContextClipToRect(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()));
+ FloatSize imageRectInUserBounds = scaleSizeToUserSpace(logicalSize(), m_data.m_backingStoreSize, internalSize());
+ CGContextDrawImage(context.get(), CGRectMake(0, 0, imageRectInUserBounds.width(), imageRectInUserBounds.height()), image.get());
</ins><span class="cx"> image = adoptCF(CGBitmapContextCreateImage(context.get()));
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageBufferDataCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -158,7 +158,7 @@
</span><span class="cx"> unsigned char* srcRows;
</span><span class="cx">
</span><span class="cx"> if (!accelerateRendering) {
</span><del>- srcBytesPerRow = 4 * size.width();
</del><ins>+ srcBytesPerRow = m_bytesPerRow.unsafeGet();
</ins><span class="cx"> srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4;
</span><span class="cx">
</span><span class="cx"> #if USE(ACCELERATE)
</span><span class="lines">@@ -339,6 +339,10 @@
</span><span class="cx">
</span><span class="cx"> void ImageBufferData::putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale)
</span><span class="cx"> {
</span><ins>+#if ASSERT_DISABLED
+ UNUSED_PARAM(size);
+#endif
+
</ins><span class="cx"> ASSERT(sourceRect.width() > 0);
</span><span class="cx"> ASSERT(sourceRect.height() > 0);
</span><span class="cx">
</span><span class="lines">@@ -381,7 +385,7 @@
</span><span class="cx"> unsigned char* destRows;
</span><span class="cx">
</span><span class="cx"> if (!accelerateRendering) {
</span><del>- destBytesPerRow = 4 * size.width();
</del><ins>+ destBytesPerRow = m_bytesPerRow.unsafeGet();
</ins><span class="cx"> destRows = reinterpret_cast<unsigned char*>(m_data) + (desty * destBytesPerRow + destx * 4).unsafeGet();
</span><span class="cx">
</span><span class="cx"> #if USE(ACCELERATE)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageBufferDataCGh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h (160120 => 160121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h        2013-12-04 21:29:45 UTC (rev 160120)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h        2013-12-04 21:35:38 UTC (rev 160121)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> Checked<unsigned, RecordOverflow> m_bytesPerRow;
</span><span class="cx"> CGColorSpaceRef m_colorSpace;
</span><span class="cx"> RetainPtr<IOSurfaceRef> m_surface;
</span><ins>+ IntSize m_backingStoreSize;
</ins><span class="cx">
</span><span class="cx"> PassRefPtr<Uint8ClampedArray> getData(const IntRect&, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale) const;
</span><span class="cx"> void putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize&, bool accelerateRendering, bool unmultiplied, float resolutionScale);
</span></span></pre>
</div>
</div>
</body>
</html>