Partial implementation for transforms

This commit is contained in:
Niklas von Hertzen 2014-02-23 17:35:46 +02:00
parent 5137e5f35a
commit 18d95d669b
5 changed files with 110 additions and 4 deletions

View File

@ -366,6 +366,18 @@ NodeContainer.prototype.css = function(attribute) {
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
};
NodeContainer.prototype.prefixedCss = function(attribute) {
var prefixes = ["webkit", "moz", "ms", "o"];
var value = this.css(attribute);
if (value === undefined) {
prefixes.some(function(prefix) {
value = this.css(prefix + attribute.substr(0, 1).toUpperCase() + attribute.substr(1));
return value !== undefined;
}, this);
}
return value === undefined ? null : value;
};
NodeContainer.prototype.computedStyle = function(type) {
return this.node.ownerDocument.defaultView.getComputedStyle(this.node, type);
};
@ -485,9 +497,35 @@ NodeContainer.prototype.parseTextShadows = function() {
return results;
};
NodeContainer.prototype.parseTransform = function() {
var transformRegExp = /(matrix)\((.+)\)/;
var transform = this.prefixedCss("transform");
if (transform !== null && transform !== "none") {
var matrix = parseMatrix(transform.match(transformRegExp));
if (matrix) {
return {
origin: this.prefixedCss("transformOrigin"),
matrix: matrix
};
}
}
return {
origin: [0, 0],
matrix: [1, 0, 0, 1, 0, 0]
};
};
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
function parseMatrix(match) {
if (match && match[1] === "matrix") {
return match[2].split(",").map(function(s) {
return parseFloat(s.trim());
});
}
}
function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}
@ -725,7 +763,7 @@ NodeParser.prototype.newStackingContext = function(container, hasOwnStacking) {
NodeParser.prototype.createStackingContexts = function() {
this.nodes.forEach(function(container) {
if (isElement(container) && (this.isRootElement(container) || hasOpacity(container) || isPositionedForStacking(container) || this.isBodyWithTransparentRoot(container))) {
if (isElement(container) && (this.isRootElement(container) || hasOpacity(container) || isPositionedForStacking(container) || this.isBodyWithTransparentRoot(container) || hasTransform(container))) {
this.newStackingContext(container, true);
} else if (isElement(container) && ((isPositioned(container) && zIndex0(container)) || isInlineBlock(container) || isFloating(container))) {
this.newStackingContext(container, false);
@ -843,6 +881,10 @@ NodeParser.prototype.paint = function(container) {
NodeParser.prototype.paintNode = function(container) {
if (isStackingContext(container)) {
this.renderer.setOpacity(container.opacity);
var transform = container.parseTransform();
if (transform) {
this.renderer.setTransform(transform);
}
}
var bounds = this.parseBounds(container);
@ -1212,6 +1254,11 @@ function hasOpacity(container) {
return container.css("opacity") < 1;
}
function hasTransform(container) {
var transform = container.prefixedCss("transform");
return transform !== null && transform !== "none";
}
function bind(callback, context) {
return function() {
return callback.apply(context, arguments);
@ -1467,6 +1514,12 @@ CanvasRenderer.prototype.setOpacity = function(opacity) {
this.ctx.globalAlpha = opacity;
};
CanvasRenderer.prototype.setTransform = function(transform) {
this.ctx.translate(transform.origin[0], transform.origin[1]);
this.ctx.setTransform.apply(this.ctx, transform.matrix);
this.ctx.translate(transform.origin[0], transform.origin[1]);
};
CanvasRenderer.prototype.setVariable = function(property, value) {
if (this.variables[property] !== value) {
this.variables[property] = this.ctx[property] = value;

File diff suppressed because one or more lines are too long

View File

@ -26,6 +26,18 @@ NodeContainer.prototype.css = function(attribute) {
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
};
NodeContainer.prototype.prefixedCss = function(attribute) {
var prefixes = ["webkit", "moz", "ms", "o"];
var value = this.css(attribute);
if (value === undefined) {
prefixes.some(function(prefix) {
value = this.css(prefix + attribute.substr(0, 1).toUpperCase() + attribute.substr(1));
return value !== undefined;
}, this);
}
return value === undefined ? null : value;
};
NodeContainer.prototype.computedStyle = function(type) {
return this.node.ownerDocument.defaultView.getComputedStyle(this.node, type);
};
@ -145,9 +157,35 @@ NodeContainer.prototype.parseTextShadows = function() {
return results;
};
NodeContainer.prototype.parseTransform = function() {
var transformRegExp = /(matrix)\((.+)\)/;
var transform = this.prefixedCss("transform");
if (transform !== null && transform !== "none") {
var matrix = parseMatrix(transform.match(transformRegExp));
if (matrix) {
return {
origin: this.prefixedCss("transformOrigin"),
matrix: matrix
};
}
}
return {
origin: [0, 0],
matrix: [1, 0, 0, 1, 0, 0]
};
};
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
function parseMatrix(match) {
if (match && match[1] === "matrix") {
return match[2].split(",").map(function(s) {
return parseFloat(s.trim());
});
}
}
function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}

View File

@ -134,7 +134,7 @@ NodeParser.prototype.newStackingContext = function(container, hasOwnStacking) {
NodeParser.prototype.createStackingContexts = function() {
this.nodes.forEach(function(container) {
if (isElement(container) && (this.isRootElement(container) || hasOpacity(container) || isPositionedForStacking(container) || this.isBodyWithTransparentRoot(container))) {
if (isElement(container) && (this.isRootElement(container) || hasOpacity(container) || isPositionedForStacking(container) || this.isBodyWithTransparentRoot(container) || hasTransform(container))) {
this.newStackingContext(container, true);
} else if (isElement(container) && ((isPositioned(container) && zIndex0(container)) || isInlineBlock(container) || isFloating(container))) {
this.newStackingContext(container, false);
@ -252,6 +252,10 @@ NodeParser.prototype.paint = function(container) {
NodeParser.prototype.paintNode = function(container) {
if (isStackingContext(container)) {
this.renderer.setOpacity(container.opacity);
var transform = container.parseTransform();
if (transform) {
this.renderer.setTransform(transform);
}
}
var bounds = this.parseBounds(container);
@ -621,6 +625,11 @@ function hasOpacity(container) {
return container.css("opacity") < 1;
}
function hasTransform(container) {
var transform = container.prefixedCss("transform");
return transform !== null && transform !== "none";
}
function bind(callback, context) {
return function() {
return callback.apply(context, arguments);

View File

@ -64,6 +64,12 @@ CanvasRenderer.prototype.setOpacity = function(opacity) {
this.ctx.globalAlpha = opacity;
};
CanvasRenderer.prototype.setTransform = function(transform) {
this.ctx.translate(transform.origin[0], transform.origin[1]);
this.ctx.setTransform.apply(this.ctx, transform.matrix);
this.ctx.translate(transform.origin[0], transform.origin[1]);
};
CanvasRenderer.prototype.setVariable = function(property, value) {
if (this.variables[property] !== value) {
this.variables[property] = this.ctx[property] = value;