svg2pdf.js
Advanced tools
Comparing version 0.9.0 to 0.10.0
{ | ||
"name": "svg2pdf.js", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"description": "A javascript-only SVG to PDF conversion utility that runs in the browser leveraging jsPDF", | ||
@@ -25,5 +25,4 @@ "main": "svg2pdf.js", | ||
"dependencies": { | ||
"jspdf": "git+https://github.com/yWorks/jsPDF.git#1.1.345", | ||
"jquery": ">=2.1.4" | ||
"jspdf": "git+https://github.com/yWorks/jsPDF.git#1.1.350" | ||
} | ||
} |
@@ -5,6 +5,34 @@ # svg2pdf.js | ||
## Installation | ||
If you have cloned this repository via | ||
```bash | ||
git clone https://github.com/yWorks/svg2pdf.js.git | ||
``` | ||
run | ||
```bash | ||
bower install | ||
``` | ||
or | ||
```bash | ||
npm install | ||
``` | ||
to install all dependencies. | ||
If you're only interested in the complete package, run | ||
```bash | ||
bower install svg2pdf.js | ||
``` | ||
or | ||
```bash | ||
npm install svg2pdf.js | ||
``` | ||
## Usage | ||
@@ -31,5 +59,3 @@ ```javascript | ||
* [jsPDF](https://github.com/yWorks/jsPDF) (yWorks fork version!) | ||
* [jQuery](https://jquery.org/) | ||
## License | ||
@@ -36,0 +62,0 @@ |
459
svg2pdf.js
@@ -35,3 +35,3 @@ /* | ||
*/ | ||
var svgElementToPdf = (function () { | ||
var svgElementToPdf = (function (global) { | ||
@@ -115,2 +115,21 @@ var _pdf; // jsPDF pdf-document | ||
var nodeIs = function (node, tagsString) { | ||
return tagsString.indexOf(node.tagName.toLowerCase()) >= 0; | ||
}; | ||
var forEachChild = function (node, fn) { | ||
// copy list of children, as the original might be modified | ||
var children = []; | ||
for (var i = 0; i < node.children.length; i++) { | ||
children.push(node.children[i]); | ||
} | ||
for (i = 0; i < children.length; i++) { | ||
fn(i, children[i]); | ||
} | ||
}; | ||
var getAngle = function (from, to) { | ||
return Math.atan2(to[1] - from[1], to[0] - from[0]); | ||
}; | ||
// mirrors p1 at p2 | ||
@@ -185,8 +204,8 @@ var mirrorPoint = function (p1, p2) { | ||
var nodeTransform = _pdf.unitMatrix; | ||
if (node.is("svg,g")) { | ||
x = parseFloat(node.attr("x")) || 0; | ||
y = parseFloat(node.attr("y")) || 0; | ||
if (nodeIs(node, "svg,g")) { | ||
x = parseFloat(node.getAttribute("x")) || 0; | ||
y = parseFloat(node.getAttribute("y")) || 0; | ||
// jquery doesn't like camelCase notation... | ||
viewBox = node.get(0).getAttribute("viewBox"); | ||
viewBox = node.getAttribute("viewBox"); | ||
if (viewBox) { | ||
@@ -196,4 +215,4 @@ bounds = parseFloats(viewBox); | ||
viewBoxHeight = bounds[3] - bounds[1]; | ||
width = parseFloat(node.attr("width")) || viewBoxWidth; | ||
height = parseFloat(node.attr("height")) || viewBoxHeight; | ||
width = parseFloat(node.getAttribute("width")) || viewBoxWidth; | ||
height = parseFloat(node.getAttribute("height")) || viewBoxHeight; | ||
nodeTransform = new _pdf.Matrix(width / viewBoxWidth, 0, 0, height / viewBoxHeight, x - bounds[0], y - bounds[1]); | ||
@@ -203,7 +222,7 @@ } else { | ||
} | ||
} else if (node.is("marker")) { | ||
x = -parseFloat(node.get(0).getAttribute("refX")) || 0; | ||
y = -parseFloat(node.get(0).getAttribute("refY")) || 0; | ||
} else if (nodeIs(node, "marker")) { | ||
x = -parseFloat(node.getAttribute("refX")) || 0; | ||
y = -parseFloat(node.getAttribute("refY")) || 0; | ||
viewBox = node.get(0).getAttribute("viewBox"); | ||
viewBox = node.getAttribute("viewBox"); | ||
if (viewBox) { | ||
@@ -213,7 +232,7 @@ bounds = parseFloats(viewBox); | ||
viewBoxHeight = bounds[3] - bounds[1]; | ||
width = parseFloat(node.get(0).getAttribute("markerWidth")) || viewBoxWidth; | ||
height = parseFloat(node.get(0).getAttribute("markerHeight")) || viewBoxHeight; | ||
width = parseFloat(node.getAttribute("markerWidth")) || viewBoxWidth; | ||
height = parseFloat(node.getAttribute("markerHeight")) || viewBoxHeight; | ||
var s = new _pdf.Matrix(width / viewBoxWidth, 0, 0, height / viewBoxHeight, 0, 0); | ||
var t = new _pdf.Matrix(1, 0, 0, 1, x - bounds[0], y - bounds[1]); | ||
var t = new _pdf.Matrix(1, 0, 0, 1, x, y); | ||
nodeTransform = _pdf.matrixMult(t, s); | ||
@@ -225,3 +244,3 @@ } else { | ||
var transformString = node.attr("transform"); | ||
var transformString = node.getAttribute("transform"); | ||
if (!transformString) | ||
@@ -326,6 +345,7 @@ return nodeTransform; | ||
var getUntransformedBBox = function (node) { | ||
var i, minX, minY, maxX, maxY, viewBox, vb; | ||
var i, minX, minY, maxX, maxY, viewBox, vb, boundingBox; | ||
var pf = parseFloat; | ||
if (node.is("polygon")) { | ||
var points = parsePointsString(node.attr("points")); | ||
if (nodeIs(node, "polygon")) { | ||
var points = parsePointsString(node.getAttribute("points")); | ||
minX = Number.POSITIVE_INFINITY; | ||
@@ -342,3 +362,3 @@ minY = Number.POSITIVE_INFINITY; | ||
} | ||
return [ | ||
boundingBox = [ | ||
minX, | ||
@@ -349,6 +369,4 @@ minY, | ||
]; | ||
} | ||
if (node.is("path")) { | ||
var list = getPathSegList(node.get(0)); | ||
} else if (nodeIs(node, "path")) { | ||
var list = getPathSegList(node); | ||
minX = Number.POSITIVE_INFINITY; | ||
@@ -359,3 +377,3 @@ minY = Number.POSITIVE_INFINITY; | ||
var x = 0, y = 0; | ||
var prevX, prevY; | ||
var prevX, prevY, newX, newY; | ||
var p2, p3, to; | ||
@@ -367,12 +385,16 @@ for (i = 0; i < list.numberOfItems; i++) { | ||
case "H": | ||
x = seg.x; | ||
newX = seg.x; | ||
newY = y; | ||
break; | ||
case "h": | ||
x = seg.x + x; | ||
newX = seg.x + x; | ||
newY = y; | ||
break; | ||
case "V": | ||
y = seg.y; | ||
newX = x; | ||
newY = seg.y; | ||
break; | ||
case "v": | ||
y = seg.y + y; | ||
newX = x; | ||
newY = seg.y + y; | ||
break; | ||
@@ -435,2 +457,5 @@ case "C": | ||
y = seg.y + y; | ||
} else if ("zZ".indexOf(cmd) < 0) { | ||
x = newX; | ||
y = newY; | ||
} | ||
@@ -449,3 +474,3 @@ if ("CSQTcsqt".indexOf(cmd) >= 0) { | ||
} | ||
return [ | ||
boundingBox = [ | ||
minX, | ||
@@ -456,7 +481,4 @@ minY, | ||
]; | ||
} | ||
var pf = parseFloat; | ||
if (node.is("svg")) { | ||
viewBox = node.get(0).getAttribute("viewBox"); | ||
} else if (nodeIs(node, "svg")) { | ||
viewBox = node.getAttribute("viewBox"); | ||
if (viewBox) { | ||
@@ -466,10 +488,9 @@ vb = parseFloats(viewBox); | ||
return [ | ||
pf(node.attr("x")) || (vb && vb[0]) || 0, | ||
pf(node.attr("y")) || (vb && vb[1]) || 0, | ||
pf(node.attr("width")) || (vb && vb[2]) || 0, | ||
pf(node.attr("height")) || (vb && vb[3]) || 0 | ||
pf(node.getAttribute("x")) || (vb && vb[0]) || 0, | ||
pf(node.getAttribute("y")) || (vb && vb[1]) || 0, | ||
pf(node.getAttribute("width")) || (vb && vb[2]) || 0, | ||
pf(node.getAttribute("height")) || (vb && vb[3]) || 0 | ||
]; | ||
} | ||
if (node.is("marker")) { | ||
viewBox = node.get(0).getAttribute("viewBox"); | ||
} else if (nodeIs(node, "marker")) { | ||
viewBox = node.getAttribute("viewBox"); | ||
if (viewBox) { | ||
@@ -481,18 +502,34 @@ vb = parseFloats(viewBox); | ||
(vb && vb[1]) || 0, | ||
(vb && vb[2]) || pf(node.attr("marker-width")) || 0, | ||
(vb && vb[3]) || pf(node.attr("marker-height")) || 0 | ||
(vb && vb[2]) || pf(node.getAttribute("marker-width")) || 0, | ||
(vb && vb[3]) || pf(node.getAttribute("marker-height")) || 0 | ||
]; | ||
} else { | ||
// TODO: check if there are other possible coordinate attributes | ||
var x1 = pf(node.getAttribute("x1")) || pf(node.getAttribute("x")) || pf((node.getAttribute("cx")) - pf(node.getAttribute("r"))) || 0; | ||
var x2 = pf(node.getAttribute("x2")) || (x1 + pf(node.getAttribute("width"))) || (pf(node.getAttribute("cx")) + pf(node.getAttribute("r"))) || 0; | ||
var y1 = pf(node.getAttribute("y1")) || pf(node.getAttribute("y")) || (pf(node.getAttribute("cy")) - pf(node.getAttribute("r"))) || 0; | ||
var y2 = pf(node.getAttribute("y2")) || (y1 + pf(node.getAttribute("height"))) || (pf(node.getAttribute("cy")) + pf(node.getAttribute("r"))) || 0; | ||
boundingBox = [ | ||
Math.min(x1, x2), | ||
Math.min(y1, y2), | ||
Math.max(x1, x2) - Math.min(x1, x2), | ||
Math.max(y1, y2) - Math.min(y1, y2) | ||
]; | ||
} | ||
// TODO: check if there are other possible coordinate attributes | ||
var x1 = pf(node.attr("x1")) || pf(node.attr("x")) || pf((node.attr("cx")) - pf(node.attr("r"))) || 0; | ||
var x2 = pf(node.attr("x2")) || (x1 + pf(node.attr("width"))) || (pf(node.attr("cx")) + pf(node.attr("r"))) || 0; | ||
var y1 = pf(node.attr("y1")) || pf(node.attr("y")) || (pf(node.attr("cy")) - pf(node.attr("r"))) || 0; | ||
var y2 = pf(node.attr("y2")) || (y1 + pf(node.attr("height"))) || (pf(node.attr("cy")) + pf(node.attr("r"))) || 0; | ||
return [ | ||
Math.min(x1, x2), | ||
Math.min(y1, y2), | ||
Math.max(x1, x2) - Math.min(x1, x2), | ||
Math.max(y1, y2) - Math.min(y1, y2) | ||
]; | ||
if (!nodeIs(node, "marker,svg,g")) { | ||
// add line-width | ||
var lineWidth = getAttribute(node, "stroke-width") || 1; | ||
var miterLimit = getAttribute(node, "stroke-miterlimit"); | ||
// miterLength / lineWidth = 1 / sin(phi / 2) | ||
miterLimit && (lineWidth *= 0.5 / (Math.sin(Math.PI / 12))); | ||
return [ | ||
boundingBox[0] - lineWidth, | ||
boundingBox[1] - lineWidth, | ||
boundingBox[2] + 2 * lineWidth, | ||
boundingBox[3] + 2 * lineWidth | ||
]; | ||
} | ||
return boundingBox; | ||
}; | ||
@@ -521,4 +558,4 @@ | ||
// draws a polygon | ||
var polygon = function (n, tfMatrix, colorMode, gradient, gradientMatrix) { | ||
var points = parsePointsString(n.attr("points")); | ||
var polygon = function (node, tfMatrix, colorMode, gradient, gradientMatrix) { | ||
var points = parsePointsString(node.getAttribute("points")); | ||
var lines = [{op: "m", c: multVecMatrix(points[0], tfMatrix)}]; | ||
@@ -535,5 +572,5 @@ for (var i = 1; i < points.length; i++) { | ||
// draws an image (converts it to jpeg first, as jsPDF doesn't support png or other formats) | ||
var image = function (n) { | ||
var image = function (node) { | ||
// convert image to jpeg | ||
var imageUrl = n.attr("xlink:href") || n.attr("href"); | ||
var imageUrl = node.getAttribute("xlink:href") || node.getAttribute("href"); | ||
var image = new Image(); | ||
@@ -543,4 +580,4 @@ image.src = imageUrl; | ||
var canvas = document.createElement("canvas"); | ||
var width = parseFloat(n.attr("width")), | ||
height = parseFloat(n.attr("height")); | ||
var width = parseFloat(node.getAttribute("width")), | ||
height = parseFloat(node.getAttribute("height")); | ||
canvas.width = width; | ||
@@ -564,4 +601,7 @@ canvas.height = height; | ||
// draws a path | ||
var path = function (n, node, tfMatrix, svgIdPrefix, colorMode, gradient, gradientMatrix) { | ||
var path = function (node, tfMatrix, svgIdPrefix, colorMode, gradient, gradientMatrix) { | ||
var list = getPathSegList(node); | ||
var markerEnd = node.getAttribute("marker-end"), | ||
markerStart = node.getAttribute("marker-start"), | ||
markerMid = node.getAttribute("marker-mid"); | ||
@@ -571,8 +611,17 @@ var getLinesFromPath = function (pathSegList, tfMatrix) { | ||
var x0 = x, y0 = y; | ||
var prevX, prevY; | ||
var from, to, p2, p3; | ||
var prevX, prevY, newX, newY; | ||
var to, p, p2, p3; | ||
var lines = []; | ||
var markers = []; | ||
var op; | ||
var prevAngle = 0, curAngle; | ||
var addMarker = function (angle, anchor, type) { | ||
var cos = Math.cos(angle); | ||
var sin = Math.sin(angle); | ||
var tf; | ||
tf = new _pdf.Matrix(cos, sin, -sin, cos, anchor[0], anchor[1]); | ||
markers.push({type: type, tf: _pdf.matrixMult(tf, tfMatrix)}); | ||
}; | ||
for (var i = 0; i < list.numberOfItems; i++) { | ||
@@ -605,3 +654,4 @@ var seg = list.getItem(i); | ||
op = "l"; | ||
x = seg.x; | ||
newX = seg.x; | ||
newY = y; | ||
break; | ||
@@ -611,3 +661,4 @@ case "h": | ||
op = "l"; | ||
x = seg.x + x; | ||
newX = seg.x + x; | ||
newY = y; | ||
break; | ||
@@ -617,3 +668,4 @@ case "V": | ||
op = "l"; | ||
y = seg.y; | ||
newX = x; | ||
newY = seg.y; | ||
break; | ||
@@ -623,3 +675,4 @@ case "v": | ||
op = "l"; | ||
y = seg.y + y; | ||
newX = x; | ||
newY = seg.y + y; | ||
break; | ||
@@ -679,4 +732,24 @@ case "C": | ||
var hasStartMarker = markerStart | ||
&& (i === 1 | ||
|| ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0)); | ||
var hasEndMarker = markerEnd | ||
&& (i === list.numberOfItems - 1 | ||
|| ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i + 1).pathSegTypeAsLetter) >= 0)); | ||
var hasMidMarker = markerMid | ||
&& i > 0 | ||
&& !(i === 1 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0); | ||
if ("sScCqQtT".indexOf(cmd) >= 0) { | ||
from = p3; | ||
hasStartMarker && addMarker(getAngle([x, y], p2), [x, y], "start"); | ||
hasEndMarker && addMarker(getAngle(p3, to), to, "end"); | ||
if (hasMidMarker) { | ||
curAngle = getAngle([x, y], p2); | ||
curAngle = "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? | ||
curAngle : .5 * (prevAngle + curAngle); | ||
addMarker(curAngle, [x, y], "mid"); | ||
} | ||
prevAngle = getAngle(p3, to); | ||
prevX = x; | ||
@@ -695,3 +768,13 @@ prevY = y; | ||
} else if ("lLhHvVmM".indexOf(cmd) >= 0) { | ||
from = [x, y]; | ||
curAngle = getAngle([x, y], to); | ||
hasStartMarker && addMarker(curAngle, [x, y], "start"); | ||
hasEndMarker && addMarker(curAngle, to, "end"); | ||
if (hasMidMarker) { | ||
var angle = "mM".indexOf(cmd) >= 0 ? | ||
prevAngle : "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? | ||
curAngle : .5 * (prevAngle + curAngle); | ||
addMarker(angle, [x, y], "mid"); | ||
} | ||
prevAngle = curAngle; | ||
p = multVecMatrix(to, tfMatrix); | ||
@@ -701,9 +784,2 @@ lines.push({op: op, c: p}); | ||
if (i === list.numberOfItems - 1 | ||
|| ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i + 1).pathSegTypeAsLetter) >= 0)) { | ||
var a = Math.atan2(to[1] - from[1], to[0] - from[0]); | ||
var tf = new _pdf.Matrix(Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), to[0], to[1]); | ||
markers.push({type: "end", tf: _pdf.matrixMult(tf, tfMatrix)}); | ||
} | ||
if ("MLCSQT".indexOf(cmd) >= 0) { | ||
@@ -715,2 +791,5 @@ x = seg.x; | ||
y = seg.y + y; | ||
} else if ("zZ".indexOf(cmd) < 0) { | ||
x = newX; | ||
y = newY; | ||
} | ||
@@ -723,4 +802,3 @@ } | ||
var markerEnd = n.attr("marker-end"); | ||
if (markerEnd) { | ||
if (markerEnd || markerStart || markerMid) { | ||
for (var i = 0; i < lines.markers.length; i++) { | ||
@@ -730,4 +808,11 @@ var marker = lines.markers[i]; | ||
switch (marker.type) { | ||
case "start": | ||
markerElement = svgIdPrefix.get() + /url\(#(\w+)\)/.exec(markerStart)[1]; | ||
break; | ||
case "end": | ||
markerElement = svgIdPrefix.get() + /url\(#(\w+)\)/.exec(markerEnd)[1]; | ||
break; | ||
case "mid": | ||
markerElement = svgIdPrefix.get() + /url\(#(\w+)\)/.exec(markerMid)[1]; | ||
break; | ||
} | ||
@@ -745,4 +830,4 @@ _pdf.doFormObject(markerElement, marker.tf); | ||
// to the pdf document. This highly reduces the file size and computation time. | ||
var use = function (n, tfMatrix, svgIdPrefix) { | ||
var url = (n.attr("href") || n.attr("xlink:href")); | ||
var use = function (node, tfMatrix, svgIdPrefix) { | ||
var url = (node.getAttribute("href") || node.getAttribute("xlink:href")); | ||
// just in case someone has the idea to use empty use-tags, wtf??? | ||
@@ -752,14 +837,11 @@ if (!url) | ||
// get the size of the referenced form object (to apply the correct saling) | ||
// get the size of the referenced form object (to apply the correct scaling) | ||
var formObject = _pdf.getFormObject(svgIdPrefix.get() + url.substring(1)); | ||
// scale and position it right | ||
var x = n.attr("x") || 0; | ||
var y = n.attr("y") || 0; | ||
var width = n.attr("width") || formObject.width; | ||
var height = n.attr("height") || formObject.height; | ||
var t = _pdf.unitMatrix; | ||
if (width > 0 && height > 0) { | ||
t = new _pdf.Matrix(width / formObject.width, 0, 0, height / formObject.height, x, y); | ||
} | ||
var x = node.getAttribute("x") || 0; | ||
var y = node.getAttribute("y") || 0; | ||
var width = node.getAttribute("width") || formObject.width; | ||
var height = node.getAttribute("height") || formObject.height; | ||
var t = new _pdf.Matrix(width / formObject.width || 0, 0, 0, height / formObject.height || 0, x, y); | ||
t = _pdf.matrixMult(t, tfMatrix); | ||
@@ -770,5 +852,5 @@ _pdf.doFormObject(svgIdPrefix.get() + url.substring(1), t); | ||
// draws a line | ||
var line = function (n, tfMatrix) { | ||
var p1 = multVecMatrix([parseFloat(n.attr('x1')), parseFloat(n.attr('y1'))], tfMatrix); | ||
var p2 = multVecMatrix([parseFloat(n.attr('x2')), parseFloat(n.attr('y2'))], tfMatrix); | ||
var line = function (node, tfMatrix) { | ||
var p1 = multVecMatrix([parseFloat(node.getAttribute('x1')), parseFloat(node.getAttribute('y1'))], tfMatrix); | ||
var p2 = multVecMatrix([parseFloat(node.getAttribute('x2')), parseFloat(node.getAttribute('y2'))], tfMatrix); | ||
_pdf.line(p1[0], p1[1], p2[0], p2[1]); | ||
@@ -778,10 +860,10 @@ }; | ||
// draws a rect | ||
var rect = function (n, colorMode, gradient, gradientMatrix) { | ||
var rect = function (node, colorMode, gradient, gradientMatrix) { | ||
_pdf.roundedRect( | ||
parseFloat(n.attr('x')) || 0, | ||
parseFloat(n.attr('y')) || 0, | ||
parseFloat(n.attr('width')), | ||
parseFloat(n.attr('height')), | ||
parseFloat(n.attr('rx')) || 0, | ||
parseFloat(n.attr('ry')) || 0, | ||
parseFloat(node.getAttribute('x')) || 0, | ||
parseFloat(node.getAttribute('y')) || 0, | ||
parseFloat(node.getAttribute('width')), | ||
parseFloat(node.getAttribute('height')), | ||
parseFloat(node.getAttribute('rx')) || 0, | ||
parseFloat(node.getAttribute('ry')) || 0, | ||
colorMode, | ||
@@ -794,8 +876,8 @@ gradient, | ||
// draws an ellipse | ||
var ellipse = function (n, colorMode, gradient, gradientMatrix) { | ||
var ellipse = function (node, colorMode, gradient, gradientMatrix) { | ||
_pdf.ellipse( | ||
parseFloat(n.attr('cx')) || 0, | ||
parseFloat(n.attr('cy')) || 0, | ||
parseFloat(n.attr('rx')), | ||
parseFloat(n.attr('ry')), | ||
parseFloat(node.getAttribute('cx')) || 0, | ||
parseFloat(node.getAttribute('cy')) || 0, | ||
parseFloat(node.getAttribute('rx')), | ||
parseFloat(node.getAttribute('ry')), | ||
colorMode, | ||
@@ -808,7 +890,7 @@ gradient, | ||
// draws a circle | ||
var circle = function (n, colorMode, gradient, gradientMatrix) { | ||
var radius = parseFloat(n.attr('r')) || 0; | ||
var circle = function (node, colorMode, gradient, gradientMatrix) { | ||
var radius = parseFloat(node.getAttribute('r')) || 0; | ||
_pdf.ellipse( | ||
parseFloat(n.attr('cx')) || 0, | ||
parseFloat(n.attr('cy')) || 0, | ||
parseFloat(node.getAttribute('cx')) || 0, | ||
parseFloat(node.getAttribute('cy')) || 0, | ||
radius, | ||
@@ -823,16 +905,6 @@ radius, | ||
// draws a text element and its tspan children | ||
var text = function (n, node, tfMatrix, hasFillColor, fillRGB) { | ||
var text = function (node, tfMatrix, hasFillColor, fillRGB) { | ||
var fontFamily = getAttribute(node, "font-family"); | ||
if (fontFamily) { | ||
switch (fontFamily.toLowerCase()) { | ||
case 'serif': | ||
_pdf.setFont('times'); | ||
break; | ||
case 'monospace': | ||
_pdf.setFont('courier'); | ||
break; | ||
default: | ||
_pdf.setFont('helvetica'); | ||
break; | ||
} | ||
_pdf.setFont(fontFamily); | ||
} | ||
@@ -896,7 +968,7 @@ | ||
tfMatrix.a, tfMatrix.b, tfMatrix.c, tfMatrix.d, | ||
tfMatrix.e + (parseFloat(n.attr('x')) || 0), | ||
tfMatrix.f + (parseFloat(n.attr('y')) || 0) | ||
tfMatrix.e + (parseFloat(node.getAttribute('x')) || 0), | ||
tfMatrix.f + (parseFloat(node.getAttribute('y')) || 0) | ||
); | ||
x = (parseFloat(n.attr("dx")) || 0) * pdfFontSize; | ||
y = (parseFloat(n.attr("dy")) || 0) * pdfFontSize; | ||
x = (parseFloat(node.getAttribute("dx")) || 0) * pdfFontSize; | ||
y = (parseFloat(node.getAttribute("dy")) || 0) * pdfFontSize; | ||
_pdf.setFontSize(pdfFontSize); | ||
@@ -909,3 +981,3 @@ | ||
y, | ||
removeNewlinesAndTrim(n.text()), | ||
removeNewlinesAndTrim(node.textContent), | ||
void 0, | ||
@@ -916,11 +988,9 @@ m | ||
// otherwise loop over tspans and position each relative to the previous one | ||
n.children().each(function (i, tSpan) { | ||
forEachChild(node, function (i, tSpan) { | ||
var xOffset = getTextOffset(textAnchor, tSpan.getComputedTextLength()); | ||
var s = $(tSpan); | ||
x += (parseFloat(s.attr("dx")) || 0) * pdfFontSize; | ||
y += (parseFloat(s.attr("dy")) || 0) * pdfFontSize; | ||
y += (parseFloat(tSpan.getAttribute("dy")) || 0) * pdfFontSize; | ||
_pdf.text( | ||
x - xOffset, | ||
y, | ||
removeNewlinesAndTrim(s.text()), | ||
removeNewlinesAndTrim(tSpan.textContent), | ||
void 0, | ||
@@ -936,4 +1006,4 @@ m | ||
// As defs elements are allowed to appear after they are referenced, we search for them at first | ||
var findAndRenderDefs = function (n, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
n.children().each(function (i, child) { | ||
var findAndRenderDefs = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
forEachChild(node, function (i, child) { | ||
if (child.tagName.toLowerCase() === "defs") { | ||
@@ -948,13 +1018,13 @@ renderNode(child, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
// processes a svg node | ||
var svg = function (n, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
var svg = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
// create a new prefix and clone the defs, as defs within the svg should not be visible outside | ||
var newSvgIdPrefix = svgIdPrefix.nextChild(); | ||
var newDefs = cloneDefs(defs); | ||
findAndRenderDefs(n, tfMatrix, newDefs, newSvgIdPrefix, withinDefs); | ||
renderChildren(n, tfMatrix, newDefs, newSvgIdPrefix, withinDefs); | ||
findAndRenderDefs(node, tfMatrix, newDefs, newSvgIdPrefix, withinDefs); | ||
renderChildren(node, tfMatrix, newDefs, newSvgIdPrefix, withinDefs); | ||
}; | ||
// renders all children of a node | ||
var renderChildren = function (n, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
n.children().each(function (i, node) { | ||
var renderChildren = function (node, tfMatrix, defs, svgIdPrefix, withinDefs) { | ||
forEachChild(node, function (i, node) { | ||
renderNode(node, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
@@ -967,3 +1037,3 @@ }); | ||
// transforms are applied on use | ||
var putGradient = function (n, node, type, coords, defs, svgIdPrefix) { | ||
var putGradient = function (node, type, coords, defs, svgIdPrefix) { | ||
var colors = []; | ||
@@ -973,9 +1043,8 @@ var opacitySum = 0; | ||
var gState; | ||
n.children().each(function (i, element) { | ||
forEachChild(node, function (i, element) { | ||
// since opacity gradients are hard to realize, avarage the opacity over the control points | ||
if (element.tagName.toLowerCase() === "stop") { | ||
var e = $(element); | ||
var color = new RGBColor(getAttribute(element, "stop-color")); | ||
colors.push({ | ||
offset: parseFloat(e.attr("offset")), | ||
offset: parseFloat(element.getAttribute("offset")), | ||
color: [color.r, color.g, color.b] | ||
@@ -996,3 +1065,3 @@ }); | ||
var pattern = new _pdf.Pattern(type, coords, colors, gState); | ||
var id = svgIdPrefix.get() + n.attr("id"); | ||
var id = svgIdPrefix.get() + node.getAttribute("id"); | ||
_pdf.addPattern(id, pattern); | ||
@@ -1012,6 +1081,2 @@ defs[id] = node; | ||
var renderNode = function (node, contextTransform, defs, svgIdPrefix, withinDefs) { | ||
var n = $(node); // jquery node for comfort | ||
var tfMatrix, | ||
@@ -1031,8 +1096,8 @@ hasFillColor = false, | ||
// of the top-level page | ||
var targetIsFormObject = withinDefs && "lineargradient,radialgradient".indexOf(node.tagName.toLowerCase()) < 0; | ||
var targetIsFormObject = withinDefs && !nodeIs(node, "lineargradient,radialgradient"); | ||
if (targetIsFormObject) { | ||
// the transformations directly at the node are written to the pdf form object transformation matrix | ||
tfMatrix = computeNodeTransform(n); | ||
bBox = getUntransformedBBox(n); | ||
tfMatrix = computeNodeTransform(node); | ||
bBox = getUntransformedBBox(node); | ||
@@ -1046,3 +1111,3 @@ _pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix); | ||
} else { | ||
tfMatrix = _pdf.matrixMult(computeNodeTransform(n), contextTransform); | ||
tfMatrix = _pdf.matrixMult(computeNodeTransform(node), contextTransform); | ||
_pdf.saveGraphicsState(); | ||
@@ -1056,4 +1121,4 @@ } | ||
// fill mode | ||
if (n.is('g,path,rect,text,ellipse,line,circle,polygon')) { | ||
var fillColor = n.attr('fill'); | ||
if (nodeIs(node, "g,path,rect,text,ellipse,line,circle,polygon")) { | ||
var fillColor = node.getAttribute("fill"); | ||
if (fillColor) { | ||
@@ -1065,3 +1130,3 @@ var url = /url\(#(\w+)\)/.exec(fillColor); | ||
var fill = getFromDefs(gradient, defs); | ||
if ("lineargradient,radialgradient".indexOf(fill.tagName.toLowerCase()) >= 0) { | ||
if (nodeIs(fill, "lineargradient,radialgradient")) { | ||
@@ -1074,6 +1139,6 @@ // matrix to convert between gradient space and user space | ||
|| fill.getAttribute("gradientUnits").toLowerCase() === "objectboundingbox") { | ||
bBox = getUntransformedBBox(n); | ||
bBox = getUntransformedBBox(node); | ||
gradientUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]); | ||
var nodeTransform = computeNodeTransform(n); | ||
var nodeTransform = computeNodeTransform(node); | ||
gradientUnitsMatrix = _pdf.matrixMult(gradientUnitsMatrix, nodeTransform); | ||
@@ -1105,3 +1170,3 @@ } | ||
// opacity is realized via a pdf graphics state | ||
var opacity = n.attr("opacity") || n.attr("fill-opacity"); | ||
var opacity = node.getAttribute("opacity") || node.getAttribute("fill-opacity"); | ||
if (opacity) { | ||
@@ -1114,3 +1179,3 @@ _pdf.setGState(new _pdf.GState({opacity: parseFloat(opacity)})); | ||
if (n.is('g,path,rect,ellipse,line,circle,polygon')) { | ||
if (nodeIs(node, "g,path,rect,ellipse,line,circle,polygon")) { | ||
// text has no fill color, so apply it not until here | ||
@@ -1122,6 +1187,6 @@ if (hasFillColor) { | ||
// stroke mode | ||
var strokeColor = n.attr('stroke'); | ||
var strokeColor = node.getAttribute('stroke'); | ||
if (strokeColor) { | ||
if (node.hasAttribute("stroke-width")) { | ||
_pdf.setLineWidth(Math.abs(parseFloat(n.attr('stroke-width')))); | ||
_pdf.setLineWidth(Math.abs(parseFloat(node.getAttribute('stroke-width')))); | ||
} | ||
@@ -1134,13 +1199,16 @@ var strokeRGB = new RGBColor(strokeColor); | ||
if (node.hasAttribute("stroke-linecap")) { | ||
_pdf.setLineCap(n.attr("stroke-linecap")); | ||
_pdf.setLineCap(node.getAttribute("stroke-linecap")); | ||
} | ||
if (node.hasAttribute("stroke-linejoin")) { | ||
_pdf.setLineJoin(n.attr("stroke-linejoin")); | ||
_pdf.setLineJoin(node.getAttribute("stroke-linejoin")); | ||
} | ||
if (node.hasAttribute("stroke-dasharray")) { | ||
_pdf.setLineDashPattern( | ||
parseFloats(n.attr("stroke-dasharray")), | ||
parseInt(n.attr("stroke-dashoffset")) || 0 | ||
parseFloats(node.getAttribute("stroke-dasharray")), | ||
parseInt(node.getAttribute("stroke-dashoffset")) || 0 | ||
); | ||
} | ||
if (node.hasAttribute("stroke-miterlimit")) { | ||
_pdf.setLineMiterLimit(parseFloat(node.getAttribute("stroke-miterlimit"))); | ||
} | ||
} | ||
@@ -1152,21 +1220,21 @@ } | ||
case 'svg': | ||
svg(n, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
svg(node, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
break; | ||
case 'g': | ||
findAndRenderDefs(n, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
findAndRenderDefs(node, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
case 'a': | ||
case "marker": | ||
renderChildren(n, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
renderChildren(node, tfMatrix, defs, svgIdPrefix, withinDefs); | ||
break; | ||
case 'defs': | ||
renderChildren(n, tfMatrix, defs, svgIdPrefix, true); | ||
renderChildren(node, tfMatrix, defs, svgIdPrefix, true); | ||
break; | ||
case 'use': | ||
use(n, tfMatrix, svgIdPrefix); | ||
use(node, tfMatrix, svgIdPrefix); | ||
break; | ||
case 'line': | ||
line(n, tfMatrix); | ||
line(node, tfMatrix); | ||
break; | ||
@@ -1176,3 +1244,3 @@ | ||
_pdf.setCurrentTransformationMatrix(tfMatrix); | ||
rect(n, colorMode, gradient, gradientMatrix); | ||
rect(node, colorMode, gradient, gradientMatrix); | ||
break; | ||
@@ -1182,3 +1250,3 @@ | ||
_pdf.setCurrentTransformationMatrix(tfMatrix); | ||
ellipse(n, colorMode, gradient, gradientMatrix); | ||
ellipse(node, colorMode, gradient, gradientMatrix); | ||
break; | ||
@@ -1188,14 +1256,14 @@ | ||
_pdf.setCurrentTransformationMatrix(tfMatrix); | ||
circle(n, colorMode, gradient, gradientMatrix); | ||
circle(node, colorMode, gradient, gradientMatrix); | ||
break; | ||
case 'text': | ||
text(n, node, tfMatrix, hasFillColor, fillRGB); | ||
text(node, tfMatrix, hasFillColor, fillRGB); | ||
break; | ||
case 'path': | ||
path(n, node, tfMatrix, svgIdPrefix, colorMode, gradient, gradientMatrix); | ||
path(node, tfMatrix, svgIdPrefix, colorMode, gradient, gradientMatrix); | ||
break; | ||
case 'polygon': | ||
polygon(n, tfMatrix, colorMode, gradient, gradientMatrix); | ||
polygon(node, tfMatrix, colorMode, gradient, gradientMatrix); | ||
break; | ||
@@ -1205,19 +1273,23 @@ | ||
_pdf.setCurrentTransformationMatrix(tfMatrix); | ||
image(n); | ||
image(node); | ||
break; | ||
case "lineargradient": | ||
putGradient(n, node, "axial", [n.attr("x1"), n.attr("y1"), n.attr("x2"), n.attr("y2")], defs, svgIdPrefix); | ||
putGradient(node, "axial", [ | ||
node.getAttribute("x1"), | ||
node.getAttribute("y1"), | ||
node.getAttribute("x2"), | ||
node.getAttribute("y2") | ||
], defs, svgIdPrefix); | ||
break; | ||
case "radialgradient": | ||
var coords = [ | ||
n.attr("fx") || n.attr("cx"), | ||
n.attr("fy") || n.attr("cy"), | ||
putGradient(node, "radial", [ | ||
node.getAttribute("fx") || node.getAttribute("cx"), | ||
node.getAttribute("fy") || node.getAttribute("cy"), | ||
0, | ||
n.attr("cx") || 0, | ||
n.attr("cy") || 0, | ||
n.attr("r") || 0 | ||
]; | ||
putGradient(n, node, "radial", coords, defs, svgIdPrefix); | ||
node.getAttribute("cx") || 0, | ||
node.getAttribute("cy") || 0, | ||
node.getAttribute("r") || 0 | ||
], defs, svgIdPrefix); | ||
break; | ||
@@ -1228,3 +1300,3 @@ } | ||
if (targetIsFormObject) { | ||
_pdf.endFormObject(svgIdPrefix.get() + n.attr("id")); | ||
_pdf.endFormObject(svgIdPrefix.get() + node.getAttribute("id")); | ||
} else { | ||
@@ -1236,3 +1308,3 @@ _pdf.restoreGraphicsState(); | ||
// the actual svgToPdf function (see above) | ||
return function (element, pdf, options) { | ||
var svg2pdf = function (element, pdf, options) { | ||
_pdf = pdf; | ||
@@ -1254,2 +1326,13 @@ | ||
}; | ||
})(); | ||
if (typeof define === 'function' && define.amd) { | ||
define("svg2pdf", function () { | ||
return svg2pdf; | ||
}); | ||
} else if (typeof module !== 'undefined' && module.exports) { | ||
module.exports = svg2pdf; | ||
} else { | ||
global.svg2pdf = svg2pdf; | ||
} | ||
return svg2pdf; | ||
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this)); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
56896
1
7
1451
81
- Removedjquery@>=2.1.4
- Removedjquery@3.7.1(transitive)
Updatedjspdf@git+https://github.com/yWorks/jsPDF.git#1.1.350