From 0b16b0c346aabd9ca27cc987b79929d5a256f57c Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Thu, 28 Jul 2016 01:07:38 -0700 Subject: [PATCH 1/7] fix issue in ctx.closePath() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prevents path from starting with ā€˜Zā€™ and throwing an error --- canvas2svg.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index 03dc392..7599402 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -585,7 +585,9 @@ * Closes the current path */ ctx.prototype.closePath = function(){ - this.__addPathCommand("Z"); + if (this.__currentDefaultPath) { + this.__addPathCommand("Z"); + } }; /** From 17a2239c3768e7561eaff5333dec4fc86712ab70 Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Sat, 13 Aug 2016 15:47:36 -0700 Subject: [PATCH 2/7] make if/for/function formatting uniform --- canvas2svg.js | 206 +++++++++++++++++++++++++------------------------- 1 file changed, 102 insertions(+), 104 deletions(-) diff --git a/canvas2svg.js b/canvas2svg.js index 7599402..9e03866 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -11,7 +11,7 @@ * Copyright (c) 2014 Gliffy Inc. */ -;(function() { +;(function () { "use strict"; var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities; @@ -181,7 +181,7 @@ * @param gradientNode - reference to the gradient * @constructor */ - CanvasGradient = function(gradientNode, ctx) { + CanvasGradient = function (gradientNode, ctx) { this.__root = gradientNode; this.__ctx = ctx; }; @@ -189,10 +189,10 @@ /** * Adds a color stop to the gradient root */ - CanvasGradient.prototype.addColorStop = function(offset, color) { + CanvasGradient.prototype.addColorStop = function (offset, color) { var stop = this.__ctx.__createElement("stop"), regex, matches; stop.setAttribute("offset", offset); - if(color.indexOf("rgba") !== -1) { + if (color.indexOf("rgba") !== -1) { //separate alpha value, since webkit can't handle it regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi; matches = regex.exec(color); @@ -204,7 +204,7 @@ this.__root.appendChild(stop); }; - CanvasPattern = function(pattern, ctx) { + CanvasPattern = function (pattern, ctx) { this.__root = pattern; this.__ctx = ctx; }; @@ -217,22 +217,21 @@ * enableMirroring - enables canvas mirroring (get image data) (defaults to false) * document - the document object (defaults to the current document) */ - ctx = function(o) { - + ctx = function (o) { var defaultOptions = { width:500, height:500, enableMirroring : false}, options; //keep support for this way of calling C2S: new C2S(width,height) - if(arguments.length > 1) { + if (arguments.length > 1) { options = defaultOptions; options.width = arguments[0]; options.height = arguments[1]; - } else if( !o ) { + } else if ( !o ) { options = defaultOptions; } else { options = o; } - if(!(this instanceof ctx)) { + if (!(this instanceof ctx)) { //did someone call this without new? return new ctx(options); } @@ -283,12 +282,12 @@ var element = this.__document.createElementNS("http://www.w3.org/2000/svg", elementName), keys = Object.keys(properties), i, key; - if(resetFill) { + if (resetFill) { //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black. element.setAttribute("fill", "none"); element.setAttribute("stroke", "none"); } - for(i=0; i 0) { + if (parent.childNodes.length > 0) { var group = this.__createElement("g"); parent.appendChild(group); this.__currentElement = group; } var transform = this.__currentElement.getAttribute("transform"); - if(transform) { + if (transform) { transform += " "; } else { transform = ""; @@ -499,8 +497,8 @@ /** * scales the current element */ - ctx.prototype.scale = function(x, y) { - if(y === undefined) { + ctx.prototype.scale = function (x, y) { + if (y === undefined) { y = x; } this.__addTransform(format("scale({x},{y})", {x:x, y:y})); @@ -509,7 +507,7 @@ /** * rotates the current element */ - ctx.prototype.rotate = function(angle){ + ctx.prototype.rotate = function (angle) { var degrees = (angle * 180 / Math.PI); this.__addTransform(format("rotate({angle},{cx},{cy})", {angle:degrees, cx:0, cy:0})); }; @@ -517,21 +515,21 @@ /** * translates the current element */ - ctx.prototype.translate = function(x, y){ + ctx.prototype.translate = function (x, y) { this.__addTransform(format("translate({x},{y})", {x:x,y:y})); }; /** * applies a transform to the current element */ - ctx.prototype.transform = function(a, b, c, d, e, f){ + ctx.prototype.transform = function (a, b, c, d, e, f) { this.__addTransform(format("matrix({a},{b},{c},{d},{e},{f})", {a:a, b:b, c:c, d:d, e:e, f:f})); }; /** * Create a new Path Element */ - ctx.prototype.beginPath = function(){ + ctx.prototype.beginPath = function () { var path, parent; // Note that there is only one current default path, it is not part of the drawing state. @@ -549,8 +547,8 @@ * Helper function to apply currentDefaultPath to current path element * @private */ - ctx.prototype.__applyCurrentDefaultPath = function() { - if(this.__currentElement.nodeName === "path") { + ctx.prototype.__applyCurrentDefaultPath = function () { + if (this.__currentElement.nodeName === "path") { var d = this.__currentDefaultPath; this.__currentElement.setAttribute("d", d); } else { @@ -562,7 +560,7 @@ * Helper function to add path command * @private */ - ctx.prototype.__addPathCommand = function(command){ + ctx.prototype.__addPathCommand = function (command) { this.__currentDefaultPath += " "; this.__currentDefaultPath += command; }; @@ -571,8 +569,8 @@ * Adds the move command to the current path element, * if the currentPathElement is not empty create a new path element */ - ctx.prototype.moveTo = function(x,y){ - if(this.__currentElement.nodeName !== "path") { + ctx.prototype.moveTo = function (x,y) { + if (this.__currentElement.nodeName !== "path") { this.beginPath(); } @@ -584,7 +582,7 @@ /** * Closes the current path */ - ctx.prototype.closePath = function(){ + ctx.prototype.closePath = function () { if (this.__currentDefaultPath) { this.__addPathCommand("Z"); } @@ -593,7 +591,7 @@ /** * Adds a line to command */ - ctx.prototype.lineTo = function(x, y){ + ctx.prototype.lineTo = function (x, y) { this.__currentPosition = {x: x, y: y}; if (this.__currentDefaultPath.indexOf('M') > -1) { this.__addPathCommand(format("L {x} {y}", {x:x, y:y})); @@ -605,7 +603,7 @@ /** * Add a bezier command */ - ctx.prototype.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { + ctx.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { this.__currentPosition = {x: x, y: y}; this.__addPathCommand(format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}", {cp1x:cp1x, cp1y:cp1y, cp2x:cp2x, cp2y:cp2y, x:x, y:y})); @@ -614,7 +612,7 @@ /** * Adds a quadratic curve to command */ - ctx.prototype.quadraticCurveTo = function(cpx, cpy, x, y){ + ctx.prototype.quadraticCurveTo = function (cpx, cpy, x, y) { this.__currentPosition = {x: x, y: y}; this.__addPathCommand(format("Q {cpx} {cpy} {x} {y}", {cpx:cpx, cpy:cpy, x:x, y:y})); }; @@ -623,7 +621,7 @@ /** * Return a new normalized vector of given vector */ - var normalize = function(vector) { + var normalize = function (vector) { var len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1]); return [vector[0] / len, vector[1] / len]; }; @@ -633,7 +631,7 @@ * * @see http://www.w3.org/TR/2015/WD-2dcontext-20150514/#dom-context-2d-arcto */ - ctx.prototype.arcTo = function(x1, y1, x2, y2, radius) { + ctx.prototype.arcTo = function (x1, y1, x2, y2, radius) { // Let the point (x0, y0) be the last point in the subpath. var x0 = this.__currentPosition && this.__currentPosition.x; var y0 = this.__currentPosition && this.__currentPosition.y; @@ -699,7 +697,7 @@ unit_vec_p1_p2[1], -unit_vec_p1_p2[0] ]; - var getAngle = function(vector) { + var getAngle = function (vector) { // get angle (clockwise) between vector and (1, 0) var x = vector[0]; var y = vector[1]; @@ -724,8 +722,8 @@ /** * Sets the stroke property on the current element */ - ctx.prototype.stroke = function(){ - if(this.__currentElement.nodeName === "path") { + ctx.prototype.stroke = function () { + if (this.__currentElement.nodeName === "path") { this.__currentElement.setAttribute("paint-order", "fill stroke markers"); } this.__applyCurrentDefaultPath(); @@ -735,8 +733,8 @@ /** * Sets fill properties on the current element */ - ctx.prototype.fill = function(){ - if(this.__currentElement.nodeName === "path") { + ctx.prototype.fill = function () { + if (this.__currentElement.nodeName === "path") { this.__currentElement.setAttribute("paint-order", "stroke fill markers"); } this.__applyCurrentDefaultPath(); @@ -746,8 +744,8 @@ /** * Adds a rectangle to the path. */ - ctx.prototype.rect = function(x, y, width, height){ - if(this.__currentElement.nodeName !== "path") { + ctx.prototype.rect = function (x, y, width, height) { + if (this.__currentElement.nodeName !== "path") { this.beginPath(); } this.moveTo(x, y); @@ -762,7 +760,7 @@ /** * adds a rectangle element */ - ctx.prototype.fillRect = function(x, y, width, height){ + ctx.prototype.fillRect = function (x, y, width, height) { var rect, parent; rect = this.__createElement("rect", { x : x, @@ -783,7 +781,7 @@ * @param width * @param height */ - ctx.prototype.strokeRect = function(x, y, width, height){ + ctx.prototype.strokeRect = function (x, y, width, height) { var rect, parent; rect = this.__createElement("rect", { x : x, @@ -803,7 +801,7 @@ * 1. save current transforms * 2. remove all the childNodes of the root g element */ - ctx.prototype.__clearCanvas = function() { + ctx.prototype.__clearCanvas = function () { var current = this.__closestGroupOrSvg(), transform = current.getAttribute("transform"); var rootGroup = this.__root.childNodes[1]; @@ -824,7 +822,7 @@ /** * "Clears" a canvas by just drawing a white rectangle in the current group. */ - ctx.prototype.clearRect = function(x, y, width, height) { + ctx.prototype.clearRect = function (x, y, width, height) { //clear entire canvas if (x === 0 && y === 0 && width === this.width && height === this.height) { this.__clearCanvas(); @@ -845,7 +843,7 @@ * Adds a linear gradient to a defs tag. * Returns a canvas gradient object that has a reference to it's parent def */ - ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){ + ctx.prototype.createLinearGradient = function (x1, y1, x2, y2) { var grad = this.__createElement("linearGradient", { id : randomString(this.__ids), x1 : x1+"px", @@ -862,7 +860,7 @@ * Adds a radial gradient to a defs tag. * Returns a canvas gradient object that has a reference to it's parent def */ - ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ + ctx.prototype.createRadialGradient = function (x0, y0, r0, x1, y1, r1) { var grad = this.__createElement("radialGradient", { id : randomString(this.__ids), cx : x1+"px", @@ -881,8 +879,8 @@ * Parses the font string and returns svg mapping * @private */ - ctx.prototype.__parseFont = function() { - var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; + ctx.prototype.__parseFont = function () { + var regex = /^\s*(?=(?:(?:[-a-z]+\s*) {0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*) {0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*) {0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*) {0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; var fontPart = regex.exec( this.font ); var data = { style : fontPart[1] || 'normal', @@ -894,12 +892,12 @@ }; //canvas doesn't support underline natively, but we can pass this attribute - if(this.__fontUnderline === "underline") { + if (this.__fontUnderline === "underline") { data.decoration = "underline"; } //canvas also doesn't support linking, but we can pass this as well - if(this.__fontHref) { + if (this.__fontHref) { data.href = this.__fontHref; } @@ -913,8 +911,8 @@ * @return {*} * @private */ - ctx.prototype.__wrapTextLink = function(font, element) { - if(font.href) { + ctx.prototype.__wrapTextLink = function (font, element) { + if (font.href) { var a = this.__createElement("a"); a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href); a.appendChild(element); @@ -931,7 +929,7 @@ * @param action - stroke or fill * @private */ - ctx.prototype.__applyText = function(text, x, y, action) { + ctx.prototype.__applyText = function (text, x, y, action) { var font = this.__parseFont(), parent = this.__closestGroupOrSvg(), textElement = this.__createElement("text", { @@ -958,7 +956,7 @@ * @param x * @param y */ - ctx.prototype.fillText = function(text, x, y){ + ctx.prototype.fillText = function (text, x, y) { this.__applyText(text, x, y, "fill"); }; @@ -968,7 +966,7 @@ * @param x * @param y */ - ctx.prototype.strokeText = function(text, x, y){ + ctx.prototype.strokeText = function (text, x, y) { this.__applyText(text, x, y, "stroke"); }; @@ -977,7 +975,7 @@ * @param text * @return {TextMetrics} */ - ctx.prototype.measureText = function(text){ + ctx.prototype.measureText = function (text) { this.__ctx.font = this.font; return this.__ctx.measureText(text); }; @@ -985,14 +983,14 @@ /** * Arc command! */ - ctx.prototype.arc = function(x, y, radius, startAngle, endAngle, counterClockwise) { + ctx.prototype.arc = function (x, y, radius, startAngle, endAngle, counterClockwise) { // in canvas no circle is drawn if no angle is provided. if (startAngle === endAngle) { return; } startAngle = startAngle % (2*Math.PI); endAngle = endAngle % (2*Math.PI); - if(startAngle === endAngle) { + if (startAngle === endAngle) { //circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle) endAngle = ((endAngle + (2*Math.PI)) - 0.001 * (counterClockwise ? -1 : 1)) % (2*Math.PI); } @@ -1005,11 +1003,11 @@ diff = endAngle - startAngle; // https://github.com/gliffy/canvas2svg/issues/4 - if(diff < 0) { + if (diff < 0) { diff += 2*Math.PI; } - if(counterClockwise) { + if (counterClockwise) { largeArcFlag = diff > Math.PI ? 0 : 1; } else { largeArcFlag = diff > Math.PI ? 1 : 0; @@ -1025,7 +1023,7 @@ /** * Generates a ClipPath from the clip command. */ - ctx.prototype.clip = function(){ + ctx.prototype.clip = function () { var group = this.__closestGroupOrSvg(), clipPath = this.__createElement("clipPath"), id = randomString(this.__ids), @@ -1054,28 +1052,28 @@ * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support. * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage */ - ctx.prototype.drawImage = function(){ + ctx.prototype.drawImage = function () { //convert arguments to a real array var args = Array.prototype.slice.call(arguments), image=args[0], dx, dy, dw, dh, sx=0, sy=0, sw, sh, parent, svg, defs, group, currentElement, svgImage, canvas, context, id; - if(args.length === 3) { + if (args.length === 3) { dx = args[1]; dy = args[2]; sw = image.width; sh = image.height; dw = sw; dh = sh; - } else if(args.length === 5) { + } else if (args.length === 5) { dx = args[1]; dy = args[2]; dw = args[3]; dh = args[4]; sw = image.width; sh = image.height; - } else if(args.length === 9) { + } else if (args.length === 9) { sx = args[1]; sy = args[2]; sw = args[3]; @@ -1091,7 +1089,7 @@ parent = this.__closestGroupOrSvg(); currentElement = this.__currentElement; var translateDirective = "translate(" + dx + ", " + dy + ")"; - if(image instanceof ctx) { + if (image instanceof ctx) { //canvas2svg mock canvas context. In the future we may want to clone nodes instead. //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context. svg = image.getSvg().cloneNode(true); @@ -1116,14 +1114,14 @@ parent.appendChild(group); } } - } else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { + } else if (image.nodeName === "CANVAS" || image.nodeName === "IMG") { //canvas or image svgImage = this.__createElement("image"); svgImage.setAttribute("width", dw); svgImage.setAttribute("height", dh); svgImage.setAttribute("preserveAspectRatio", "none"); - if(sx || sy || sw !== image.width || sh !== image.height) { + if (sx || sy || sw !== image.width || sh !== image.height) { //crop the image using a temporary canvas canvas = this.__document.createElement("canvas"); canvas.width = dw; @@ -1142,13 +1140,13 @@ /** * Generates a pattern tag */ - ctx.prototype.createPattern = function(image, repetition){ + ctx.prototype.createPattern = function (image, repetition) { var pattern = this.__document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids), img; pattern.setAttribute("id", id); pattern.setAttribute("width", image.width); pattern.setAttribute("height", image.height); - if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { + if (image.nodeName === "CANVAS" || image.nodeName === "IMG") { img = this.__document.createElementNS("http://www.w3.org/2000/svg", "image"); img.setAttribute("width", image.width); img.setAttribute("height", image.height); @@ -1156,14 +1154,14 @@ image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src")); pattern.appendChild(img); this.__defs.appendChild(pattern); - } else if(image instanceof ctx) { + } else if (image instanceof ctx) { pattern.appendChild(image.__root.childNodes[1]); this.__defs.appendChild(pattern); } return new CanvasPattern(pattern, this); }; - ctx.prototype.setLineDash = function(dashArray) { + ctx.prototype.setLineDash = function (dashArray) { if (dashArray && dashArray.length > 0) { this.lineDash = dashArray.join(","); } else { @@ -1174,12 +1172,12 @@ /** * Not yet implemented */ - ctx.prototype.drawFocusRing = function(){}; - ctx.prototype.createImageData = function(){}; - ctx.prototype.getImageData = function(){}; - ctx.prototype.putImageData = function(){}; - ctx.prototype.globalCompositeOperation = function(){}; - ctx.prototype.setTransform = function(){}; + ctx.prototype.drawFocusRing = function () {}; + ctx.prototype.createImageData = function () {}; + ctx.prototype.getImageData = function () {}; + ctx.prototype.putImageData = function () {}; + ctx.prototype.globalCompositeOperation = function () {}; + ctx.prototype.setTransform = function () {}; //add options for alternative namespace if (typeof window === "object") { From c7df7fa81e9d8b392d0fc2a894f72af7ba54e306 Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Sat, 13 Aug 2016 16:59:17 -0700 Subject: [PATCH 3/7] 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()}`) --- canvas2svg.js | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/canvas2svg.js b/canvas2svg.js index 9e03866..2be977d 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -340,13 +340,23 @@ * @private */ 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; - for (i=0; i 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"); parent.appendChild(group); this.__currentElement = group; @@ -548,11 +562,11 @@ * @private */ ctx.prototype.__applyCurrentDefaultPath = function () { - if (this.__currentElement.nodeName === "path") { - var d = this.__currentDefaultPath; - this.__currentElement.setAttribute("d", d); + var currentElement = this.__currentElement; + if (currentElement.nodeName === "path") { + currentElement.setAttribute("d", this.__currentDefaultPath); } 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); } }; From 214f8f2a1a094c9646b47dc579a16fb9ad3a4587 Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Sat, 13 Aug 2016 21:30:06 -0700 Subject: [PATCH 4/7] revert regexp --- canvas2svg.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index 2be977d..0796306 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -894,7 +894,7 @@ * @private */ ctx.prototype.__parseFont = function () { - var regex = /^\s*(?=(?:(?:[-a-z]+\s*) {0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*) {0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*) {0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*) {0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; + var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; var fontPart = regex.exec( this.font ); var data = { style : fontPart[1] || 'normal', From f9d5e2b68e957202d1a69d1bc159dee0272253da Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Fri, 6 Jan 2017 16:56:12 -0800 Subject: [PATCH 5/7] fix issue with applying gradient to stroke --- canvas2svg.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/canvas2svg.js b/canvas2svg.js index 0796306..a1861ce 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -356,7 +356,7 @@ value = this[keys[i]]; if (style.apply) { //is this a gradient or pattern? - if (style.apply.indexOf("fill") !== -1 && value instanceof CanvasPattern) { + if (value instanceof CanvasPattern) { //pattern if (value.__ctx) { //copy over defs @@ -366,11 +366,11 @@ this.__defs.appendChild(value.__ctx.__defs.childNodes[0]); } } - currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")})); + currentElement.setAttribute(style.apply, format("url(#{id})", {id:value.__root.getAttribute("id")})); } - else if (style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) { + else if (value instanceof CanvasGradient) { //gradient - currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")})); + currentElement.setAttribute(style.apply, format("url(#{id})", {id:value.__root.getAttribute("id")})); } else if (style.apply.indexOf(type)!==-1 && style.svg !== value) { if ((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) { //separate alpha value, since illustrator can't handle it From 49f22cc7a35c916544db866005c10c82ef90fa2a Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Mon, 16 Jan 2017 15:06:27 -0800 Subject: [PATCH 6/7] fix issue with parsing fonts familys that have numbers in their names --- canvas2svg.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index a1861ce..6c1660c 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -894,7 +894,7 @@ * @private */ ctx.prototype.__parseFont = function () { - var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z]+?)\s*$/i; + var regex = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z0-9]+?)\s*$/i; var fontPart = regex.exec( this.font ); var data = { style : fontPart[1] || 'normal', From e90927c2fd054cfe88227f9f8a01c739f2bb6247 Mon Sep 17 00:00:00 2001 From: Michael Deal Date: Thu, 18 May 2017 22:44:03 -0700 Subject: [PATCH 7/7] Change to regular if() statement --- canvas2svg.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index 6c1660c..e58e0d7 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -488,7 +488,7 @@ var parent = this.__closestGroupOrSvg(); if (parent.childNodes.length > 0) { if (this.__currentElement.nodeName === "path") { - this.__currentElementsToStyle || (this.__currentElementsToStyle = { element: parent, children: [] }); + if (!this.__currentElementsToStyle) this.__currentElementsToStyle = {element: parent, children: []}; this.__currentElementsToStyle.children.push(this.__currentElement) this.__applyCurrentDefaultPath(); }