From e58fc6902bed666adb6b5ad3761d192b4d307922 Mon Sep 17 00:00:00 2001 From: Erik Koopmans Date: Sun, 26 Mar 2017 21:24:08 -0400 Subject: [PATCH 1/5] Remove grunt webdriver task for pull requests --- Gruntfile.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index af9004605..3b1ae26dc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -177,6 +177,9 @@ module.exports = function(grunt) { }); grunt.registerTask('webdriver', 'Browser render tests', function(browser, test) { + if (process.env.TRAVIS_PULL_REQUEST != "false") { + return; + } var selenium = require("./tests/selenium.js"); var done = this.async(); var browsers = (browser) ? [grunt.config.get(this.name + "." + browser)] : _.values(grunt.config.get(this.name)); From 32b8d1c92656f05f6ff4d31977d1fd720c9d6a43 Mon Sep 17 00:00:00 2001 From: Erik Koopmans Date: Sat, 25 Mar 2017 15:25:36 -0400 Subject: [PATCH 2/5] Add box-shadow rendering --- src/nodeparser.js | 4 ++++ src/renderer.js | 8 ++++++++ src/renderers/canvas.js | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/nodeparser.js b/src/nodeparser.js index 683f9bdd8..c62417517 100644 --- a/src/nodeparser.js +++ b/src/nodeparser.js @@ -330,6 +330,10 @@ NodeParser.prototype.paintElement = function(container) { this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth)); }, this); + this.renderer.mask(bounds, function() { + this.renderer.renderShadows(container, bounds); + }, this); + this.renderer.clip(container.clip, function() { this.renderer.renderBorders(container.borders.borders); }, this); diff --git a/src/renderer.js b/src/renderer.js index 11e96172f..50140ea10 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -44,6 +44,14 @@ Renderer.prototype.renderBackgroundColor = function(container, bounds) { } }; +Renderer.prototype.renderShadows = function(container, bounds) { + var boxShadow = container.css('boxShadow'); + if (boxShadow !== 'none') { + var shadows = boxShadow.split(/,(?![^(]*\))/); + this.shadow(bounds.left, bounds.top, bounds.width, bounds.height, shadows); + } +}; + Renderer.prototype.renderBorders = function(borders) { borders.forEach(this.renderBorder, this); }; diff --git a/src/renderers/canvas.js b/src/renderers/canvas.js index 225a1488a..c7c126122 100644 --- a/src/renderers/canvas.js +++ b/src/renderers/canvas.js @@ -41,6 +41,39 @@ CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, this.ctx.stroke(); }; +CanvasRenderer.prototype.shadow = function(left, top, width, height, shadows) { + var parseShadow = function(str) { + var propertyFilters = { color: /^(#|rgb|hsl|(?!(inset|initial|inherit))\D+)/i, inset: /^inset/i, px: /px$/i }; + var pxPropertyNames = [ 'x', 'y', 'blur', 'spread' ]; + var properties = str.split(/ (?![^(]*\))/); + var info = {}; + for (var key in propertyFilters) { + info[key] = properties.filter(propertyFilters[key].test.bind(propertyFilters[key])); + info[key] = info[key].length === 0 ? null : info[key].length === 1 ? info[key][0] : info[key]; + } + for (var i=0; i Date: Thu, 6 Apr 2017 17:58:09 -0400 Subject: [PATCH 3/5] Handle complex masking/clipping --- src/nodeparser.js | 2 +- src/renderers/canvas.js | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/nodeparser.js b/src/nodeparser.js index c62417517..f1fbbe0ab 100644 --- a/src/nodeparser.js +++ b/src/nodeparser.js @@ -330,7 +330,7 @@ NodeParser.prototype.paintElement = function(container) { this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth)); }, this); - this.renderer.mask(bounds, function() { + this.renderer.mask(container.backgroundClip, function() { this.renderer.renderShadows(container, bounds); }, this); diff --git a/src/renderers/canvas.js b/src/renderers/canvas.js index c7c126122..c7f1943f8 100644 --- a/src/renderers/canvas.js +++ b/src/renderers/canvas.js @@ -109,14 +109,14 @@ CanvasRenderer.prototype.clip = function(shapes, callback, context) { this.ctx.restore(); }; -CanvasRenderer.prototype.mask = function(bounds, callback, context) { - var canvasBorderCCW = ["rect", this.canvas.width, 0, -this.canvas.width, this.canvas.height]; - var boundsCW = ["rect", bounds.left, bounds.top, bounds.width, bounds.height]; - this.ctx.save(); - var shape = [canvasBorderCCW, boundsCW]; - this.shape(shape).clip(); - callback.call(context); - this.ctx.restore(); +CanvasRenderer.prototype.mask = function(shapes, callback, context) { + var borderClip = shapes[shapes.length-1]; + if (borderClip && borderClip.length) { + var canvasBorderCCW = ["rect", this.canvas.width, 0, -this.canvas.width, this.canvas.height]; + var maskShape = [canvasBorderCCW].concat(borderClip).concat([borderClip[0]]); + shapes = shapes.slice(0,-1).concat([maskShape]); + } + this.clip(shapes, callback, context); }; CanvasRenderer.prototype.shape = function(shape) { From a077b4a49391034a0ec3b1039e92f7730fab4554 Mon Sep 17 00:00:00 2001 From: Erik Koopmans Date: Thu, 6 Apr 2017 18:01:05 -0400 Subject: [PATCH 4/5] Draw drop-shadows with complex shapes --- src/nodeparser.js | 2 +- src/renderer.js | 4 ++-- src/renderers/canvas.js | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/nodeparser.js b/src/nodeparser.js index f1fbbe0ab..8bde2f2ed 100644 --- a/src/nodeparser.js +++ b/src/nodeparser.js @@ -331,7 +331,7 @@ NodeParser.prototype.paintElement = function(container) { }, this); this.renderer.mask(container.backgroundClip, function() { - this.renderer.renderShadows(container, bounds); + this.renderer.renderShadows(container, container.borders.clip); }, this); this.renderer.clip(container.clip, function() { diff --git a/src/renderer.js b/src/renderer.js index 50140ea10..c7d0cb191 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -44,11 +44,11 @@ Renderer.prototype.renderBackgroundColor = function(container, bounds) { } }; -Renderer.prototype.renderShadows = function(container, bounds) { +Renderer.prototype.renderShadows = function(container, shape) { var boxShadow = container.css('boxShadow'); if (boxShadow !== 'none') { var shadows = boxShadow.split(/,(?![^(]*\))/); - this.shadow(bounds.left, bounds.top, bounds.width, bounds.height, shadows); + this.shadow(shape, shadows); } }; diff --git a/src/renderers/canvas.js b/src/renderers/canvas.js index c7f1943f8..2d7bdc3b5 100644 --- a/src/renderers/canvas.js +++ b/src/renderers/canvas.js @@ -41,7 +41,7 @@ CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, this.ctx.stroke(); }; -CanvasRenderer.prototype.shadow = function(left, top, width, height, shadows) { +CanvasRenderer.prototype.shadow = function(shape, shadows) { var parseShadow = function(str) { var propertyFilters = { color: /^(#|rgb|hsl|(?!(inset|initial|inherit))\D+)/i, inset: /^inset/i, px: /px$/i }; var pxPropertyNames = [ 'x', 'y', 'blur', 'spread' ]; @@ -68,8 +68,7 @@ CanvasRenderer.prototype.shadow = function(left, top, width, height, shadows) { }; var context = this.setFillStyle('white'); context.save(); - context.beginPath(); - context.rect(left, top, width, height); + this.shape(shape); shadows.forEach(drawShadow, this); context.restore(); }; From 29a15f6291713b6aaf257a8283fefe6d1aa29758 Mon Sep 17 00:00:00 2001 From: Erik Koopmans Date: Thu, 6 Apr 2017 18:04:07 -0400 Subject: [PATCH 5/5] Add container for merge with bugfix/clip-transform --- src/nodeparser.js | 2 +- src/renderers/canvas.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nodeparser.js b/src/nodeparser.js index 8bde2f2ed..961b9a47b 100644 --- a/src/nodeparser.js +++ b/src/nodeparser.js @@ -332,7 +332,7 @@ NodeParser.prototype.paintElement = function(container) { this.renderer.mask(container.backgroundClip, function() { this.renderer.renderShadows(container, container.borders.clip); - }, this); + }, this, container); this.renderer.clip(container.clip, function() { this.renderer.renderBorders(container.borders.borders); diff --git a/src/renderers/canvas.js b/src/renderers/canvas.js index 2d7bdc3b5..ea5083769 100644 --- a/src/renderers/canvas.js +++ b/src/renderers/canvas.js @@ -108,14 +108,14 @@ CanvasRenderer.prototype.clip = function(shapes, callback, context) { this.ctx.restore(); }; -CanvasRenderer.prototype.mask = function(shapes, callback, context) { +CanvasRenderer.prototype.mask = function(shapes, callback, context, container) { var borderClip = shapes[shapes.length-1]; if (borderClip && borderClip.length) { var canvasBorderCCW = ["rect", this.canvas.width, 0, -this.canvas.width, this.canvas.height]; var maskShape = [canvasBorderCCW].concat(borderClip).concat([borderClip[0]]); shapes = shapes.slice(0,-1).concat([maskShape]); } - this.clip(shapes, callback, context); + this.clip(shapes, callback, context, container); }; CanvasRenderer.prototype.shape = function(shape) {