From 37ea368051fe589ee7af898154f1d979217c6af5 Mon Sep 17 00:00:00 2001
From: MoyuScript <i@moyu.moe>
Date: Sat, 10 Mar 2012 14:28:09 +0000
Subject: [PATCH 1/3] "added TODO"

---
 src/Generate.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/Generate.js b/src/Generate.js
index 026a709..505e612 100644
--- a/src/Generate.js
+++ b/src/Generate.js
@@ -27,6 +27,7 @@ var reGradients = [
 /*
  * TODO: Add IE10 vendor prefix (-ms) support
  * TODO: Add W3C gradient (linear-gradient) support
+ * TODO: Add old Webkit -webkit-gradient(radial, ...) support (new Chrome doesn´t support old syntax?!)
  * TODO: Maybe some RegExp optimizations are possible ;o)
  */
 _html2canvas.Generate.parseGradient = function(css, bounds) {  

From 2bb3cc29d541572532af4e9fff0929ef44653f7b Mon Sep 17 00:00:00 2001
From: MoyuScript <i@moyu.moe>
Date: Sat, 10 Mar 2012 15:31:16 +0000
Subject: [PATCH 2/3] "added ellipse background gradient generation"

---
 src/Generate.js              | 101 +++++++++++++++++++++++------------
 tests/background.html        |  20 +++----
 tests/qunit/unit/generate.js |  12 ++---
 3 files changed, 84 insertions(+), 49 deletions(-)

diff --git a/src/Generate.js b/src/Generate.js
index 505e612..e9841cc 100644
--- a/src/Generate.js
+++ b/src/Generate.js
@@ -206,7 +206,7 @@ _html2canvas.Generate.parseGradient = function(css, bounds) {
             case '-o-radial-gradient':
                 
                 gradient = {
-                    type: 'radial',
+                    type: 'circle',
                     x0: 0,
                     y0: 0,
                     x1: bounds.width,
@@ -256,7 +256,7 @@ _html2canvas.Generate.parseGradient = function(css, bounds) {
                                 );
                             } else { // ellipse
                             
-                                h2clog('No ellipse gradient supported by now, cause canvas can´t draw ellipse :(');
+                                gradient.type = m2[0];
                                 
                                 gradient.rx = Math.max(
                                     gradient.cx,
@@ -279,7 +279,7 @@ _html2canvas.Generate.parseGradient = function(css, bounds) {
                                 );
                             } else { // ellipse
                             
-                                h2clog('No ellipse gradient supported by now, cause canvas can´t draw ellipse :(');
+                                gradient.type = m2[0];
                             
                                 gradient.rx = Math.min(
                                     gradient.cx,
@@ -339,40 +339,75 @@ _html2canvas.Generate.Gradient = function(src, bounds) {
     
     img = new Image();
     
-    if(gradient && gradient.type === 'linear'){
-        grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
+    if(gradient){
+        if(gradient.type === 'linear'){
+            grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
+            
+            for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
+                try {
+                    grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
+                }
+                catch(e) {
+                    h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
+                }
+            }
+            
+            ctx.fillStyle = grad;
+            ctx.fillRect(0, 0, bounds.width, bounds.height);
         
-        for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
-            try {
-                grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
+            img.src = canvas.toDataURL();
+        } else if(gradient.type === 'circle'){
+            
+            grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
+            
+            for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
+                try {
+                    grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
+                }
+                catch(e) {
+                    h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
+                }
             }
-            catch(e) {
-                h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
+            
+            ctx.fillStyle = grad;
+            ctx.fillRect(0, 0, bounds.width, bounds.height);
+        
+            img.src = canvas.toDataURL();
+        } else if(gradient.type === 'ellipse'){
+            
+            // draw circle
+            var canvasRadial = document.createElement('canvas'),
+                ctxRadial = canvasRadial.getContext('2d'),
+                ri = Math.max(gradient.rx, gradient.ry),
+                di = ri * 2, imgRadial;
+                
+            canvasRadial.width = canvasRadial.height = di;
+            
+            grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
+            
+            for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
+                try {
+                    grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
+                }
+                catch(e) {
+                    h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
+                }
             }
+            
+            ctxRadial.fillStyle = grad;
+            ctxRadial.fillRect(0, 0, di, di);
+        
+            imgRadial = new Image();
+            imgRadial.src = canvasRadial.toDataURL();
+            
+            // transform circle to ellipse
+            ctx.fillStyle = gradient.colorStops[i - 1].color;
+            ctx.fillRect(0, 0, canvas.width, canvas.height);
+            
+            ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
+            
+            img.src = canvas.toDataURL();
         }
-        
-        ctx.fillStyle = grad;
-        ctx.fillRect(0, 0, bounds.width, bounds.height);
-    
-        img.src = canvas.toDataURL();
-    } else if(gradient && gradient.type === 'radial'){
-        
-        // TODO: Add support for "ellipsis" drawing
-        grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
-        
-        for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
-            try {
-                grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
-            }
-            catch(e) {
-                h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
-            }
-        }
-        
-        ctx.fillStyle = grad;
-        ctx.fillRect(0, 0, bounds.width, bounds.height);
-    
-        img.src = canvas.toDataURL();
     }
     
     return img;
diff --git a/tests/background.html b/tests/background.html
index 11e7793..4219f2d 100644
--- a/tests/background.html
+++ b/tests/background.html
@@ -170,18 +170,18 @@
                 background: radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
             }
             .radialGradient7 {
-                background: -moz-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -webkit-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -o-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -ms-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
-                background: radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -moz-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -webkit-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -o-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -ms-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
+                background: radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
             }
             .radialGradient8 {
-                background: -moz-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -webkit-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -o-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
-                background: -ms-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
-                background: radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -moz-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -webkit-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -o-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
+                background: -ms-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
+                background: radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
             }
             .radialGradient9 {
                 background: -moz-radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
diff --git a/tests/qunit/unit/generate.js b/tests/qunit/unit/generate.js
index 5201ba8..280f7e5 100644
--- a/tests/qunit/unit/generate.js
+++ b/tests/qunit/unit/generate.js
@@ -104,7 +104,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "ellipse",
             x0: 0,
             y0: 0,
             x1: 50,
@@ -129,7 +129,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "circle",
             x0: 0,
             y0: 0,
             x1: 50,
@@ -154,7 +154,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "ellipse",
             x0: 0,
             y0: 0,
             x1: 50,
@@ -179,7 +179,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "circle",
             x0: 0,
             y0: 0,
             x1: 50,
@@ -204,7 +204,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "ellipse",
             x0: 0,
             y0: 0,
             x1: 50,
@@ -229,7 +229,7 @@ $(function() {
             ]
         },
         {
-            type: "radial",
+            type: "circle",
             x0: 0,
             y0: 0,
             x1: 50,

From d0321c4194afea3290ae4d75296e5f9d4716efc6 Mon Sep 17 00:00:00 2001
From: MoyuScript <i@moyu.moe>
Date: Sun, 11 Mar 2012 17:12:24 +0000
Subject: [PATCH 3/3] "fixed circle gradient generation - image loading bug"

---
 src/Generate.js | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/Generate.js b/src/Generate.js
index e9841cc..3dfa3c1 100644
--- a/src/Generate.js
+++ b/src/Generate.js
@@ -27,7 +27,7 @@ var reGradients = [
 /*
  * TODO: Add IE10 vendor prefix (-ms) support
  * TODO: Add W3C gradient (linear-gradient) support
- * TODO: Add old Webkit -webkit-gradient(radial, ...) support (new Chrome doesn´t support old syntax?!)
+ * TODO: Add old Webkit -webkit-gradient(radial, ...) support
  * TODO: Maybe some RegExp optimizations are possible ;o)
  */
 _html2canvas.Generate.parseGradient = function(css, bounds) {  
@@ -115,7 +115,7 @@ _html2canvas.Generate.parseGradient = function(css, bounds) {
             case '-webkit-gradient':
                 
                 gradient = {
-                    type: m1[2],
+                    type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions
                     x0: 0,
                     y0: 0,
                     x1: 0,
@@ -396,17 +396,20 @@ _html2canvas.Generate.Gradient = function(src, bounds) {
             
             ctxRadial.fillStyle = grad;
             ctxRadial.fillRect(0, 0, di, di);
-        
-            imgRadial = new Image();
-            imgRadial.src = canvasRadial.toDataURL();
             
-            // transform circle to ellipse
             ctx.fillStyle = gradient.colorStops[i - 1].color;
             ctx.fillRect(0, 0, canvas.width, canvas.height);
             
-            ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
-            
-            img.src = canvas.toDataURL();
+            imgRadial = new Image();
+            imgRadial.onload = function() { // wait until the image is filled
+                
+                // transform circle to ellipse
+                ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
+                
+                img.src = canvas.toDataURL();
+                
+            }
+            imgRadial.src = canvasRadial.toDataURL();
         }
     }