From 6637ba1bd74d92da94283e6d9496ba5703bc13b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fiedler?= Date: Mon, 5 Mar 2012 19:20:44 +0000 Subject: [PATCH] "-webkit-linear-gradient color stops and rendering" --- src/Generate.js | 222 ++++++++++++++++++++++-------------------- tests/background.html | 34 +++++++ 2 files changed, 153 insertions(+), 103 deletions(-) diff --git a/src/Generate.js b/src/Generate.js index 932fca2..f55812b 100644 --- a/src/Generate.js +++ b/src/Generate.js @@ -6,124 +6,138 @@ Released under MIT License */ +(function(){ + _html2canvas.Generate = {}; +// -webkit-linear-gradient(left top, rgb(255, 0, 0), rgb(0, 0, 255), rgb(186, 218, 85), rgba(0, 0, 255, 0.496094)) +// -webkit-linear-gradient(left, rgb(206, 219, 233) 0%, rgb(170, 197, 222) 17%, rgb(97, 153, 199) 50%, rgb(58, 132, 195) 51%, rgb(65, 154, 214) 59%, rgb(75, 184, 240) 71%, rgb(58, 139, 194) 84%, rgb(38, 85, 139) 100%) +// -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232))) +// -moz-linear-gradient(100% 0%, rgb(255, 0, 0), rgb(0, 0, 255), rgb(186, 218, 85), rgba(0, 0, 255, 0.5)) + +var reGradients = [ + /^(-webkit-linear-gradient)\(([a-z\s]+)((?:,\s(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+)\)$/, + /^(-webkit-gradient)\((linear|radial),\s((?:[a-z]+|\d{1,3}%?)\s(?:[a-z]+|\d{1,3}%?)),\s((?:[a-z]+|\d{1,3}%?)\s(?:[a-z]+|\d{1,3}%?))((?:,\s(?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+)\)$/ +]; + +// ["-webkit-linear-gradient(left top, rgb(255, 0, 0), rgb(0, 0, 255), rgb(186, 218, 85), rgba(0, 0, 255, 0.496094))", "-webkit-linear-gradient", "left top", ", rgb(255, 0, 0), rgb(0, 0, 255), rgb(186, 218, 85), rgba(0, 0, 255, 0.496094)"] +// ["-webkit-linear-gradient(left, rgb(206, 219, 233) 0%, rgb(170, 197, 222) 17%, rgb(97, 153, 199) 50%, rgb(58, 132, 195) 51%, rgb(65, 154, 214) 59%, rgb(75, 184, 240) 71%, rgb(58, 139, 194) 84%, rgb(38, 85, 139) 100%)", "-webkit-linear-gradient", "left", ", rgb(206, 219, 233) 0%, rgb(170, 197, 222) 17%, rgb(97, 153, 199) 50%, rgb(58, 132, 195) 51%, rgb(65, 154, 214) 59%, rgb(75, 184, 240) 71%, rgb(58, 139, 194) 84%, rgb(38, 85, 139) 100%"] +// ["-webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232)))", "-webkit-gradient", "linear", "0% 0", "0% 100%", ", from(rgb(252, 252, 252)), to(rgb(232, 232, 232))"] + +_html2canvas.Generate.getColorStopsFromGradient = function(css, bounds) { + console.log(css); + + var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3; + + for(i = 0; i < len; i+=1){ + m1 = css.match(reGradients[i]); + if(m1) break; + } + + console.log(m1); + if(m1) { + switch(m1[1]) { + case '-webkit-linear-gradient': + + gradient = { + type: 'linear', + x0: 0, + y0: 0, + x1: 0, + y1: 0, + colorStops: [] + }; + + // get coordinates + m2 = m1[2].match(/\w+/g); + if(m2){ + m2Len = m2.length; + for(i = 0; i < m2Len; i+=1){ + switch(m2[i]) { + case 'top': + gradient.y1 = bounds.height; + break; + + case 'right': + gradient.x0 = bounds.width; + break; + + case 'bottom': + gradient.y0 = bounds.height; + break; + + case 'left': + gradient.x1 = bounds.width; + break; + } + } + } + + // get colors and stops + m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g); + if(m2){ + m2Len = m2.length; + step = 1 / Math.max(m2Len - 1, 1); + for(i = 0; i < m2Len; i+=1){ + m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/); + if(m3[2]){ + stop = parseFloat(m3[2]); + if(m3[3]){ //percentage + stop /= 100; + } + } else { + stop = i * step; + } + gradient.colorStops.push({ + color: m3[1], + stop: stop + }); + } + console.log(gradient); + } + break; + + case '-webkit-gradient': + // stop = m2[1] == 'from' ? 0.0 : 1.0; + break; + } + } + + return gradient; +}; _html2canvas.Generate.Gradient = function(src, bounds) { var canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'), - tmp, - p0 = 0, - p1 = 0, - p2 = 0, - p3 = 0, - steps = [], - position, - i, - len, - lingrad, - increment, - p, - img; + gradient, lingrad, i, len, img; canvas.width = bounds.width; canvas.height = bounds.height; + gradient = _html2canvas.Generate.getColorStopsFromGradient(src, bounds); - function getColors(input) { - var j = -1, - color = '', - chr; - while( j++ < input.length ) { - chr = input.charAt( j ); - if (chr === ')') { - color += chr; - steps.push( color ); - color = ''; - j = input.indexOf(",", j) + 1; - if (j === 0) { - break; - } - // while (j++ < input.length && input.charAt( j ) !== ',') {} - } else { - color += chr; - } - } - } - - if ( (tmp = src.match(/-webkit-linear-gradient\((.*)\)/)) !== null ) { - - position = tmp[1].split( ",", 1 )[0]; - getColors( tmp[1].substr( position.length + 2 ) ); - position = position.split(' '); - - for ( p = 0, len = position.length; p < len; p+=1 ) { - - switch( position[ p ] ) { - case 'top': - p3 = bounds.height; - break; - - case 'right': - p0 = bounds.width; - break; - - case 'bottom': - p1 = bounds.height; - break; - - case 'left': - p2 = bounds.width; - break; - } - - } - - } else if ( (tmp = src.match(/-webkit-gradient\(linear, (\d+)[%]{0,1} (\d+)[%]{0,1}, (\d+)[%]{0,1} (\d+)[%]{0,1}, from\((.*)\), to\((.*)\)\)/)) !== null ) { - - p0 = (tmp[1] * bounds.width) / 100; - p1 = (tmp[2] * bounds.height) / 100; - p2 = (tmp[3] * bounds.width) / 100; - p3 = (tmp[4] * bounds.height) / 100; - - steps.push(tmp[5]); - steps.push(tmp[6]); - - } else if ( (tmp = src.match(/-moz-linear-gradient\((\d+)[%]{0,1} (\d+)[%]{0,1}, (.*)\)/)) !== null ) { - - p0 = (tmp[1] * bounds.width) / 100; - p1 = (tmp[2] * bounds.width) / 100; - p2 = bounds.width - p0; - p3 = bounds.height - p1; - getColors( tmp[3] ); - - } else { - return; - } - - lingrad = ctx.createLinearGradient( p0, p1, p2, p3 ); - increment = 1 / (steps.length - 1); - - for (i = 0, len = steps.length; i < len; i+=1) { - try { - lingrad.addColorStop(increment * i, steps[i]); - } - catch(e) { - h2clog(['failed to add color stop: ', e, '; tried to add: ', steps[i], '; stop: ', i, '; in: ', src]); - } - } - - ctx.fillStyle = lingrad; - - // draw shapes - ctx.fillRect(0, 0, bounds.width,bounds.height); - img = new Image(); - img.src = canvas.toDataURL(); + + if(gradient){ + lingrad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1); + + for (i = 0, len = gradient.colorStops.length; i < len; i+=1) { + try { + lingrad.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 = lingrad; + ctx.fillRect(0, 0, bounds.width, bounds.height); + + img.src = canvas.toDataURL(); + } return img; - }; _html2canvas.Generate.ListAlpha = function(number) { @@ -160,3 +174,5 @@ _html2canvas.Generate.ListRoman = function(number) { return roman; }; + +})(); \ No newline at end of file diff --git a/tests/background.html b/tests/background.html index ef97595..8b0a184 100644 --- a/tests/background.html +++ b/tests/background.html @@ -54,6 +54,38 @@ .linearGradient2 { background: -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232))); } + + .linearGradient3 { + /* FF 3.6+ */ + background: -moz-linear-gradient(left, #ff0000, #ffff00, #00ff00); + /* Chrome,Safari4+ */ + background: -webkit-gradient(linear, left top, right top, color-stop(#ff0000), color-stop(#ffff00), color-stop(#00ff00)); + /* Chrome 10+, Safari 5.1+ */ + background: -webkit-linear-gradient(left, #ff0000, #ffff00, #00ff00); + /* Opera 11.10+ */ + background: -o-linear-gradient(left, #ff0000, #ffff00, #00ff00); + /* IE 10+ */ + background: -ms-linear-gradient(left, #ff0000, #ffff00, #00ff00); + /* W3C */ + background: linear-gradient(left, #ff0000, #ffff00, #00ff00); + } + + .linearGradient4 { + /* IE9 SVG */ + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2NlZGJlOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjE3JSIgc3RvcC1jb2xvcj0iI2FhYzVkZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzYxOTljNyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUxJSIgc3RvcC1jb2xvcj0iIzNhODRjMyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjU5JSIgc3RvcC1jb2xvcj0iIzQxOWFkNiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjcxJSIgc3RvcC1jb2xvcj0iIzRiYjhmMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9Ijg0JSIgc3RvcC1jb2xvcj0iIzNhOGJjMiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMyNjU1OGIiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); + /* FF 3.6+ */ + background: -moz-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%); + /* Chrome, Safari 4+ */ + background: -webkit-gradient(linear, left top, right top, color-stop(0%, #cedbe9), color-stop(17%, #aac5de), color-stop(50%, #6199c7), color-stop(51%, #3a84c3), color-stop(59%, #419ad6), color-stop(71%, #4bb8f0), color-stop(84%, #3a8bc2), color-stop(100%, #26558b)); + /* Chrome 10+, Safari 5.1+ */ + background: -webkit-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%); + /* Opera 11.10+ */ + background: -o-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%); + /* IE10+ */ + background: -ms-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%); + /* W3C */ + background: linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%); + } @@ -61,6 +93,8 @@
 
 
+
 
+