<!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>[166836] 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/166836">166836</a></dd>
<dt>Author</dt> <dd>krit@webkit.org</dd>
<dt>Date</dt> <dd>2014-04-05 12:57:00 -0700 (Sat, 05 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Canvas stroke and strokeRect with SourceIn, DestinationIn, SourceOut, DestinationAtop and Copy have errors
https://bugs.webkit.org/show_bug.cgi?id=66762

Reviewed by Andreas Kling.

Source/WebCore:

For fill operations we create a new ImageBuffer to ensure that the results are composited
correctly according to the Canvas spec. This patch creates a new transparency layer
for stroking on certain compositing operators to archive the same. This makes WebKit's
behavior interoperable with Firefox and IE as well.

Test: fast/fast/canvas/canvas-composite-stroke-alpha.html

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::strokeInternal):
(WebCore::CanvasRenderingContext2D::strokeRect):

LayoutTests:

330 tests based on canvas-composite-alpha to test correct compositing behavior with
strokeRect() and stroke().

* fast/canvas/canvas-composite-stroke-alpha-expected.txt: Added.
* fast/canvas/canvas-composite-stroke-alpha.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dcpp">trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcanvascanvascompositestrokealphaexpectedtxt">trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcanvascanvascompositestrokealphahtml">trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (166835 => 166836)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-04-05 19:54:18 UTC (rev 166835)
+++ trunk/LayoutTests/ChangeLog        2014-04-05 19:57:00 UTC (rev 166836)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-04-05  Dirk Schulze  &lt;krit@webkit.org&gt;
+
+        Canvas stroke and strokeRect with SourceIn, DestinationIn, SourceOut, DestinationAtop and Copy have errors
+        https://bugs.webkit.org/show_bug.cgi?id=66762
+
+        Reviewed by Andreas Kling.
+
+        330 tests based on canvas-composite-alpha to test correct compositing behavior with
+        strokeRect() and stroke().
+
+        * fast/canvas/canvas-composite-stroke-alpha-expected.txt: Added.
+        * fast/canvas/canvas-composite-stroke-alpha.html: Added.
+
</ins><span class="cx"> 2014-04-05  Jeongeun Kim  &lt;je_julie.kim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         bad values from HTMLImageElement x and y attributes (CSSOM-View)
</span></span></pre></div>
<a id="trunkLayoutTestsfastcanvascanvascompositestrokealphaexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha-expected.txt (0 => 166836)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha-expected.txt        2014-04-05 19:57:00 UTC (rev 166836)
</span><span class="lines">@@ -0,0 +1,363 @@
</span><ins>+This test exercises a bunch of alpha composition checks with stroking. The top-left rectangles are the source images and bottom-right rectangles are the destination images.
+
+Tests for stroke rect
+
+src 255, 0, 0, 255        src 255, 0, 0, 255        src 255, 0, 0, 255        src 0, 255, 0, 0        src 0, 255, 0, 1        src 255, 0, 0, 0        src 255, 0, 0, 127        src 255, 0, 0, 255        src 255, 0, 0, 127        src 127, 0, 0, 255        src 127, 0, 0, 127        src 255, 0, 0, 127        src 255, 127, 0, 32        src 255, 0, 0, 191        src 255, 0, 255, 191
+dst 0, 255, 0, 255        dst 0, 255, 0, 0        dst 0, 255, 0, 1        dst 255, 0, 0, 255        dst 255, 0, 0, 255        dst 0, 255, 0, 255        dst 0, 255, 0, 127        dst 0, 255, 0, 127        dst 0, 255, 0, 255        dst 0, 127, 0, 127        dst 0, 127, 0, 255        dst 255, 0, 0, 63        dst 255, 63, 0, 63        dst 0, 255, 0, 127        dst 0, 255, 255, 127
+source-over                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-in                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-out                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-atop                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-over                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-in                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-out                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-atop                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+lighter                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+copy                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+xor                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+Tests for path and stroke
+
+src 255, 0, 0, 255        src 255, 0, 0, 255        src 255, 0, 0, 255        src 0, 255, 0, 0        src 0, 255, 0, 1        src 255, 0, 0, 0        src 255, 0, 0, 127        src 255, 0, 0, 255        src 255, 0, 0, 127        src 127, 0, 0, 255        src 127, 0, 0, 127        src 255, 0, 0, 127        src 255, 127, 0, 32        src 255, 0, 0, 191        src 255, 0, 255, 191
+dst 0, 255, 0, 255        dst 0, 255, 0, 0        dst 0, 255, 0, 1        dst 255, 0, 0, 255        dst 255, 0, 0, 255        dst 0, 255, 0, 255        dst 0, 255, 0, 127        dst 0, 255, 0, 127        dst 0, 255, 0, 255        dst 0, 127, 0, 127        dst 0, 127, 0, 255        dst 255, 0, 0, 63        dst 255, 63, 0, 63        dst 0, 255, 0, 127        dst 0, 255, 255, 127
+source-over                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-in                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-out                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+source-atop                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-over                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-in                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-out                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+destination-atop                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+lighter                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+copy                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+xor                                                                                                                                                                                                                                                
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcanvascanvascompositestrokealphahtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha.html (0 => 166836)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha.html                                (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-composite-stroke-alpha.html        2014-04-05 19:57:00 UTC (rev 166836)
</span><span class="lines">@@ -0,0 +1,448 @@
</span><ins>+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;A canvas globalCompositeOperation test with alpha blending&lt;/title&gt;
+    &lt;!-- This test was inspired by http://canvex.lazyilluminati.com/misc/compositex.html --&gt;
+    &lt;script type=&quot;application/x-javascript&quot;&gt;
+      if (window.testRunner) {
+          testRunner.dumpAsText();
+          testRunner.waitUntilDone();
+      }
+
+      var compositeTypes = [
+          'source-over','source-in','source-out','source-atop',
+          'destination-over','destination-in','destination-out','destination-atop',
+          'lighter','copy','xor'
+      ];
+      var inputColors = [
+          { source: [255, 0, 0, 255], destination: [0, 255, 0, 255] },
+          { source: [255, 0, 0, 255], destination: [0, 255, 0, 0] },
+          { source: [255, 0, 0, 255], destination: [0, 255, 0, 1] },
+          { source: [0, 255, 0, 0], destination: [255, 0, 0, 255] },
+          { source: [0, 255, 0, 1], destination: [255, 0, 0, 255] },
+          { source: [255, 0, 0, 0], destination: [0, 255, 0, 255] },
+          { source: [255, 0, 0, 127], destination: [0, 255, 0, 127] },
+          { source: [255, 0, 0, 255], destination: [0, 255, 0, 127] },
+          { source: [255, 0, 0, 127], destination: [0, 255, 0, 255] },
+          { source: [127, 0, 0, 255], destination: [0, 127, 0, 127] },
+          { source: [127, 0, 0, 127], destination: [0, 127, 0, 255] },
+          { source: [255, 0, 0, 127], destination: [255, 0, 0, 63] },
+          { source: [255, 127, 0, 32], destination: [255, 63, 0, 63] },
+          { source: [255, 0, 0, 191], destination: [0, 255, 0, 127] },
+          { source: [255, 0, 255, 191], destination: [0, 255, 255, 127] }
+      ];
+      var expectedColors = [
+          [
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 255, 0, 1], composition: [254, 1, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [170, 84, 0, 190], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 127], composition: [127, 128, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [127, 0, 0, 255], composition: [127, 0, 0, 255], destination: [0, 126, 0, 127] },
+              { source: [126, 0, 0, 127], composition: [63, 63, 0, 255], destination: [0, 127, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 158], destination: [255, 0, 0, 63] },
+              { source: [255, 127, 0, 32], composition: [255, 85, 0, 87], destination: [255, 64, 0, 63] },
+              { source: [255, 0, 0, 191], composition: [219, 35, 0, 222], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 255, 191], composition: [219, 35, 255, 222], destination: [0, 255, 255, 127] }
+          ],
+          [
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 64], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [128, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [126, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 127, 0, 8], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 255, 96], destination: [0, 0, 0, 0] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 254], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 255, 0, 1], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 64], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 128], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [127, 0, 0, 255], composition: [127, 0, 0, 128], destination: [0, 0, 0, 0] },
+              { source: [126, 0, 0, 127], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] },
+              { source: [255, 127, 0, 32], composition: [255, 132, 0, 25], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 191], composition: [255, 0, 0, 96], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 255, 191], composition: [255, 0, 255, 96], destination: [0, 0, 0, 0] }
+          ],
+          [
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 1], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [254, 1, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [126, 126, 0, 127], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 127], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [127, 128, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [128, 0, 0, 127], destination: [0, 126, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [63, 63, 0, 255], destination: [0, 127, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 63], destination: [255, 0, 0, 63] },
+              { source: [0, 0, 0, 0], composition: [255, 68, 0, 63], destination: [255, 64, 0, 63] },
+              { source: [0, 0, 0, 0], composition: [190, 62, 0, 127], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [190, 62, 255, 127], destination: [0, 255, 255, 127] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [254, 1, 0, 255], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 255, 0, 1], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [84, 170, 0, 190], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 255], composition: [128, 127, 0, 255], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 127], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [127, 0, 0, 255], composition: [63, 63, 0, 255], destination: [0, 126, 0, 127] },
+              { source: [126, 0, 0, 127], composition: [0, 127, 0, 255], destination: [0, 127, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 158], destination: [255, 0, 0, 63] },
+              { source: [255, 127, 0, 32], composition: [255, 82, 0, 87], destination: [255, 64, 0, 63] },
+              { source: [255, 0, 0, 191], composition: [109, 145, 0, 222], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 255, 191], composition: [109, 145, 255, 222], destination: [0, 255, 255, 127] }
+          ],
+          [
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 1], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 1], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 64], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 126, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 128, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [255, 95, 0, 8], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 96], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 255, 96], destination: [0, 0, 0, 0] }
+          ],
+          [
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 254], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 64], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 128], destination: [0, 255, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 126, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [0, 127, 0, 128], destination: [0, 127, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 32], destination: [255, 0, 0, 63] },
+              { source: [0, 0, 0, 0], composition: [255, 63, 0, 56], destination: [255, 64, 0, 63] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 32], destination: [0, 255, 0, 127] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 255, 32], destination: [0, 255, 255, 127] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [0, 255, 0, 255], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [254, 1, 0, 255], destination: [0,0,0,0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0,0,0,0] },
+              { source: [0, 255, 0, 1], composition: [255, 0, 0, 1], destination: [0,0,0,0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 127], composition: [126, 126, 0, 127], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 255], composition: [128, 127, 0, 255], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 127], composition: [0, 255, 0, 127], destination: [0,0,0,0] },
+              { source: [127, 0, 0, 255], composition: [63, 63, 0, 255], destination: [0,0,0,0] },
+              { source: [126, 0, 0, 127], composition: [0, 126, 0, 127], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0,0,0,0] },
+              { source: [255, 127, 0, 32], composition: [255, 111, 0, 32], destination: [0,0,0,0] },
+              { source: [255, 0, 0, 191], composition: [126, 126, 0, 191], destination: [0,0,0,0] },
+              { source: [255, 0, 255, 191], composition: [126, 126, 255, 191], destination: [0,0,0,0] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [255, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 1, 0, 255], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 255, 0, 1], composition: [255, 1, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [127, 127, 0, 254], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 255], composition: [255, 127, 0, 255], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 127], composition: [127, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [127, 0, 0, 255], composition: [127, 63, 0, 255], destination: [0, 126, 0, 127] },
+              { source: [126, 0, 0, 127], composition: [63, 127, 0, 255], destination: [0, 127, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 190], destination: [255, 0, 0, 63] },
+              { source: [255, 127, 0, 32], composition: [255, 85, 0, 95], destination: [255, 64, 0, 63] },
+              { source: [255, 0, 0, 191], composition: [191, 127, 0, 255], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 255, 191], composition: [191, 127, 255, 255], destination: [0, 255, 255, 127] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [0, 255, 0, 1], composition: [0, 255, 0, 1], destination: [0, 0, 0, 0] },
+              { source: [0, 0, 0, 0], composition: [0, 0, 0, 0], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [127, 0, 0, 255], composition: [127, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [126, 0, 0, 127], composition: [126, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [0, 0, 0, 0] },
+              { source: [255, 127, 0, 32], composition: [255, 127, 0, 32], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 191], composition: [255, 0, 0, 191], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 255, 191], composition: [255, 0, 255, 191], destination: [0, 0, 0, 0] }
+          ],
+          [
+              { source: [255, 0, 0, 255], composition: [0, 0, 0, 0], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 255], destination: [0, 0, 0, 0] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 254], destination: [0, 255, 0, 1] },
+              { source: [0, 0, 0, 0], composition: [255, 0, 0, 255], destination: [255, 0, 0, 255] },
+              { source: [0, 255, 0, 1], composition: [255, 0, 0, 254], destination: [255, 0, 0, 255] },
+              { source: [0, 0, 0, 0], composition: [0, 255, 0, 255], destination: [0, 255, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [126, 126, 0, 127], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 255], composition: [255, 0, 0, 128], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 0, 127], composition: [0, 255, 0, 128], destination: [0, 255, 0, 255] },
+              { source: [127, 0, 0, 255], composition: [127, 0, 0, 128], destination: [0, 126, 0, 127] },
+              { source: [126, 0, 0, 127], composition: [0, 125, 0, 128], destination: [0, 127, 0, 255] },
+              { source: [255, 0, 0, 127], composition: [255, 0, 0, 127], destination: [255, 0, 0, 63] },
+              { source: [255, 127, 0, 32], composition: [255, 83, 0, 79], destination: [255, 64, 0, 63] },
+              { source: [255, 0, 0, 191], composition: [190, 62, 0, 127], destination: [0, 255, 0, 127] },
+              { source: [255, 0, 255, 191], composition: [190, 62, 255, 127], destination: [0, 255, 255, 127] }
+          ]
+      ];
+
+      // Compare two colors with a few margin.
+      function isDifferentColor(actualColor, expectedColor)
+      {
+          var actualAlpha = actualColor[3];
+          var expectedAlpha = expectedColor[3];
+          if (Math.abs(actualColor - expectedColor) &gt; 3) return true;
+          // For the value of RGB, we compare the values the users actually see.
+          if (Math.abs(actualColor[0] * actualAlpha / 256 - expectedColor[0] * expectedAlpha / 256) &gt; 3) return true;
+          if (Math.abs(actualColor[1] * actualAlpha / 256 - expectedColor[1] * expectedAlpha / 256) &gt; 3) return true;
+          if (Math.abs(actualColor[2] * actualAlpha / 256 - expectedColor[2] * expectedAlpha / 256) &gt; 3) return true;
+          return false;
+      }
+
+      function getRGBAString(a)
+      {
+          return &quot;rgba(&quot; + [a[0], a[1], a[2], a[3] / 255.0].join(&quot;,&quot;) + &quot;)&quot;;
+      }
+
+      function drawTable(drawPolicy)
+      {
+          var tableElement = document.createElement(&quot;table&quot;);
+
+          // Create a header for source color.
+          var trElement = document.createElement(&quot;tr&quot;);
+          tableElement.appendChild(trElement);
+          trElement.appendChild(document.createElement(&quot;th&quot;));
+          for (var column = 0; column &lt; inputColors.length; column++) {
+              var inputColor = inputColors[column];
+              var thElement = document.createElement(&quot;th&quot;);
+              thElement.setAttribute(&quot;colspan&quot;, &quot;2&quot;);
+              thElement.textContent = &quot;src &quot; + inputColor.source.join(&quot;, &quot;);
+              trElement.appendChild(thElement);
+          }
+
+          // Create a header for destination color.
+          trElement = document.createElement(&quot;tr&quot;);
+          tableElement.appendChild(trElement);
+          trElement.appendChild(document.createElement(&quot;th&quot;));
+          for (var column = 0; column &lt; inputColors.length; column++) {
+              var inputColor = inputColors[column];
+              var thElement = document.createElement(&quot;th&quot;);
+              thElement.setAttribute(&quot;colspan&quot;, &quot;2&quot;);
+              thElement.textContent = &quot;dst &quot; + inputColor.destination.join(&quot;, &quot;);
+              trElement.appendChild(thElement);
+          }
+
+          var resultsElement = document.getElementById(&quot;results&quot;);
+          var titleElement = document.createElement(&quot;h1&quot;);
+          titleElement.textContent = &quot;Tests for &quot; + drawPolicy.name;
+          resultsElement.appendChild(titleElement);
+          resultsElement.appendChild(tableElement);
+
+          for (var row = 0; row &lt; compositeTypes.length; row++){
+              var type = compositeTypes[row];
+
+              var trCanvasElement = document.createElement(&quot;tr&quot;);
+              var thElement = document.createElement(&quot;th&quot;);
+              thElement.setAttribute(&quot;rowspan&quot;, &quot;2&quot;);
+              thElement.textContent = type;
+              trCanvasElement.appendChild(thElement);
+              var trMessageElement = document.createElement(&quot;tr&quot;);
+              tableElement.appendChild(trCanvasElement);
+              tableElement.appendChild(trMessageElement);
+
+              for (var column = 0; column &lt; inputColors.length; column++) {
+                  var test = type + &quot;-&quot; + column;
+                  var inputColor = inputColors[column];
+                  var expectedColor = expectedColors[row][column];
+
+                  // Create canvas element for actual color.
+                  var actualCanvasElement = document.createElement(&quot;canvas&quot;);
+                  actualCanvasElement.setAttribute(&quot;width&quot;, &quot;25&quot;);
+                  actualCanvasElement.setAttribute(&quot;height&quot;, &quot;25&quot;);
+                  tdElement = document.createElement(&quot;td&quot;);
+                  tdElement.appendChild(actualCanvasElement);
+                  trCanvasElement.appendChild(tdElement);
+
+                  // Create canvas element for expected color.
+                  var expectedCanvasElement = document.createElement(&quot;canvas&quot;);
+                  expectedCanvasElement.setAttribute(&quot;width&quot;, &quot;25&quot;);
+                  expectedCanvasElement.setAttribute(&quot;height&quot;, &quot;25&quot;);
+                  var tdElement = document.createElement(&quot;td&quot;);
+                  tdElement.appendChild(expectedCanvasElement);
+                  trCanvasElement.appendChild(tdElement);
+
+                  // Create div element for pass/fail messages.
+                  var messageElement = document.createElement(&quot;div&quot;);
+                  tdElement = document.createElement(&quot;td&quot;);
+                  tdElement.setAttribute(&quot;colspan&quot;, &quot;2&quot;);
+                  tdElement.appendChild(messageElement);
+                  trMessageElement.appendChild(tdElement);
+
+                  var ctx = expectedCanvasElement.getContext(&quot;2d&quot;);
+                  ctx.lineWidth = 10;
+                  // Draw expected image.
+                  ctx.globalCompositeOperation = &quot;copy&quot;;
+                  ctx.fillStyle = getRGBAString(expectedColor.destination);
+                  ctx.strokeStyle = getRGBAString(expectedColor.destination);
+                  drawPolicy.drawDestination(ctx);
+                  ctx.fillStyle = getRGBAString(expectedColor.source);
+                  ctx.strokeStyle = getRGBAString(expectedColor.source);
+                  drawPolicy.drawSource(ctx);
+                  ctx.fillStyle = getRGBAString(expectedColor.composition);
+                  ctx.strokeStyle = getRGBAString(expectedColor.composition);
+                  drawPolicy.drawComposition(ctx);
+
+                  ctx = actualCanvasElement.getContext(&quot;2d&quot;);
+                  ctx.lineWidth = 10;
+
+                  // Draw destination rectangle.
+                  ctx.globalCompositeOperation = &quot;copy&quot;;
+                  ctx.fillStyle = getRGBAString(inputColor.destination);
+                  ctx.strokeStyle = getRGBAString(inputColor.destination);
+                  drawPolicy.drawDestination(ctx);
+
+                  // Draw source rectangle.
+                  ctx.globalCompositeOperation = type;
+                  ctx.fillStyle = getRGBAString(inputColor.source);
+                  ctx.strokeStyle = getRGBAString(inputColor.source);
+                  drawPolicy.drawSource(ctx);
+
+                  // Let's check if the results are expected or not.
+                  var errorSuffix = &quot;, composite type: &quot; + type + &quot;, source: &quot; + inputColor.source + &quot;, destination: &quot; + inputColor.destination + &quot;&lt;br&gt;&quot;;
+
+                  var results = &quot;&quot;;
+                  // Note that (0, 0) may be affected by anti-alias.
+                  var img = ctx.getImageData(1, 1, 1, 1).data;
+                  var actualColor = [img[0], img[1], img[2], img[3]];
+                  if (isDifferentColor(actualColor, expectedColor.source)) {
+                      results += &quot;Unexpected source! expected: &quot; + expectedColor.source + &quot; actual: &quot; + actualColor + errorSuffix;
+                  }
+                  // Note that (24, 24) may be affected by anti-alias.
+                  img = ctx.getImageData(23, 23, 1, 1).data;
+                  actualColor = [img[0], img[1], img[2], img[3]];
+                  if (isDifferentColor(actualColor, expectedColor.destination)) {
+                      results += &quot;Unexpected destination! expected: &quot; + expectedColor.destination + &quot; actual: &quot; + actualColor + errorSuffix;
+                  }
+                  img = ctx.getImageData(12, 12, 1, 1).data;
+                  actualColor = [img[0], img[1], img[2], img[3]];
+                  if (isDifferentColor(actualColor, expectedColor.composition)) {
+                      results += &quot;Unexpected composition! expected: &quot; + expectedColor.composition + &quot; actual: &quot; + actualColor + errorSuffix;
+                  }
+
+                  if (results == &quot;&quot;) {
+                      messageElement.style.backgroundColor = &quot;green&quot;;
+                      messageElement.innerHTML = results = &quot;PASS&quot;;
+                  } else {
+                      messageElement.style.backgroundColor = &quot;red&quot;;
+                      messageElement.innerHTML = results;
+                  }
+
+                  // Dump colors into text area for debugging purpose.
+                  var debugText = document.getElementById(&quot;debug&quot;);
+                  img = ctx.getImageData(0, 0, 1, 1).data;
+                  debugText.value += img[0] + &quot;,&quot; + img[1] + &quot;,&quot; + img[2] + &quot;,&quot; + img[3] + &quot;\n&quot;;
+                  img = ctx.getImageData(12, 12, 1, 1).data;
+                  debugText.value += img[0] + &quot;,&quot; + img[1] + &quot;,&quot; + img[2] + &quot;,&quot; + img[3] + &quot;\n&quot;;
+                  img = ctx.getImageData(24, 24, 1, 1).data;
+                  debugText.value += img[0] + &quot;,&quot; + img[1] + &quot;,&quot; + img[2] + &quot;,&quot; + img[3] + &quot;\n&quot;;
+              }
+          }
+      }
+
+      var useStrokeRect = {
+          drawSource: function(ctx) {
+              ctx.strokeRect(5, 5, 10, 10);
+          },
+
+          drawDestination: function(ctx) {
+              ctx.fillRect(5, 5, 20, 20);
+          },
+
+          drawComposition: function(ctx) {
+              ctx.fillRect(5, 5, 15, 15);
+          },
+
+          name: &quot;stroke rect&quot;
+      };
+
+      var usePathAndStroke = {
+          drawSource: function(ctx) {
+              ctx.beginPath();
+              ctx.moveTo(5, 5);
+              ctx.lineTo(15, 5);
+              ctx.lineTo(15, 15);
+              ctx.lineTo(5, 15);
+              ctx.closePath();
+              ctx.stroke();
+          },
+
+          drawDestination: function(ctx) {
+              ctx.fillRect(5, 5, 20, 20);
+          },
+
+          drawComposition: function(ctx) {
+              ctx.fillRect(5, 5, 15, 15);
+          },
+
+          name: &quot;path and stroke&quot;
+      };
+
+      function draw()
+      {
+          drawTable(useStrokeRect);
+          drawTable(usePathAndStroke);
+          if (window.testRunner)
+              testRunner.notifyDone();
+      }
+    &lt;/script&gt;
+    &lt;style type=&quot;text/css&quot;&gt;
+      body { margin: 20px; font-family: arial,verdana,helvetica; background: #fff;}
+      h1 { font-size: 140%; font-weight:normal; color: #036; border-bottom: 1px solid #ccc; }
+      canvas { border: 2px solid #000; margin-bottom: 5px; }
+      table { background: #00f; }
+      th { font-size: 70%; padding: 0; }
+      td { font-size: 70%; padding: 0; }
+      pre { float:left; display:block; background: rgb(238,238,238); border: 1px dashed #666; padding: 15px 20px; margin: 0 0 10px 0; }
+    &lt;/style&gt;
+  &lt;/head&gt;
+  &lt;body onload=&quot;draw();&quot;&gt;
+    &lt;p&gt;This test exercises a bunch of alpha composition checks with stroking. The top-left rectangles are the source images and bottom-right rectangles are the destination images.&lt;/p&gt;
+    &lt;div id=&quot;results&quot;&gt;
+    &lt;/div&gt;
+    &lt;textarea id=&quot;debug&quot;&gt;&lt;/textarea&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (166835 => 166836)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-04-05 19:54:18 UTC (rev 166835)
+++ trunk/Source/WebCore/ChangeLog        2014-04-05 19:57:00 UTC (rev 166836)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2014-04-05  Dirk Schulze  &lt;krit@webkit.org&gt;
+
+        Canvas stroke and strokeRect with SourceIn, DestinationIn, SourceOut, DestinationAtop and Copy have errors
+        https://bugs.webkit.org/show_bug.cgi?id=66762
+
+        Reviewed by Andreas Kling.
+
+        For fill operations we create a new ImageBuffer to ensure that the results are composited
+        correctly according to the Canvas spec. This patch creates a new transparency layer
+        for stroking on certain compositing operators to archive the same. This makes WebKit's
+        behavior interoperable with Firefox and IE as well. 
+
+        Test: fast/fast/canvas/canvas-composite-stroke-alpha.html
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::strokeInternal):
+        (WebCore::CanvasRenderingContext2D::strokeRect):
+
</ins><span class="cx"> 2014-04-05  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use preallocated stack reference to store adjacentBacktrackingStart
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (166835 => 166836)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2014-04-05 19:54:18 UTC (rev 166835)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2014-04-05 19:57:00 UTC (rev 166836)
</span><span class="lines">@@ -970,11 +970,21 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (!path.isEmpty()) {
</span><del>-        FloatRect dirtyRect = path.fastBoundingRect();
-        inflateStrokeRect(dirtyRect);
-
-        c-&gt;strokePath(path);
-        didDraw(dirtyRect);
</del><ins>+        if (isFullCanvasCompositeMode(state().m_globalComposite)) {
+            c-&gt;beginTransparencyLayer(1);
+            c-&gt;strokePath(path);
+            c-&gt;endTransparencyLayer();
+            didDrawEntireCanvas();
+        } else if (state().m_globalComposite == CompositeCopy) {
+            clearCanvas();
+            c-&gt;strokePath(path);
+            didDrawEntireCanvas();
+        } else {
+            FloatRect dirtyRect = path.fastBoundingRect();
+            inflateStrokeRect(dirtyRect);
+            c-&gt;strokePath(path);
+            didDraw(dirtyRect);
+        }
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1147,12 +1157,21 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     FloatRect rect(x, y, width, height);
</span><del>-
-    FloatRect boundingRect = rect;
-    boundingRect.inflate(state().m_lineWidth / 2);
-
-    c-&gt;strokeRect(rect, state().m_lineWidth);
-    didDraw(boundingRect);
</del><ins>+    if (isFullCanvasCompositeMode(state().m_globalComposite)) {
+        c-&gt;beginTransparencyLayer(1);
+        c-&gt;strokeRect(rect, state().m_lineWidth);
+        c-&gt;endTransparencyLayer();
+        didDrawEntireCanvas();
+    } else if (state().m_globalComposite == CompositeCopy) {
+        clearCanvas();
+        c-&gt;strokeRect(rect, state().m_lineWidth);
+        didDrawEntireCanvas();
+    } else {
+        FloatRect boundingRect = rect;
+        boundingRect.inflate(state().m_lineWidth / 2);
+        c-&gt;strokeRect(rect, state().m_lineWidth);
+        didDraw(boundingRect);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CanvasRenderingContext2D::setShadow(float width, float height, float blur)
</span></span></pre>
</div>
</div>

</body>
</html>