fix issue with mixing transform with path commands
Fixes this case: var ctx = new C2S() ctx.save() ctx.translate(10, 10) ctx.fillStyle = 'red' ctx.fillRect(0, 0, 10, 10) ctx.fillStyle = 'blue' ctx.fillRect(10, 0, 10, 10) ctx.fillStyle = 'green' ctx.fillRect(20, 0, 10, 10) ctx.fillStyle = 'pink' ctx.translate(10, 10); ctx.rect(0, 0, 10, 10); ctx.translate(10, 10); ctx.rect(0, 0, 100, 100); ctx.scale(2, 2) ctx.rect(100, 100, 10, 10); ctx.fill() window.open(`data:image/svg+xml;utf8,${ctx.getSerializedSvg()}`)
This commit is contained in:
parent
17a2239c37
commit
c7df7fa81e
@ -340,13 +340,23 @@
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ctx.prototype.__applyStyleToCurrentElement = function (type) {
|
ctx.prototype.__applyStyleToCurrentElement = function (type) {
|
||||||
|
var currentElement = this.__currentElement;
|
||||||
|
var currentStyleGroup = this.__currentElementsToStyle;
|
||||||
|
if (currentStyleGroup) {
|
||||||
|
currentElement.setAttribute(type, "");
|
||||||
|
currentElement = currentStyleGroup.element;
|
||||||
|
currentStyleGroup.children.forEach(function (node) {
|
||||||
|
node.setAttribute(type, "");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var keys = Object.keys(STYLES), i, style, value, id, regex, matches;
|
var keys = Object.keys(STYLES), i, style, value, id, regex, matches;
|
||||||
for (i=0; i<keys.length; i++) {
|
for (i = 0; i < keys.length; i++) {
|
||||||
style = STYLES[keys[i]];
|
style = STYLES[keys[i]];
|
||||||
value = this[keys[i]];
|
value = this[keys[i]];
|
||||||
if (style.apply) {
|
if (style.apply) {
|
||||||
//is this a gradient or pattern?
|
//is this a gradient or pattern?
|
||||||
if (style.apply.indexOf("fill")!==-1 && value instanceof CanvasPattern) {
|
if (style.apply.indexOf("fill") !== -1 && value instanceof CanvasPattern) {
|
||||||
//pattern
|
//pattern
|
||||||
if (value.__ctx) {
|
if (value.__ctx) {
|
||||||
//copy over defs
|
//copy over defs
|
||||||
@ -356,37 +366,35 @@
|
|||||||
this.__defs.appendChild(value.__ctx.__defs.childNodes[0]);
|
this.__defs.appendChild(value.__ctx.__defs.childNodes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
||||||
}
|
}
|
||||||
else if (style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) {
|
else if (style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) {
|
||||||
//gradient
|
//gradient
|
||||||
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
||||||
} else if (style.apply.indexOf(type)!==-1 && style.svg !== value) {
|
} else if (style.apply.indexOf(type)!==-1 && style.svg !== value) {
|
||||||
if ((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) {
|
if ((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) {
|
||||||
//separate alpha value, since illustrator can't handle it
|
//separate alpha value, since illustrator can't handle it
|
||||||
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
|
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
|
||||||
matches = regex.exec(value);
|
matches = regex.exec(value);
|
||||||
this.__currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
|
currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
|
||||||
//should take globalAlpha here
|
//should take globalAlpha here
|
||||||
var opacity = matches[4];
|
var opacity = matches[4];
|
||||||
var globalAlpha = this.globalAlpha;
|
var globalAlpha = this.globalAlpha;
|
||||||
if (globalAlpha != null) {
|
if (globalAlpha != null) {
|
||||||
opacity *= globalAlpha;
|
opacity *= globalAlpha;
|
||||||
}
|
}
|
||||||
this.__currentElement.setAttribute(style.svgAttr+"-opacity", opacity);
|
currentElement.setAttribute(style.svgAttr+"-opacity", opacity);
|
||||||
} else {
|
} else {
|
||||||
var attr = style.svgAttr;
|
var attr = style.svgAttr;
|
||||||
if (keys[i] === 'globalAlpha') {
|
if (keys[i] === 'globalAlpha') {
|
||||||
attr = type+'-'+style.svgAttr;
|
attr = type+'-'+style.svgAttr;
|
||||||
if (this.__currentElement.getAttribute(attr)) {
|
if (currentElement.getAttribute(attr)) {
|
||||||
//fill-opacity or stroke-opacity has already been set by stroke or fill.
|
//fill-opacity or stroke-opacity has already been set by stroke or fill.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//otherwise only update attribute if right type, and not svg default
|
//otherwise only update attribute if right type, and not svg default
|
||||||
this.__currentElement.setAttribute(attr, value);
|
currentElement.setAttribute(attr, value);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,13 +470,13 @@
|
|||||||
*/
|
*/
|
||||||
ctx.prototype.restore = function () {
|
ctx.prototype.restore = function () {
|
||||||
this.__currentElement = this.__groupStack.pop();
|
this.__currentElement = this.__groupStack.pop();
|
||||||
|
this.__currentElementsToStyle = null;
|
||||||
//Clearing canvas will make the poped group invalid, currentElement is set to the root group node.
|
//Clearing canvas will make the poped group invalid, currentElement is set to the root group node.
|
||||||
if (!this.__currentElement) {
|
if (!this.__currentElement) {
|
||||||
this.__currentElement = this.__root.childNodes[1];
|
this.__currentElement = this.__root.childNodes[1];
|
||||||
}
|
}
|
||||||
var state = this.__stack.pop();
|
var state = this.__stack.pop();
|
||||||
this.__applyStyleState(state);
|
this.__applyStyleState(state);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -479,6 +487,12 @@
|
|||||||
//if the current element has siblings, add another group
|
//if the current element has siblings, add another group
|
||||||
var parent = this.__closestGroupOrSvg();
|
var parent = this.__closestGroupOrSvg();
|
||||||
if (parent.childNodes.length > 0) {
|
if (parent.childNodes.length > 0) {
|
||||||
|
if (this.__currentElement.nodeName === "path") {
|
||||||
|
this.__currentElementsToStyle || (this.__currentElementsToStyle = { element: parent, children: [] });
|
||||||
|
this.__currentElementsToStyle.children.push(this.__currentElement)
|
||||||
|
this.__applyCurrentDefaultPath();
|
||||||
|
}
|
||||||
|
|
||||||
var group = this.__createElement("g");
|
var group = this.__createElement("g");
|
||||||
parent.appendChild(group);
|
parent.appendChild(group);
|
||||||
this.__currentElement = group;
|
this.__currentElement = group;
|
||||||
@ -548,11 +562,11 @@
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ctx.prototype.__applyCurrentDefaultPath = function () {
|
ctx.prototype.__applyCurrentDefaultPath = function () {
|
||||||
if (this.__currentElement.nodeName === "path") {
|
var currentElement = this.__currentElement;
|
||||||
var d = this.__currentDefaultPath;
|
if (currentElement.nodeName === "path") {
|
||||||
this.__currentElement.setAttribute("d", d);
|
currentElement.setAttribute("d", this.__currentDefaultPath);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Attempted to apply path command to node " + this.__currentElement.nodeName);
|
console.error("Attempted to apply path command to node", currentElement.nodeName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user