From 96da4c2c6c93e6acb7ab7fb310fddcb6689b09d0 Mon Sep 17 00:00:00 2001 From: Dmitry Baranovskiy Date: Mon, 2 Feb 2015 14:56:47 +1100 Subject: [PATCH] Fixes #8 Nesting tspans --- svgWriter.js | 245 ++++++++++++++++++++++++++++----------- tests/data/svgText.svg | 6 +- tests/data/svgTextFx.svg | 2 +- 3 files changed, 183 insertions(+), 70 deletions(-) diff --git a/svgWriter.js b/svgWriter.js index 0572876..046a011 100644 --- a/svgWriter.js +++ b/svgWriter.js @@ -99,7 +99,7 @@ } var defaults = { - fill: "#000000", + fill: "#000", stroke: "none", "stroke-width": 1, "stroke-linecap": "butt", @@ -115,9 +115,10 @@ visibility: "visible" }; - function writeClassIfNeccessary(ctx) { - if (ctx.omStylesheet.hasStyleBlock(ctx.currentOMNode)) { - var omStyleBlock = ctx.omStylesheet.getStyleBlockForElement(ctx.currentOMNode); + function writeClassIfNeccessary(ctx, node) { + node = node || ctx.currentOMNode; + if (ctx.omStylesheet.hasStyleBlock(node)) { + var omStyleBlock = ctx.omStylesheet.getStyleBlockForElement(node); if (omStyleBlock) { if (ctx.usePresentationAttribute) { for (var i = 0, len = omStyleBlock.rules.length; i < len; i++) { @@ -292,71 +293,14 @@ break; case "tspan": { - write(ctx, ""); - if (omIn.children.length) { - for (var i = 0; i < omIn.children.length; i++) { - var childNode = omIn.children[i]; - ctx.currentOMNode = childNode; - writeSVGNode(ctx, i, omIn.children.length); - } + mergeTSpans(ctx, sibling, omIn.children); +// break; } + + if (omIn.text) { write(ctx, encodedText(omIn.text)); } @@ -595,6 +539,175 @@ return toString(ctx); } + function dealWithTSpan(ctx, sibling, omIn) { + write(ctx, ""); + } + + var mergeTSpans = (function () { + var matchAfterDash = /-.*$/, + matchAllSpaces = /\s/g + function iseq(name, val1, val2) { + if (name == "font-family") { + val1 = val1.replace(matchAfterDash, "").replace(matchAllSpaces, "").toLowerCase(); + val2 = val2.replace(matchAfterDash, "").replace(matchAllSpaces, "").toLowerCase(); + } + return val1 == val2; + } + function compareStyles(st1, st2) { + if (!st1) { + return; + } + var eq = 0, + s2 = {}; + for (i = 0, ii = st2.rules.length; i < ii; i++) { + s2[st2.rules[i].propertyName] = st2.rules[i].value; + } + for (var i = 0, ii = st1.rules.length; i < ii; i++) { + var prop = st1.rules[i].propertyName; + if (prop in s2) { + eq += iseq(prop, st1.rules[i].value, s2[prop]); + } else { + return; + } + } + return eq; + } + function simpleClone(o) { + var c = {}; + for (var prop in o) { + c[prop] = o[prop]; + } + return c; + } + function run(c, css) { + css = simpleClone(css); + for (var i = 0, len = c.length; i < len; i++) { + var style = c[i].style; + for (var j = 0; j < style.rules.length; j++) { + if (css[style.rules[j].propertyName] == style.rules[j].value) { + style.rules.splice(j, 1); + j--; + } else { + css[style.rules[j].propertyName] = style.rules[j].value; + } + } + style.fingerprint = JSON.stringify(style.rules); + if (c[i].children && c[i].children.length) { + run(c[i].children, css); + } + } + } + return function mergeTSpans(ctx, sibling, tspans) { + var str = "", + opened = [], + styles = [], + curstyle = styles; + for (var i = 0, len = tspans.length; i < len; i++) { + var j = opened.length, + compres = {match: -1}, + match; + while (j--) { + match = compareStyles(opened[j], tspans[i].styleBlock); + if (match > compres.match) { + compres = { + match: match, + full: match == tspans[i].styleBlock.rules.length, + style: opened[j], + j: j + }; + } + } + if (compres) { + var todel = opened.splice(compres.j + 1); + for (var k = 0; k < todel.length; k++) { + curstyle = curstyle.parent; + } + write(ctx, new Array(todel.length + 1).join("")); + if (compres.full) { + if (tspans[i].text) { + write(ctx, encodedText(tspans[i].text)); + } + continue; + } + } else { + write(ctx, new Array(opened.length + 1).join("")); + opened.length = 0; + } + var chldrn = []; + curstyle.push({ + style: tspans[i].styleBlock, + children: chldrn, + parent: curstyle + }); + chldrn.parent = curstyle; + curstyle = chldrn; + dealWithTSpan(ctx, sibling, tspans[i]); + if (tspans[i].text) { + write(ctx, encodedText(tspans[i].text)); + } + opened.push(tspans[i].styleBlock); + } + write(ctx, new Array(opened.length + 1).join("")); + run(styles, {}); + return str; + }; + }()); module.exports.printSVG = print; }()); diff --git a/tests/data/svgText.svg b/tests/data/svgText.svg index 0464a78..66ee01f 100644 --- a/tests/data/svgText.svg +++ b/tests/data/svgText.svg @@ -40,7 +40,7 @@ This is a text example - This is a text example - This is a text example - This isa textexample + This is a text example + This is a text example + This isa textexample diff --git a/tests/data/svgTextFx.svg b/tests/data/svgTextFx.svg index 3ec06b2..ff69aea 100644 --- a/tests/data/svgTextFx.svg +++ b/tests/data/svgTextFx.svg @@ -34,5 +34,5 @@ - This is a text + This is a text