Skip to content

Commit

Permalink
Fix clipping on css-transformed elements
Browse files Browse the repository at this point in the history
  • Loading branch information
eKoopmans committed Mar 27, 2017
1 parent e58fc69 commit 3aafe82
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
13 changes: 13 additions & 0 deletions src/nodecontainer.js
Expand Up @@ -240,6 +240,11 @@ NodeContainer.prototype.parseTransformMatrix = function() {
return this.transformMatrix;
};

NodeContainer.prototype.inverseTransform = function() {
var transformData = this.parseTransform();
return { origin: transformData.origin, matrix: matrixInverse(transformData.matrix) };
};

NodeContainer.prototype.parseBounds = function() {
return this.bounds || (this.bounds = this.hasTransform() ? offsetBounds(this.node) : getBounds(this.node));
};
Expand Down Expand Up @@ -281,6 +286,14 @@ function parseMatrix(match) {
}
}

function matrixInverse(m) {
// This is programmed specifically for transform matrices, which have a fixed structure.
var a = m[0], b = m[2], c = m[4], d = m[1], e = m[3], f = m[5];
var det = a*e - b*d;
var M = [e, -d, -b, a, b*f-c*e, c*d-a*f].map(function(val) { return val/det; });
return M;
}

function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}
Expand Down
12 changes: 6 additions & 6 deletions src/nodeparser.js
Expand Up @@ -328,11 +328,11 @@ NodeParser.prototype.paintElement = function(container) {
var bounds = container.parseBounds();
this.renderer.clip(container.backgroundClip, function() {
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
}, this);
}, this, container);

this.renderer.clip(container.clip, function() {
this.renderer.renderBorders(container.borders.borders);
}, this);
}, this, container);

this.renderer.clip(container.backgroundClip, function() {
switch (container.node.nodeName) {
Expand Down Expand Up @@ -362,7 +362,7 @@ NodeParser.prototype.paintElement = function(container) {
this.paintFormValue(container);
break;
}
}, this);
}, this, container);
};

NodeParser.prototype.paintCheckbox = function(container) {
Expand All @@ -385,7 +385,7 @@ NodeParser.prototype.paintCheckbox = function(container) {
this.renderer.font(new Color('#424242'), 'normal', 'normal', 'bold', (size - 3) + "px", 'arial');
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
}
}, this);
}, this, container);
};

NodeParser.prototype.paintRadio = function(container) {
Expand All @@ -398,7 +398,7 @@ NodeParser.prototype.paintRadio = function(container) {
if (container.node.checked) {
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), new Color('#424242'));
}
}, this);
}, this, container);
};

NodeParser.prototype.paintFormValue = function(container) {
Expand Down Expand Up @@ -457,7 +457,7 @@ NodeParser.prototype.paintText = function(container) {
this.renderTextDecoration(container.parent, bounds, this.fontMetrics.getMetrics(family, size));
}
}, this);
}, this);
}, this, container.parent);
};

NodeParser.prototype.renderTextDecoration = function(container, bounds, metrics) {
Expand Down
16 changes: 12 additions & 4 deletions src/renderers/canvas.js
Expand Up @@ -67,11 +67,19 @@ CanvasRenderer.prototype.drawImage = function(imageContainer, sx, sy, sw, sh, dx
}
};

CanvasRenderer.prototype.clip = function(shapes, callback, context) {
CanvasRenderer.prototype.clip = function(shapes, callback, context, container) {
this.ctx.save();
shapes.filter(hasEntries).forEach(function(shape) {
this.shape(shape).clip();
}, this);
if (container && container.hasTransform()) {
this.setTransform(container.inverseTransform());
shapes.filter(hasEntries).forEach(function(shape) {
this.shape(shape).clip();
}, this);
this.setTransform(container.parseTransform());
} else {
shapes.filter(hasEntries).forEach(function(shape) {
this.shape(shape).clip();
}, this);
}
callback.call(context);
this.ctx.restore();
};
Expand Down

0 comments on commit 3aafe82

Please sign in to comment.