From 7db8cc9c369b3760d0170d380e58bfd6944a49ee Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Sat, 22 Sep 2018 11:59:34 +0800 Subject: [PATCH] - Fix: Ensure poly shape has a `points` attribute - Refactoring: Avoid building nested function upon each function call - Linting (ESLint): Coding standards --- dist/jspdf.plugin.svgToPdf.js | 48 ++++++++++++++++++-- editor/jspdf/jspdf.plugin.svgToPdf.js | 64 +++++++++++++-------------- 2 files changed, 76 insertions(+), 36 deletions(-) diff --git a/dist/jspdf.plugin.svgToPdf.js b/dist/jspdf.plugin.svgToPdf.js index 48e375e4..33134306 100644 --- a/dist/jspdf.plugin.svgToPdf.js +++ b/dist/jspdf.plugin.svgToPdf.js @@ -384,6 +384,8 @@ rect: ['x', 'y', 'width', 'height', 'stroke', 'fill', 'stroke-width'], ellipse: ['cx', 'cy', 'rx', 'ry', 'stroke', 'fill', 'stroke-width'], circle: ['cx', 'cy', 'r', 'stroke', 'fill', 'stroke-width'], + polygon: ['points', 'stroke', 'fill', 'stroke-width'], + // polyline attributes are the same as those of polygon text: ['x', 'y', 'font-size', 'font-family', 'text-anchor', 'font-weight', 'font-style', 'fill'] }; @@ -409,6 +411,33 @@ }); }; + var numRgx = /[+-]?(?:\d+\.\d*|\d+|\.\d+)(?:[eE][+-]?\d+)?/g; + var getLinesOptionsOfPoly = function getLinesOptionsOfPoly(node) { + var nums = node.getAttribute('points'); + nums = nums && nums.match(numRgx) || []; + if (nums && nums.length) { + nums = nums.map(Number); + if (nums.length % 2) { + nums.length--; + } + } + if (nums.length < 4) { + console.log('invalid points attribute:', node); + return; + } + + var _nums = nums, + _nums2 = slicedToArray(_nums, 2), + x = _nums2[0], + y = _nums2[1], + lines = []; + + for (var i = 2; i < nums.length; i += 2) { + lines.push([nums[i] - nums[i - 2], nums[i + 1] - nums[i - 1]]); + } + return { x: x, y: y, lines: lines }; + }; + var svgElementToPdf = function svgElementToPdf(element, pdf, options) { // pdf is a jsPDF object // console.log('options =', options); @@ -420,7 +449,7 @@ // let hasStrokeColor = false; var hasFillColor = false; var fillRGB = void 0; - if (nodeIs(node, ['g', 'line', 'rect', 'ellipse', 'circle', 'text'])) { + if (nodeIs(node, ['g', 'line', 'rect', 'ellipse', 'circle', 'polygon', 'polyline', 'text'])) { var fillColor = node.getAttribute('fill'); if (attributeIsNotEmpty(fillColor)) { fillRGB = new RGBColor(fillColor); @@ -432,7 +461,7 @@ } } } - if (nodeIs(node, ['g', 'line', 'rect', 'ellipse', 'circle'])) { + if (nodeIs(node, ['g', 'line', 'rect', 'ellipse', 'circle', 'polygon', 'polyline'])) { if (hasFillColor) { pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b); } @@ -448,14 +477,15 @@ if (colorMode === 'F') { colorMode = 'FD'; } else { - colorMode = null; + colorMode = 'S'; } } else { colorMode = null; } } } - switch (node.tagName.toLowerCase()) { + var tag = node.tagName.toLowerCase(); + switch (tag) { case 'svg': case 'a': case 'g': @@ -478,6 +508,16 @@ pdf.circle(k * parseInt(node.getAttribute('cx'), 10), k * parseInt(node.getAttribute('cy'), 10), k * parseInt(node.getAttribute('r'), 10), colorMode); removeAttributes(node, pdfSvgAttr.circle); break; + case 'polygon': + case 'polyline': + var linesOptions = getLinesOptionsOfPoly(node); + if (linesOptions) { + pdf.lines(linesOptions.lines, k * linesOptions.x, k * linesOptions.y, [k, k], colorMode, tag === 'polygon' // polygon is closed, polyline is not closed + ); + } + removeAttributes(node, pdfSvgAttr.polygon); + break; + // TODO: path case 'text': if (node.hasAttribute('font-family')) { switch ((node.getAttribute('font-family') || '').toLowerCase()) { diff --git a/editor/jspdf/jspdf.plugin.svgToPdf.js b/editor/jspdf/jspdf.plugin.svgToPdf.js index 1c0a7638..c608a77f 100644 --- a/editor/jspdf/jspdf.plugin.svgToPdf.js +++ b/editor/jspdf/jspdf.plugin.svgToPdf.js @@ -31,7 +31,7 @@ const pdfSvgAttr = { ellipse: ['cx', 'cy', 'rx', 'ry', 'stroke', 'fill', 'stroke-width'], circle: ['cx', 'cy', 'r', 'stroke', 'fill', 'stroke-width'], polygon: ['points', 'stroke', 'fill', 'stroke-width'], - //polyline attributes is same as polygon + // polyline attributes are the same as those of polygon text: ['x', 'y', 'font-size', 'font-family', 'text-anchor', 'font-weight', 'font-style', 'fill'] }; @@ -57,38 +57,38 @@ const removeAttributes = function (node, attributes) { }); }; +const numRgx = /[+-]?(?:\d+\.\d*|\d+|\.\d+)(?:[eE][+-]?\d+)?/g; +const getLinesOptionsOfPoly = function (node) { + let nums = node.getAttribute('points'); + nums = (nums && nums.match(numRgx)) || []; + if (nums && nums.length) { + nums = nums.map(Number); + if (nums.length % 2) { + nums.length--; + } + } + if (nums.length < 4) { + console.log('invalid points attribute:', node); + return; + } + const [x, y] = nums, lines = []; + for (let i = 2; i < nums.length; i += 2) { + lines.push([nums[i] - nums[i - 2], nums[i + 1] - nums[i - 1]]); + } + return {x, y, lines}; +}; + const svgElementToPdf = function (element, pdf, options) { // pdf is a jsPDF object // console.log('options =', options); const remove = (options.removeInvalid === undefined ? false : options.removeInvalid); const k = (options.scale === undefined ? 1.0 : options.scale); - const numRgx = /[+-]?(?:\d+\.\d*|\d+|\.\d+)(?:[eE][+-]?\d+)?/g; let colorMode = null; - let getLinesOptionsOfPoly = function (node) { - let nums = node.getAttribute('points'); - nums = nums.match(numRgx) || []; - if (nums && nums.length) { - nums = [].map.call(nums, Number); - if (nums.length % 2) { - nums.length -= 1; - } - } - if (nums.length < 4) { - console.log('invalid points attribute:', node); - return; - } - let x = nums[0], y = nums[1], lines = []; - for (let i = 2; i < nums.length; i += 2) { - lines.push([nums[i] - nums[i - 2], nums[i + 1] - nums[i - 1]]); - } - return {x, y, lines}; - }; [].forEach.call(element.children, function (node) { // console.log('passing: ', node); // let hasStrokeColor = false; let hasFillColor = false; let fillRGB; - let linesOptions; if (nodeIs(node, ['g', 'line', 'rect', 'ellipse', 'circle', 'polygon', 'polyline', 'text'])) { const fillColor = node.getAttribute('fill'); if (attributeIsNotEmpty(fillColor)) { @@ -124,7 +124,7 @@ const svgElementToPdf = function (element, pdf, options) { } } } - let tag = node.tagName.toLowerCase(); + const tag = node.tagName.toLowerCase(); switch (tag) { case 'svg': case 'a': @@ -172,16 +172,16 @@ const svgElementToPdf = function (element, pdf, options) { break; case 'polygon': case 'polyline': - linesOptions = getLinesOptionsOfPoly(node); + const linesOptions = getLinesOptionsOfPoly(node); if (linesOptions) { - pdf.lines( - linesOptions.lines, - k * linesOptions.x, - k * linesOptions.y, - [k, k], - colorMode, - tag === 'polygon' //polygon is closed, polyline is not closed - ); + pdf.lines( + linesOptions.lines, + k * linesOptions.x, + k * linesOptions.y, + [k, k], + colorMode, + tag === 'polygon' // polygon is closed, polyline is not closed + ); } removeAttributes(node, pdfSvgAttr.polygon); break;