From 1aa1d69842fa84f4de1e0cf9f3835df52d437c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20B=C3=A9la=20Palkovics?= Date: Sat, 13 Sep 2014 19:27:19 +0200 Subject: [PATCH 1/5] resolves #5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements textAlign Signed-off-by: Luca Béla Palkovics --- canvas2svg.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index 898a3f8..382fa90 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -746,7 +746,8 @@ "font-weight" : font.weight, "text-decoration" : font.decoration, "x" : x, - "y" : y + "y" : y, + "text-anchor": this.textAlign.replace("left", "start").replace("right", "end").replace("center", "middle") }, true); textElement.appendChild(document.createTextNode(text)); From 39e147def7af04a2855dac9582420bc7699deff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20B=C3=A9la=20Palkovics?= Date: Sun, 14 Sep 2014 09:38:54 +0200 Subject: [PATCH 2/5] Update canvas2svg.js Added Helper function. --- canvas2svg.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/canvas2svg.js b/canvas2svg.js index 382fa90..ffada46 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -57,6 +57,12 @@ lookup["\\xa0"] = ' '; return lookup; } + + //helper function to map canvas-textAlign to svg-textAnchor + function getTextAnchor(textAlign) { + var mapping = {"left":"start", "right":"end", "center":"middle", "start":"start", "end":"end"}; + return mapping[textAlign] || mapping.start; + } // Unpack entities lookup where the numbers are in radix 32 to reduce the size // entity mapping courtesy of tinymce @@ -747,7 +753,7 @@ "text-decoration" : font.decoration, "x" : x, "y" : y, - "text-anchor": this.textAlign.replace("left", "start").replace("right", "end").replace("center", "middle") + "text-anchor": getTextAnchor(this.textAlign) }, true); textElement.appendChild(document.createTextNode(text)); From 519231b78ae5b4ac16d5b661017cd4a69c44499e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20B=C3=A9la=20Palkovics?= Date: Sun, 14 Sep 2014 09:58:46 +0200 Subject: [PATCH 3/5] Correct measureText set `font` of `__ctx` before `measureText`. --- canvas2svg.js | 1 + 1 file changed, 1 insertion(+) diff --git a/canvas2svg.js b/canvas2svg.js index 898a3f8..192bb98 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -781,6 +781,7 @@ * @return {TextMetrics} */ ctx.prototype.measureText = function(text){ + this.__ctx.font = this.font; return this.__ctx.measureText(text); }; From ffc017bfe268b64bf7442f3abfe0ee7935e63853 Mon Sep 17 00:00:00 2001 From: kerryliu Date: Sun, 14 Sep 2014 09:11:03 -0700 Subject: [PATCH 4/5] fixes #6 --- canvas2svg.js | 5 ++++- jasmine-tests/spec/canvas2svgspec.js | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/canvas2svg.js b/canvas2svg.js index 898a3f8..088c977 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -1,5 +1,5 @@ /*!! - * Canvas 2 Svg v1.0.4 + * Canvas 2 Svg v1.0.5 * A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document. * * Licensed under the MIT license: @@ -507,6 +507,9 @@ * if the currentPathElement is not empty create a new path element */ ctx.prototype.moveTo = function(x,y){ + if(this.__currentElement.nodeName !== "path") { + this.beginPath(); + } this.__addPathCommand(format("M {x} {y}", {x:x, y:y})); }; diff --git a/jasmine-tests/spec/canvas2svgspec.js b/jasmine-tests/spec/canvas2svgspec.js index b4b3cdf..b338f93 100755 --- a/jasmine-tests/spec/canvas2svgspec.js +++ b/jasmine-tests/spec/canvas2svgspec.js @@ -38,11 +38,11 @@ describe("canvas2svg", function() { expect(ctx2.height).toEqual(400); expect(ctx2.enableMirroring).toEqual(false); - var ctx = C2S(); - expect(ctx instanceof C2S).toBe(true); - expect(ctx.width).toEqual(500); - expect(ctx.height).toEqual(500); - expect(ctx.enableMirroring).toEqual(false); + var ctx3 = C2S(); + expect(ctx3 instanceof C2S).toBe(true); + expect(ctx3.width).toEqual(500); + expect(ctx3.height).toEqual(500); + expect(ctx3.enableMirroring).toEqual(false); }); @@ -155,4 +155,14 @@ describe("canvas2svg", function() { }); }); + describe("supports path commands", function() { + + it("and moveTo may be called without beginPath, but is not recommended", function() { + var ctx = new C2S(); + ctx.moveTo(0,0); + ctx.lineTo(100,100); + ctx.stroke(); + }); + }); + }); From d984cf76e72bbe300c220a62cd7bf0f13f738fc2 Mon Sep 17 00:00:00 2001 From: kerryliu Date: Sun, 14 Sep 2014 09:42:26 -0700 Subject: [PATCH 5/5] add unit tests for new textalign support, update readme --- README.md | 1 + canvas2svg.js | 1 + jasmine-tests/spec/canvas2svgspec.js | 63 ++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/README.md b/README.md index aae7258..8c4158a 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ var svg = ctx.getSvg(); Updates ========== +- v1.0.5 fixes for #5 and #6 (with contributions from KoKuToru) - v1.0.4 generate ids that start with a letter - v1.0.3 fixed #4 where largeArcFlag was set incorrectly in some cases - v1.0.2 Split up rgba values set in fill/stroke to allow illustrator import support. diff --git a/canvas2svg.js b/canvas2svg.js index 303c46a..e8e4f33 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -60,6 +60,7 @@ //helper function to map canvas-textAlign to svg-textAnchor function getTextAnchor(textAlign) { + //TODO: support rtl languages var mapping = {"left":"start", "right":"end", "center":"middle", "start":"start", "end":"end"}; return mapping[textAlign] || mapping.start; } diff --git a/jasmine-tests/spec/canvas2svgspec.js b/jasmine-tests/spec/canvas2svgspec.js index b338f93..00674c9 100755 --- a/jasmine-tests/spec/canvas2svgspec.js +++ b/jasmine-tests/spec/canvas2svgspec.js @@ -165,4 +165,67 @@ describe("canvas2svg", function() { }); }); + describe("supports text align", function() { + + it("not specifying a value defaults to 'start'", function() { + + var ctx = new C2S(); + ctx.font = "normal 36px Times"; + ctx.fillStyle = "#000000"; + ctx.fillText("A Text Example", 0, 50); + var svg = ctx.getSvg(); + expect(svg.querySelector("text").getAttribute("text-anchor")).toBe("start"); + + }); + + it("assuming ltr, left maps to 'start'", function() { + + var ctx = new C2S(); + ctx.textAlign = "left"; + ctx.font = "normal 36px Times"; + ctx.fillStyle = "#000000"; + ctx.fillText("A Text Example", 0, 50); + var svg = ctx.getSvg(); + expect(svg.querySelector("text").getAttribute("text-anchor")).toBe("start"); + + }); + + it("assuming ltr, right maps to 'end'", function() { + + var ctx = new C2S(); + ctx.textAlign = "right"; + ctx.font = "normal 36px Times"; + ctx.fillStyle = "#000000"; + ctx.fillText("A Text Example", 0, 50); + var svg = ctx.getSvg(); + expect(svg.querySelector("text").getAttribute("text-anchor")).toBe("end"); + + }); + + it("center maps to 'middle'", function() { + + var ctx = new C2S(); + ctx.textAlign = "center"; + ctx.font = "normal 36px Times"; + ctx.fillStyle = "#000000"; + ctx.fillText("A Text Example", 0, 50); + var svg = ctx.getSvg(); + expect(svg.querySelector("text").getAttribute("text-anchor")).toBe("middle"); + + }); + + it("stores the proper values on save and restore", function() { + var ctx = new C2S(); + ctx.textAlign = "center"; + expect(ctx.textAlign).toBe("center"); + ctx.save(); + expect(ctx.textAlign).toBe("center"); + ctx.textAlign = "right"; + expect(ctx.textAlign).toBe("right"); + ctx.restore(); + expect(ctx.textAlign).toBe("center"); + }); + + }); + });