NAME
SVGPDF - Create PDF XObject from SVG data
SYNOPSIS
my $pdf = PDF::API2->new;
my $svg = SVGPDF->new($pdf);
my $xof = $svg->process("demo.svg");
# If all goes well, $xof is an array of hashes, each representing an
# XObject corresponding to the <svg> elements in the file.
# Get a page and graphics context.
my $page = $pdf->page;
$page->bbox( 0, 0, 595, 842 );
my $gfx = $pdf->gfx;
# Place the objects.
my $y = 832;
foreach my $xo ( @$xof ) {
my @bb = @{$xo->{vbox}};
my $h = $bb[3];
$gfx->object( $xo->{xo}, 10, $y-$h, 1 );
$y -= $h;
}
$pdf->save("demo.pdf");
DESCRIPTION
This module processes SVG data and produces one or more PDF XObjects to be placed in a PDF document. This module is intended to be used with PDF::Builder, PDF::API2 and compatible PDF packages.
The main method is process(). It takes the SVG from an input source, see "INPUT".
COORDINATES & UNITS
SVG coordinates run from top-left to bottom-right.
Dimensions without units are pixels, at 96 pixels / inch. E.g., width="96"
means 96px (pixels) and is equal to 72pt (points) or 1in (inch).
For font sizes, CSS defines em
to be equal to the font size, and ex
is half of the font size.
CONSTRUCTOR
In its most simple form, a new SVGPDF object can be created with a single argument, the PDF document.
$svg = SVGPDF->new($pdf);
There are a few optional arguments, these can be specified as key/value pairs.
fc
-
A reference to a callback routine to handle fonts. See "FONT HANDLER CALLBACK".
It may also be an array of routines which will be called in sequence until one of them succeeds (returns a 'true' result).
fontsize
-
The font size to be used for dimensions in 'ex' and 'em' units.
Note that CSS defines 'em' to be the font size, and 'ex' half of the font size.
pagesize
-
An array reference containing the maximum width and height of the resultant image.
There is no widely accepted default for this, so we use
[595,842]
which corresponds to an ISO A4 page. grid
-
If not zero, a grid will be added to the image. This is mostly for developing and debugging.
The value determines the grid spacing.
verbose
-
Verbosity of informational messages. Set to zero to silence all but fatal errors.
debug
-
Internal use only.
For convenience, the mandatory PDF argument can also be specified with a key/value pair:
$svg = SVGPDF->new( pdf => $pdf, grid => 1, fc => \&fonthandler );
METHODS
process
$xof = $svg->process( $data, %options )
This methods gets SVG data from $data
and returns an array reference with rendered images. See "OUTPUT" for details.
The input is read using File::LoadLines. See "INPUT" for details.
Recognized attributes in %options
are:
- fontsize
-
The font size to be used for dimensions in 'ex' and 'em' units.
This value overrides the value set in the constructor.
- combine
-
An SVG can produce multiple XObjects, but sometimes these should be kept as a single image.
There are two ways to combine the image objects. This can be selected by setting $opts{combine} to either
"stacked"
or"bbox"
.Type
"stacked"
(default) stacks the images on top of each other, left sides aligned. The bounding box of each object is only used to obtain the width and height.Type
"bbox"
stacks the images using the bounding box details. The origins of the images are vertically aligned and images may protrude other images when the image extends below the origin. - sep
-
When combining images, add additional vertical space between the individual images.
INPUT
The input SVG data must be correct XML data. The data can be a single <svg>
element, or a container element (e.g. <html>
or <xml>
) with one or more <svg>
elements among its children.
The SVG data can come from several sources:
An SVG document on disk, specified as the name of the document.
A file handle, openened on a SVG document, specified as a glob reference. You can use
\*DATA
to append the SVG data after a__DATA__
separator at the end of the program.A string containing SVG data, specified as a reference to a scalar.
The input is read using File::LoadLines. See its documentation for details.
OUTPUT
The result from calling process() is a reference to an array containing hashes that describe the XObjects. Each hash has the following keys:
vbox
-
The viewBox as specified in the SVG element.
If no viewBox is specified it is set to
0 0
W H, where W and H are the width and the height. width
-
The width of the XObject, as specified in the SVG element or derived from its viewBox.
height
-
The height of the XObject, as specified in the SVG element or derived from its viewBox.
vwidth
-
The desired width, as specified in the SVG element or derived from its viewBox.
vheight
-
The desired height, as specified in the SVG element or derived from its viewBox.
xo
-
The XObject itself.
FONT HANDLER CALLBACK
In SVG fonts are designated by style attributes font-family
, font-style
, font-weight
, and font-size
. How these translate to a PDF font is system dependent. SVGPDF provides a callback mechanism to handle this. As described at CONSTRUCTOR, constructor argument fc
can be set to designate a user routine.
When a font is required at the PDF level, SVGPDF first checks if a @font-face
CSS rule has been set up with matching properties. If a match is found, it is resolved and the font is set. If there is no appropriate CSS rule for this font, the callback is called with the following arguments:
( $self, $pdf, $style )
where $pdf
is de PDF document and $style
a hash reference that contains values for font-family
, font-style
, font-weight
, and font-size
. Don't touch $self
, it is undocumented for a reason.
The callback function can use the contents of $style
to select an appropriate font and return it.
SVGPDF will try to call the font handler callback only once for each combination of family, style and weight. If the callback function returns a 'false' result SVGPDF will try other alternatives to find a font.
Example of an (extremely simplified) callback:
sub simple_font_handler {
my ( $self, $pdf, $style ) = @_;
my $family = $style->{'font-family'};
my $font;
if ( $family eq 'sans' ) {
$font = $pdf->font('Helvetica');
}
else {
$font = $pdf->font('Times-Roman');
}
return $font;
}
If no callback function is set, SVGPDF will recognize the standard PDF corefonts, and aliases serif
, sans
and mono
.
IMPORTANT: With the standard corefonts only characters of the ISO-8859-1 set (Latin-1) can be used. No greek, no chinese, no cyrillic. You have been warned.
LIMITATIONS
The following SVG elements are implemented.
svg
, but not nested.style
, as a child of the outersvg
.Many style attributes are understood, including but not limited to:
color, stroke, stroke-width, stroke-linecap, stroke-linejoin, stroke-dasharray, fill, stroke-width, stroke-linecap, stroke-linejoin, transform (translate, scale, skewX, skewY, rotate, matrix) font-family, font-style, font-weight, font-size, text-anchor.
Partially implemented: @font-face (src url data and local file only).
circle, ellipse, g, image, line, path, polygon, polyline, rect (no rounded corners), text and tspan (no white-space styles).
defs and use,
The following SVG features are partially implemented.
Percentage units. For most "y", "h" or "height" attributes the result will be the percentage of the viewBox height.
Similar for "x", "w" and "width".
Everything else will result in a percentage of the viewBox diagonal (according to the specs).
Embedded SVG elements and preserveAspectRatio.
Standalone T-path elements.
The following SVG features are not (yet) implemented.
title, desc elements
The following SVG features are not planned to be implemented.
Shades, gradients, patterns and animations.
Shape rendering attributes.
Transparency.
Text paths.
Clipping and masking.
What is supported, then? Most SVG files generated by any of the following tools seem to produce good if not perfect results:
abc2svg
(ABC music notation tool)MathJax, inline and display without tag
GNUplot
QRcode and barcode generating tools
XTerm SVG screen dumps
AUTHOR
Johan Vromans < jvromans at squirrel dot nl >
Code for circular and elliptic arcs donated by Phil Perry.
SUPPORT
SVGPDF development is hosted on GitHub, repository https://github.com/sciurius/perl-SVGPDF.
Please report any bugs or feature requests to the GitHub issue tracker, https://github.com/sciurius/perl-SVGPDF/issues.
LICENSE
Copyright (C) 2022.2023 Johan Vromans,
Redistribution and use in source and binary forms, with or without modification, are permitted provided under the terms of the Simplified BSD License.