thekestrel has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,
I'm trying to automatically generate some screens for a project by using the SVG module with a reasonable degree of success.

My issue is that i wish to generate a specific path command and I want to specify the command field seen in the following table that details the path behaviour.

Command
Parameters
Repeat
Explanation
M
x,y
Yes
moveto: Moves the pen to a new location. No line is drawn. All path data must begin with a 'moveto' command.
Line Commands
L
x,y
Yes
lineto: Draws a line from the current point to the point (x,y).
H
x
Yes
horizontal lineto: Draws a horizontal line from the current point to x.
V
y
Yes
vertical lineto: Draws a vertical line from the current point to y.
Cubic Bezier Curve Commands
C
x1 y1 x2 y2 x y
Yes
curveto: Draw a cubic bezier curve to the point (x,y) where the points (x1,y1) and (x2,y2) are the start and end control points, respectively.
S
x2 y2 x y
Yes
shorthand/smooth curveto: Draw a curve to the point (x,y) where the point (x2,y2) is the end control point and the start control point is the reflection of the last point's end control point.
Quadratic Bezier Curve Commands
Q
x1 y1 x y
Yes
Quadratic Bezier curveto: Draw a quadratic bezier between the last point and point (x,y) using the point (x1,y1) as the control point.
T
x y
Yes
Shorthand/smooth quadratic Bezier curveto: Draw a quadratic bezier between the last point and point (x,y) using the reflection of the last control point as the control point.
Elliptical Arc Curve Commands
A
**
Yes
elliptical arc: Draws and arc from the current point to x, y. The actual scale factor and position of the arc needed to bridge the two points is computed by the SVG viewer.
End Path Commands
z
-
No
closepath: Closes the path. A line is drawn from the last point to the first.

Unfortunately, it appears that I'm only able to specify the X,Y points and the module automatically prepends the M (moveto command) at the beginnining, L (lineto), in front of every other line and Z to close the path that the end. Without direct access to the curveto command I get the default of straight lines between each of the defined points instead of some nice vector corners. Here is the code I'm using;
#!/usr/bin/perl -w use strict; use warnings; use SVG; # create an SVG object my $svg= SVG->new(width=>800,height=>600); my $cont_w = 500; my $cont_h = 100; my $cont_tbh = 19; # a 10-pointsaw-tooth pattern drawn with a path definition my $xv = [6, "C 2.676", 0, 0, 0, $cont_w, $cont_w, "C $cont_w", $c +ont_w - 2.676, $cont_w - 6, 6]; my $yv = [0, 0, 2.676, 6, $cont_tbh, $cont_tbh, 6, 2.676, 0, 0, 0] +; my $points = $svg->get_path( x => $xv, y => $yv, -type => 'path', -closed => 'true' #specify that the polyline is closed ); my $tag = $svg->path( %$points, id => 'pline_1', style => { 'fill-color' => 'green' } ); # now render the SVG object, implicitly use svg namespace print $svg->xmlify;
As you can see from the code snippet above I tried forcing the curveto command characters into the array (which was useless) as in the generated XML there are now two commands. This can be seen in the generated XML below;
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2 +001/REC-SVG-20010904/DTD/svg10.dtd"> <svg height="600" width="800" xmlns="http://www.w3.org/2000/svg" xmlns +:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999 +/xlink"> <path d="M 6 0 L C 2.676 0 L 0 2.676 L 0 6 L 0 19 L 500 +19 L 500 6 L C 500 2.676 L 497.324 0 L 494 0 L 6 0 z " id= +"pline_1" style="fill-color: green" /><!-- Generated using the Perl SVG Module V2.49 by Ronan Oger Info: http://www.roitsystems.com/ --> </svg>
Does anyone know if it is possible to specify the X,Y Point List and the Associated command within the SVG module, or am I out of luck. (I'm using Inkscape to validate my output is valid) Ideas, Appreciated. Paul.

Replies are listed 'Best First'.
Re: Curveto Command in SVG
by gwadej (Chaplain) on Jul 07, 2009 at 19:56 UTC

    The issue is that the get_path method is designed specifically for creating appropriate paths in <path/>, <polyline/>, and <polygon/> tags. Piecewise-linear paths are the only things these three tags have in common.

    If you want to use the other path commands, you need to create the path yourself. The syntax is not really very complicated.

    G. Wade
      Ok,
      Found the module code and I believe I understand what it going on now.
      my $string = "M 6,0 C 2.676,0 0,2.676 0,6 L 0,$cont_tbh L $cont_w, +$cont_tbh L $cont_w,6 C $cont_w,2.676 $cont_w - 2.676,0 $cont_w - 6,0 + L 6,0 Z"; my $tag = $svg->path( d => $string, id => 'pline_1', style => { 'fill-color' => 'green' } );

      The following allows me to send a custom string to the SVG engine.
      Thanks, Paul.