dompdf icon indicating copy to clipboard operation
dompdf copied to clipboard

PDF/A does not work with SVG

Open micheh opened this issue 1 year ago • 4 comments

Version 3.1.0 introduced a PDF/A compliance mode (#3269), which is awesome!

But it does not seem to work with SVG. In the before method of Document, a default style is added to the surface: https://github.com/dompdf/php-svg-lib/blob/ee5bab8e99e99e493ed4d35a7f0e7efd09b748b6/src/Svg/Document.php#L228-L239

This call adds the serif or Times Roman font (even if there are no to texts in the SVG). Since the font is not embedded, Dompdf throws an exception when trying to generate the output: A fully embeddable font must be used when generating a document in PDF/A mode

I tried to remap the font family serif and various alternatives of Times to an embedded font, but this does not seem to help.

$font_metrics->setFontFamily("serif", $font_metrics->getFamily("DejaVu Serif"));

micheh avatar Feb 06 '25 10:02 micheh

Font mapping in SvgLib is more challenging. That library doesn't use Dompdf's font management functionality. Perhaps the solution would be to tweak Cpdf to exclude unused fonts when it's compiling the PDF.

bsweeney avatar Feb 06 '25 13:02 bsweeney

Maybe the call to setFont could be separated from setStyle? Then only the Text shape could call setFont, as the other shapes probably do not require fonts. Unfortunately, i don't know the project well enough to be able to assess the feasibility and potential side effects.

micheh avatar Feb 06 '25 14:02 micheh

Interestingly the serif stuff is also what I describe in https://github.com/dompdf/dompdf/issues/3443#issuecomment-2645733574

I am not really sure what it does think there is the need of this. I have set the default font to Helvetica. But maybe I am a bit confused on this

williamdes avatar Feb 08 '25 23:02 williamdes

I was able to make this work after I remapped all the default font families (generic and core PDF). I updated the wiki's PDF/A guidance to indicate this. The Cpdf default font is Helvetica so that's probably what's causing your issue even after you remapped serif.

bsweeney avatar Feb 12 '25 14:02 bsweeney

@bsweeney remapping all default fonts as documented in the wiki does not seem to solve the issue.

See following sample code:

<?php
	use Dompdf\Dompdf;
	use Dompdf\Options;

	require "vendor/autoload.php";

	$dompdf = new Dompdf();
	$dompdf->setPaper("a4");
	$dompdf->setOptions(new Options(["isPdfAEnabled" => true, "defaultFont" => "DejaVu Serif"]));

	$font_metrics = $dompdf->getFontMetrics();
	$font_metrics->setFontFamily("courier", $font_metrics->getFamily("DejaVu Sans Mono"));
	$font_metrics->setFontFamily("fixed", $font_metrics->getFamily("DejaVu Sans Mono"));
	$font_metrics->setFontFamily("helvetica", $font_metrics->getFamily("DejaVu Sans"));
	$font_metrics->setFontFamily("monospace", $font_metrics->getFamily("DejaVu Sans Mono"));
	$font_metrics->setFontFamily("sans-serif", $font_metrics->getFamily("DejaVu Sans"));
	$font_metrics->setFontFamily("serif", $font_metrics->getFamily("DejaVu Serif"));
	$font_metrics->setFontFamily("times", $font_metrics->getFamily("DejaVu Serif"));
	$font_metrics->setFontFamily("times-roman", $font_metrics->getFamily("DejaVu Serif"));

	$dompdf->loadHtml(<<<HTML
		<html>
		<head>
		    <style>
		        * { font-family: sans-serif; }
		    </style>
		</head>
		<body>
			<p>PDF/A file</p>
			<img src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwMCIgd2lkdGg9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIHI9IjQ1IiBjeD0iNTAiIGN5PSI1MCIgZmlsbD0icmVkIi8+PC9zdmc+Cg">
		</body>
		</html>
		HTML
	);

	$dompdf->render();
	$dompdf->stream();

Instead of creating a PDF/A file with a red circle (included as SVG), it throws the following exception: A fully embeddable font must be used when generating a document in PDF/A mode.

Tested with Dompdf version 3.1.0 and PHP 8.4.4.

nox-4O4 avatar Aug 10 '25 14:08 nox-4O4

I believe what is happening is that a cached font metrics for one of the core fonts already exist in the directory specified by the fontCache configuration option. When the cache file exists Cpdf will use it, otherwise the font specified has to be valid.

I was able to render without issue in my own code because my setup uses clean, non-default font and cache directories on each run. I didn't consider that my particular use case is not common when I added that guidance.

bsweeney avatar Aug 11 '25 03:08 bsweeney

Thanks for your reply! This was indeed what was happening.

I did not specify any specific font cache directory. So the default directory (vendor/dompdf/dompdf/lib/fonts) was used, which already contained some cached font metrics from my previous tests.

As the wiki states not to touch the lib/fonts directory, I had left all the files in it as they were. Now, after deleting Times-Roman.afm.json, I was able to create a PDF/A file containing an SVG image.

nox-4O4 avatar Aug 17 '25 21:08 nox-4O4

Thanks for the feedback. I'm still looking to see if I can do something more in the code or provide better guidance in the wiki.

bsweeney avatar Aug 17 '25 21:08 bsweeney

OK I have a work around for the issue. If the SVG document has an inline style declaration on the SVG element you can override the default font.

<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg" style="font-family: DejaVu Sans;">
<circle r="45" cx="50" cy="50" fill="red"/></svg>

I might also recommend modifying Cpdf's default font, though I believe this is unnecessary after implementing the other guidance.

dompdf->get_canvas()->get_cpdf()->defaultFont = "./lib/fonts/DejaVuSerif.ttf";

I will look at performing font exclusion and conformance check during render instead, though not until a later release.

Another relevant ticket to watch would be the addition of font management to SvgLib.

bsweeney avatar Aug 24 '25 19:08 bsweeney