Skip to content

Commit

Permalink
Implement embedSvg
Browse files Browse the repository at this point in the history
  • Loading branch information
MatheusrdSantos committed May 16, 2024
1 parent f0540b9 commit 3f93a29
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 99 deletions.
8 changes: 4 additions & 4 deletions apps/web/test19.html
Original file line number Diff line number Diff line change
Expand Up @@ -248,21 +248,21 @@
y: 0,
size: 20,
});
await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
x: 100,
y: 841 /*
width: 427 / 3,
height: 769 / 3 */,
});
await firstPage.drawSvg(svgPowerTwo, {
firstPage.drawSvg(svgPowerTwo, {
x: 550,
y: 841,
});
await secondPage.drawSvg(svgDemo, {
secondPage.drawSvg(svgDemo, {
x: 100,
y: 841,
});
await secondPage.drawSvg(scienceSvgs, {
secondPage.drawSvg(scienceSvgs, {
x: 100,
y: 500,
});
Expand Down
4 changes: 2 additions & 2 deletions apps/web/test20.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@
x: 100,
y: 1000
}); */
await firstPage.drawSvg(svg3, {
firstPage.drawSvg(svg3, {
x: 100,
y: 950,
});
await firstPage.drawSvg(svg2, {
firstPage.drawSvg(svg2, {
x: 100,
y: 800,
});
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test21.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
drawLines(firstPage);
drawLines(secondPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
x: 100,
y: 800,
});
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test22.html
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 173.0060640625,
width: 167.68455000000003,
x: 100,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test23.html
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 595.28,
width: 841.89,
// height: 100,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test24.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 719,
width: 611,
// height: 100,
Expand Down
8 changes: 4 additions & 4 deletions apps/web/test25.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 602,
width: 409,
// height: 32,
Expand All @@ -149,21 +149,21 @@
y: 700,
});

// await firstPage.drawSvg(svg3, {
// firstPage.drawSvg(svg3, {
// height: 100,
// width: 100,
// x: 100,
// y: 700
// })

// await firstPage.drawSvg(svg2, {
// firstPage.drawSvg(svg2, {
// height: 100,
// width: 100,
// x: 100,
// y: 500
// })

// await firstPage.drawSvg(svg4, {
// firstPage.drawSvg(svg4, {
// height: 100,
// width: 100,
// x: 100,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test26.html
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 240.75,
width: 249.75,
x: 100,
Expand Down
6 changes: 3 additions & 3 deletions apps/web/test27.html
Original file line number Diff line number Diff line change
Expand Up @@ -321,21 +321,21 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 246.75,
width: 231,
x: 100,
y: 700,
});

await firstPage.drawSvg(cutArrowSvg, {
firstPage.drawSvg(cutArrowSvg, {
height: 246.75,
width: 231,
x: 500,
y: 700,
});

await firstPage.drawSvg(simpleCutArrowSvg, {
firstPage.drawSvg(simpleCutArrowSvg, {
height: 246.75,
width: 231,
x: 500,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/test28.html
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 300,
width: 400,
x: 100,
Expand Down
16 changes: 14 additions & 2 deletions apps/web/test29.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<iframe id="iframe"></iframe>
</body>

<script type="text/javascript">
<script type="text/javascript" >
// startFpsTracker('animation-target');

const renderInIframe = (pdfBytes) => {
Expand Down Expand Up @@ -105,12 +105,24 @@
// drawGrid(firstPage)
drawLines(firstPage);

await firstPage.drawSvg(svg, {
firstPage.drawSvg(svg, {
height: 100,
width: 100,
x: 100,
y: 700,
});

const svg2 = `<svg height="200" width="300">
<image width="300" height="200" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" />
</svg>`
const images = await pdfDoc.embedSvg(svg2)
firstPage.drawSvg(svg2, {
height: 200,
width: 300,
x: 500,
y: 700,
images,
});
firstPage.moveUp(600);
firstPage.moveRight(100);
firstPage.drawSvgPath(
Expand Down
26 changes: 26 additions & 0 deletions src/api/PDFDocument.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
parse as parseHtml,
HTMLElement,
NodeType,
} from 'node-html-better-parser';
import Embeddable from './Embeddable';
import {
EncryptedPDFError,
Expand Down Expand Up @@ -1110,6 +1115,27 @@ export default class PDFDocument {
return pdfImage;
}

async embedSvg(svg: string): Promise<Record<string, PDFImage>> {
const parsedSvg = parseHtml(svg)
const findImages = (element: HTMLElement): HTMLElement[] => {
if (element.tagName === 'image') return [element]
else return element.childNodes.map(child => child.nodeType === NodeType.ELEMENT_NODE ? findImages(child): []).flat()
}
const images = findImages(parsedSvg)
const imagesDict = {} as Record<string, PDFImage>

await Promise.all(
images.map(async image => {
const href = image.attributes.href
if (!href || imagesDict[href]) return
const isPng = href.match(/\.png(\?|$)|^data:image\/png;base64/gim)
const pdfImage = isPng ? await this.embedPng(href) : await this.embedJpg(href)
imagesDict[href] = pdfImage
})
)

return imagesDict
}
/**
* Embed one or more PDF pages into this document.
*
Expand Down
28 changes: 4 additions & 24 deletions src/api/PDFPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import {
assertRangeOrUndefined,
assertIsOneOfOrUndefined,
} from '../utils';
import { drawSvg, drawSvgSync } from './svg';
import { drawSvg } from './svg';

/**
* Represents a single page of a [[PDFDocument]].
Expand Down Expand Up @@ -1585,26 +1585,7 @@ export default class PDFPage {
* @param svg The SVG to be drawn.
* @param options The options to be used when drawing the SVG.
*/
async drawSvg(
svg: string,
options: PDFPageDrawSVGElementOptions = {},
): Promise<void> {
assertIs(svg, 'svg', ['string']);
assertOrUndefined(options.x, 'options.x', ['number']);
assertOrUndefined(options.y, 'options.y', ['number']);
assertOrUndefined(options.width, 'options.width', ['number']);
assertOrUndefined(options.height, 'options.height', ['number']);

await drawSvg(this, svg, {
x: options.x ?? this.x,
y: options.y ?? this.y,
fonts: options.fonts,
width: options.width,
height: options.height,
});
}

drawSvgSync(
drawSvg(
svg: string,
options: PDFPageDrawSVGElementOptions = {},
): void {
Expand All @@ -1613,15 +1594,14 @@ export default class PDFPage {
assertOrUndefined(options.y, 'options.y', ['number']);
assertOrUndefined(options.width, 'options.width', ['number']);
assertOrUndefined(options.height, 'options.height', ['number']);
assertOrUndefined(options.images, 'options.images', [[PDFImage, 'PDFImage']])

drawSvgSync(this, svg, {
drawSvg(this, svg, {
x: options.x ?? this.x,
y: options.y ?? this.y,
fonts: options.fonts,
width: options.width,
height: options.height,
images: options.images
images: options.images,
});
}

Expand Down
61 changes: 7 additions & 54 deletions src/api/svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ const parseAttributes = (
};

const svgAttributes: SVGAttributes = {
src: attributes.src || attributes['xlink:href'],
src: attributes.src || attributes.href || attributes['xlink:href'],
textAnchor: attributes['text-anchor'],
dominantBaseline: attributes['dominant-baseline'],
preserveAspectRatio: attributes.preserveAspectRatio,
Expand Down Expand Up @@ -894,12 +894,12 @@ const parse = (
);
};

const parseSvg = (
export const drawSvg = (
page: PDFPage,
svg: string,
options: PDFPageDrawSVGElementOptions,
options: PDFPageDrawSVGElementOptions
) => {
if (!svg) return [];
if (!svg) return;
const size = page.getSize();
const firstChild = parseHtml(svg).firstChild as HTMLElement;

Expand Down Expand Up @@ -951,44 +951,8 @@ const parseSvg = (
baseTransformation,
);

return elements
};

export const drawSvg = async (
page: PDFPage,
svg: string,
options: PDFPageDrawSVGElementOptions
) => {
const elements = parseSvg(page, svg, options)
const runners = runnersToPage(page, options);

const parseImage = async (element: SVGElement) => {
const { src } = element.svgAttributes;
if (!src) return;
const isPng = src.match(/\.png(\?|$)|^data:image\/png;base64/gim);
const img = isPng
? await page.doc.embedPng(src)
: await page.doc.embedJpg(src);

const { x, y, width, height } = getFittingRectangle(
img.width,
img.height,
element.svgAttributes.width || img.width,
element.svgAttributes.height || img.height,
element.svgAttributes.preserveAspectRatio,
);
page.drawImage(img, {
x,
y: -y - height,
width,
height,
opacity: element.svgAttributes.fillOpacity,
matrix: element.svgAttributes.matrix,
clipSpaces: element.svgAttributes.clipSpaces,
});
}
await elements.reduce(async (prev, elt) => {
await prev;
elements.forEach(elt => {
// uncomment these lines to draw the clipSpaces
// elt.svgAttributes.clipSpaces.forEach(space => {
// page.drawLine({
Expand Down Expand Up @@ -1019,17 +983,6 @@ export const drawSvg = async (
// thickness: 1
// })
// })
if (elt.tagName === 'image') return parseImage(elt);
return runners[elt.tagName]?.(elt);
}, Promise.resolve());
}

export const drawSvgSync = (
page: PDFPage,
svg: string,
options: PDFPageDrawSVGElementOptions
) => {
const elements = parseSvg(page, svg, options);
const runners = runnersToPage(page, options);
elements.forEach(elt => runners[elt.tagName]?.(elt));
runners[elt.tagName]?.(elt)
});
}

0 comments on commit 3f93a29

Please sign in to comment.