NAME
Image::SVG::Path - read the "d" attribute of an SVG path
SYNOPSIS
use Image::SVG::Path 'extract_path_info';
my @path_info = extract_path_info ($path_d_attribute);
DESCRIPTION
This module extracts information contained in the "d" attribute of an SVG <path> element and turns it into a simpler series of steps.
For example, an SVG <path> element might take the form
<path d="M9.6,20.25c0.61,0.37,3.91,0.45,4.52,0.34c2.86-0.5,14.5-2.09,21.37-2.64c0.94-0.07,2.67-0.26,3.45,0.04"/>
Using an XML parser, such as XML::Parser,
use XML::Parser;
use Image::SVG::Path 'extract_path_info';
my $p = XML::Parser->new (Handlers => {Start => \& start});
$p->parsefile ($file)
or die "Error $file: ";
sub start
{
my ($expat, $element, %attr) = @_;
if ($element eq 'path') {
my $d = $attr{d};
my @r = extract_path_info ($d);
# Do something with path info in @r
}
}
SVG means "scalable vector graphics" and it is a standard of the W3 consortium. See "SVG standards" for details. Although SVG is a type of XML, the text in the d
attribute of SVG paths is not XML but a condensed form using single letters and numbers. This module is a parser for that condensed format.
FUNCTIONS
extract_path_info
my @path_info = extract_path_info ($path_d_attribute);
Turn the SVG path string into a series of simpler things. For example,
my @path_info = extract_path_info ('M6.93,103.36c3.61-2.46,6.65-6.21,6.65-13.29c0-1.68-1.36-3.03-3.03-3.03s-3.03,1.36-3.03,3.03s1.36,3.03,3.03,3.03C15.17,93.1,10.4,100.18,6.93,103.36z');
my $count = 0;
for my $element (@path_info) {
$count++;
print "Element $count:\n";
for my $k (keys %$element) {
my $val = $element->{$k};
if (ref $val eq 'ARRAY') {
$val = "[$val->[0], $val->[1]]";
}
print " $k -> $val\n";
}
}
This prints out
Element 1:
point -> [6.93, 103.36]
svg_key -> M
position -> absolute
type -> moveto
Element 2:
control1 -> [3.61, -2.46]
svg_key -> c
control2 -> [6.65, -6.21]
position -> relative
type -> cubic-bezier
end -> [6.65, -13.29]
Element 3:
control1 -> [0, -1.68]
svg_key -> c
control2 -> [-1.36, -3.03]
position -> relative
type -> cubic-bezier
end -> [-3.03, -3.03]
Element 4:
svg_key -> s
control2 -> [-3.03, 1.36]
position -> relative
type -> shortcut-cubic-bezier
end -> [-3.03, 3.03]
Element 5:
svg_key -> s
control2 -> [1.36, 3.03]
position -> relative
type -> shortcut-cubic-bezier
end -> [3.03, 3.03]
Element 6:
control1 -> [15.17, 93.1]
svg_key -> C
control2 -> [10.4, 100.18]
position -> absolute
type -> cubic-bezier
end -> [6.93, 103.36]
Element 7:
svg_key -> z
position -> relative
type -> closepath
The return value is a list of hash references. Each hash reference has at least three keys, type
, position
, and svg_key
. The type
field says what type of thing it is, for example a cubic bezier curve or a line. The position
value is either "relative" or "absolute" depending on whether the coordinates of this step of the path are relative to the current point (relative) or to the drawing's origin (absolute). The svg_key
field is the original key from the path. position
is relative if this key is lower case and absolute if this key is upper case.
If type
is moveto
, the hash reference contains one more field, point
, which is the point to move to. This is an array reference containing the x and y coordinates as elements indexed 0 and 1 respectively.
If the type is cubic-bezier
, the hash reference contains three more fields, control1
, control2
and end
. The value of each is an array reference containing the x and y coordinates of the first and second control points and the end point of the Bezier curve respectively. (The start point of the curve is the end point of the previous part of the path.)
If the type is shortcut-cubic-bezier
, the hash contains two more fields, control2
and end
. control2
is the second control point, and end
is the end point. The first control point is got by reflecting the second control point of the previous curve around the end point of the previous curve (the start point of the current curve).
There is also an option "no_shortcuts" which automatically replaces shortcut cubic bezier curves with the normal kind, by calculating the first control point.
A second argument to extract_path_info
contains options for the extraction in the form of a hash reference. For example,
my @path_info = extract_path_info ($path, {absolute => 1});
The following may be chosen by adding them to the hash reference:
- absolute
-
If the hash element
absolute
is set to a true value, relative positions are changed to absolute. For example a "c" curve is changed to the equivalent "C" curve. - no_shortcuts
-
If the hash element
no_shortcuts
is set to a true value then shortcuts ("S" curves) are changed into the equivalent "C" curves. A deficiency of this is that it only works in combination with the "absolute" option, otherwise it does nothing. - verbose
-
If this is set to a true value,
extract_path_info
prints out informative messages about what it is doing as it parses the path.
reverse_path
my $reverse_path = reverse_path ($path);
Make an SVG path which is the exact reverse of the input.
Bugs
This only works for cubic bezier curves with absolute position and no shortcuts (C elements only). It doesn't fill in all the information correctly.
create_path_string
my $path = create_path_string (\@info);
Given a set of information as created by "extract_path_info", turn them into an SVG string representing a path.
Bugs
This only works for cubic bezier curves and the initial moveto element for absolute position and no shortcuts (C elements only).
SVG path elements
This section documents the output elements. For example, if we extract the path information from a path $d
using
my @path = extract_path_info ($d);
then each element of @path
is a hash reference containing one of the following types of elements and the corresponding hash keys.
An SVG path consists of a sequence of movements from one point to another, so each of the following steps in the path begins from the end point of the previous movement.
Move to elements
- svg_key
-
This is M or m.
- point
-
This is the point to move to.
Line elements
- svg_key
-
This is L or l.
- point
-
This is the end point of the line.
- end
-
This field occurs in some lines for backwards compatibility with pre-0.16 versions of the module.
Cubic bezier curve elements
- svg_key
-
This is C or c.
- control1
-
Control point 1 of the curve.
- control2
-
Control point 2 of the curve.
- end
-
The end point of the curve.
Shortcut cubic bezier curve elements
Use the "no_shortcuts" option to automatically convert these into cubic bezier curve elements.
- svg_key
-
This is S or s.
- control2
-
This is the second control point of the curve (the first one is implicit).
- end
-
This is the end point of the curve.
Quadratic bezier curve elements
- svg_key
-
This is Q or q.
- control
-
This is the control point.
- end
-
This is the end point.
Shortcut quadratic Bezier curves
Use the "no_shortcuts" option to automatically convert these into quadratic bezier curves.
- svg_key
-
This is T or t.
- end
-
This is the end point.
Arc elements
Arcs are omitted from "SVG Tiny".
- rx, ry
-
X and Y radiuses
- x_axis_rotation
-
See the SVG documentation for details.
- large_arc_flag
-
See the SVG documentation for details.
- sweep_flag
-
See the SVG documentation for details.
- x, y
-
These are the end points of the arc.
Horizontal line elements
- svg_key
-
This is H or h.
- x
-
This is the x coordinate of the end point. The y coordinate is implicit.
Vertical line elements
- svg_key
-
This is V or v.
- y
-
This is the y coordinate of the end point. The x coordinate is implicit.
BUGS
- Does not use the grammar
-
There is a grammar for the paths in the W3 specification. See http://www.w3.org/TR/SVG/paths.html#PathDataBNF. However, this module does not use that grammar. Instead it hacks up the path using regexes.
EXPORTS
The module exports "extract_path_info" on demand, so
use Image::SVG::Path 'extract_path_info';
imports it.
SEE ALSO
MarpaX::Languages::SVG::Parser
This parser uses the SVG grammar mentioned in "BUGS".
SVG standards
The full specification contains all the details. The SVG path specification contains the specifications for paths.
SVG Tiny
SVG Tiny is a subset of SVG. It claims to have a Perl Language Binding, but I cannot locate the source code.
There is also another standard, SVG basic, I'm not too sure whether either this or SVG Tiny are in use.
AUTHOR
Ben Bullock, <bkb@cpan.org>
LICENCE
This module and all associated files can be used, modified and distributed under either the Perl artistic licence or the GNU General Public Licence.