Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better SVG handling #2228

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
24 changes: 22 additions & 2 deletions src/DocMeasure.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,29 @@ class DocMeasure {
}

convertIfBase64Image(node) {
if (/^data:image\/(jpeg|jpg|png);base64,/.test(node.image)) { // base64 image
if (/^data:image\/(jpeg|jpg|png|svg+xml);base64,/.test(node.image)) { // base64 image
let label = `$$pdfmake$$${this.autoImageIndex++}`;
this.pdfDocument.images[label] = node.image;
node.image = label;
}
}

chekIfIsSVG(imageSource) {
// read the first 1000 bytes instead of 4 to allow for possible whitespace
return imageSource.toString('utf-8', 0, 1000).includes('<svg');
}

measureImage(node) {
this.convertIfBase64Image(node);
let imageSource = this.pdfDocument.provideImageSource(node.image);

if (this.chekIfIsSVG(imageSource)) {
delete node.image;
node.svg = imageSource.toString('utf-8');
return this.measureSVG(node);
}

let image = this.pdfDocument.provideImage(node.image);
let image = this.pdfDocument.provideImage(node.image, imageSource);
let imageSize = { width: image.width, height: image.height };

this.measureImageWithDimensions(node, imageSize);
Expand All @@ -133,6 +145,14 @@ class DocMeasure {
}

measureSVG(node) {
let imageSource = this.pdfDocument.provideImageSource(node.svg);

if (!this.chekIfIsSVG(imageSource)) {
throw new Error('DocMeasure.measureSVG: No valid SVG image provided');
} else {
node.svg = imageSource;
}

let dimensions = this.svgMeasure.measureSVG(node.svg);

this.measureImageWithDimensions(node, dimensions);
Expand Down
17 changes: 14 additions & 3 deletions src/PDFDocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ class PDFDocument extends PDFKit {
return this.fontCache[familyName][type];
}

provideImage(src) {
const realImageSrc = src => {
provideImageSource(src) {
const getRealImageSrc = src => {
let image = this.images[src];

if (!image) {
Expand All @@ -102,14 +102,25 @@ class PDFDocument extends PDFKit {
return Buffer.from(image.substring(index + 7), 'base64');
};

const realImageSrc = getRealImageSrc(src);

// convert to Buffer if in browser context
if (realImageSrc instanceof ArrayBuffer) {
return Buffer.from(new Uint8Array(realImageSrc));
}

return realImageSrc;
}

provideImage(src, imageSource) {
if (this._imageRegistry[src]) {
return this._imageRegistry[src];
}

let image;

try {
image = this.openImage(realImageSrc(src));
image = this.openImage(imageSource);
if (!image) {
throw new Error('No image');
}
Expand Down
4 changes: 4 additions & 0 deletions src/SVGMeasure.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class SVGMeasure {
writeDimensions(svgString, dimensions) {
let doc = parseSVG(svgString);

if ( typeof doc.attr.viewBox !== 'string' ) {
doc.attr.viewBox = `0 0 ${stripUnits(doc.attr.width)} ${stripUnits(doc.attr.height)}`;
}

doc.attr.width = "" + dimensions.width;
doc.attr.height = "" + dimensions.height;

Expand Down
3 changes: 3 additions & 0 deletions tests/unit/LayoutBuilder.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ var sampleTestProvider = {
descender: -50
};
},
provideImageSource(src) { // eslint-disable-line no-unused-vars
return {};
},
provideImage(src) { // eslint-disable-line no-unused-vars
return {
width: 1,
Expand Down