HW 3 : SVG2PS Conversion
DUE: SUNDAY, March 25th 2007, 11:59PM
This Homework writing a simple UNIX Utility to convert one graphics format to another. It will give you a chance to work with real-world data formats, deal with the realities of software engineering. We will build on this assignment once we start lectures on pointers, dynamic memory, and structured data.
1. SVG2PS Coversion Utility (6 Pts)
Write a UNIX command line utilty that converts SVG (scalable vector graphics) format to the PS (Adobe Postscript format).
What is SVG?
(From wikipedia) "SVG (scalable vector graphics) is an XML markup language for describing two-dimensional vector graphics, both static and animated, and either declarative or scripted"
Vector graphics are graphics that are represented in a mathematical format. In other words, one describes the three circles on the left in the above picture in terms of their x and y coordinates, their radii, their fill color, their line color, and transparencies. So a circle could be described as a set of specially formated and structured numbers. SVG (Scalable Vector Graphics) is a standard to describe formatting (and hence storing) those numbers, and thereby describing qualities of position, size, and color description.
XML stands for eXtenisble Markup Language, and is very similar to HTML (the text format that web-pages are described in) in it's form (acutally XHTML, used now by modern web-pages) is an XML version of HTML). The basics of XML are the use of tags and attributes to represent data.
What is PS?
(From wikipedia) "Postscript (PS) is a page description language and programming language used primarily in the electronic and desktop publishing areas."
PostScript is more of a declarative format. It rather describes shapes as being a set of instructions given to the printer and how they are drawn on the page in a certain sequence. A rectangle drawn in PostScript is a set of four lines being drawn in a certain order.
Most printers actually take the Postscript format directly, in the UNIX labs you can send Postscripts files to the printers with the lpr command (could be a good way to verify the output of your program). Additionally, PostScript is a programming language as well. It has computational properties, memory (a "dictionary" and a "stack"), and small programs can be written with it (however, not in this class).
Coordinate Systems
For both SVG and PS, you can imagine a cartesian coordinate system with the origin at the bottom left-hand corner of your screen, moving in the positive x direction is to move from left to right, and moving in the positive y direction is to move from bottom of the screen to the top.
An Example of SVG Rectangles
Here is an example of two rectangles being specified in SVG:
<rect x="1" y="1" width="300" height="100" fill="none" stroke="blue" stroke-width="2"/>
<rect x="100" y="40" width="100" height="50" fill="yellow" stroke="navy" stroke-width="3" />
The rendered output of both rectangles are (shown in the image below):
Note the use of the < and the /> to deliminate two individual data structures (this is called a tag mark-up). The word rect indicates that what is contained between the < and the /> are the attributes of the rectangle. We call the rect a tag (in XML and hence SVG). A tag (in this case the rect tag), has a few attributes (or data associated with that rectangle).
Look at the first rect tag. It's attributes are the x and y position (x="1" y="1") of the rectangle in our coordinate system, the width and height of the rectangle (width="300" height="100"), whether the rectange is filled, and if it is filled what color it is filled with (fill="none" which indicates the outer rectangle is not filled). It also describes the attributes of the line qualities of the rectangle: its stroke color (line color) and stoke-width (line width). (stroke="navy" stroke-width="10").
NOTE: In SVG, attributes for tags may appear in ANY ORDER. So this is equivalent to the first rect tag specified above:
<rect width="300" stroke-width="2" x="1" height="100" fill="none" stroke="blue" y="1"/>
Also, attributes may be optional without having an error on the part of your program. Default values will be specified below in case some of the attributes are missing. So this is a legal rect tag as well:
<rect />
It would just be a rectangle drawn with all of the default values.
... our Rectangles converted to PS
Now below are the above 2 rectangles (i.e. rect tags) specified in PostScript. (Note that different segments of the code are high-lighted with the colors of blue, red, and green, in order to refer to them in the text below):
1 setlinewidth
newpath
1 1 moveto
301 1 lineto
301 101 lineto
1 101 lineto
1 1 lineto
stroke
0.5 setgray
newpath
100 25 moveto
200 25 lineto
200 75 lineto
100 75 lineto
100 25 lineto
fill
0 setgray
3 setlinewidth
newpath
100 25 moveto
200 25 lineto
200 75 lineto
100 75 lineto
100 25 lineto
stroke
And this is the resulting output (note that is only black and white - the yellow fill of the rectangle has be converted to grey):
Note that the scale may be different, but the relative dimensions are the same.
The blue segment of PostScript draws the larger outlined rectangle. The commands are more declarative. It begins by setting the width of the line with 1 setlinewidth (Note how the arguements are presented first and then the command). Following setlinewidth command, a new path (i.e. shape) is specified by newpath. Next, the "pen" of the printer is moved to the position x = 1 and y = 1 with 1 1 moveto. The next point is specified with a lineto command, which means that a line is drawn from the point x = 1 and y = 1 to x = 301 and y = 1. All in total, 4 lines of the rectangle are drawn (for the blue segment of code). The path (i.e. shape) is completed with the stroke command (which means the outline is drawn).
The red segment of PostScript draws the filled in section of the inner box. It works the same as the previous segment, but it is preceded with a 0.5 setgray, which sets the fill to a mid-tone gray (gray values are specified from 0 to 1.0, black to white respectively). Instead of the stroke command specified in the blue segment, the fill command is used (which indicates only to fill the certain area specified).
Now the green segment of PostScript is drawn, with a black stroke, and a thicker line width.
Finally, note that a small chunk of the lower left hand corner of the center box is missing. This is because we specified our rectangle as 4 individual lines, and we did not take into account of the thicker line. To avoid that we can leave out the last lineto command in all of our 3 rectangles that we specified and replace that command with the closepath command (which automatically connects the current point you are at with the very first point you specified after the opening newpath command). See the altered PostScript code:
1 setlinewidth
newpath
1 1 moveto
301 1 lineto
301 101 lineto
1 101 lineto
closepath
stroke
0.5 setgray
newpath
100 25 moveto
200 25 lineto
200 75 lineto
100 75 lineto
closepath
fill
0 setgray
3 setlinewidth
newpath
100 25 moveto
200 25 lineto
200 75 lineto
100 75 lineto
closepath
stroke
This above chunk of PostScript is rendered now as completed rectangles:
Required Features
The SVG markup language and the PostScript Page Description language are huge and ever evolving languages, and a true convertor utility would be beyond the scope of this 2 week assignment (although hopefully by the end of this course you would have the tools and abilities to write such a complete utility, given enough time).
Our tool will support only:
1. Rects
2. Lines
3. Descriptions
4. Comments
We will not worry about color conversions. In it's basic format our program will draw fills as 0.5 gray, and the lines will be rendered solid black.
1. Rects
Look at our first example above to see the format for the Rect in SVG and how to draw it in PostScript.
<rect x="1" y="1" width="300" height="100" fill="none" stroke="blue" stroke-width="2"/>
Remember that all of the attributes are optional. That means you must have default values set in your code in case some of the attributes are missing.
Default Values:
x = 1
y = 1
width = 40
height = 40
fill = none
stroke = black
stroke-width = 2
2. Lines
Lines are specified as two coordinate points (x1, y1) and (x2, y2) with a line connecting them. It can have a stroke color and a stroke-width. Note that there is no fill attribute for a line (i.e. a line is one dimensional). Here is an example line tag:
<line x1="100" y1="100" x2="300" y2="300" stroke="blue" stroke-width="1" />
It draws a line between the points (100,100) and (300,300) with a width of 1 and a stroke of blue (remember this will default to solid black for our basic program).
Given the PostScript Rectangle Example above, how would one draw the line in PostScript?
3. Descriptions
Description tags in SVG provide meta-data to the graphics being drawn. We will just convert these to comments in PostScript. Here is an example of the description tag in SVG:
<desc> Everything between these two tags is the description including news lines and whitespace! </desc>
Notice that the <desc> tag is paired with a similar tag (</desc>) except for an addition back-slash. In XML the first <desc> tag is referred to as a the opening tag and the </desc> tag is referred to as the closing tag. Anything that lies inside is considered the description.
We will convert the description to this PostScript line comment:
% Everything between these two tags is the description including news lines and whitespace!
In PostScript we have the ability to have lines be specified to be comments (EXACTLY how we specify comments in C++) , EXCEPT instead of two back-slashed (//) we use the number sign (%) to specify that what follows is a comment.
4. Comments
Finally, SVG has a different style of comments which we will also convert to the same line comments in PS.
In SVG:
<!-- This is a comment -->
Everything in between the <!-- and the --> is a comment and will be converted to the PostScript line comment:
% This is a comment
Headers and Footers
Wait, we are not done yet. All of the above SVG elements is preceeded by an opening <svg> tag (with a bunch of attributes) and is followed by a closing </svg> tag. In addition in the SVG file you will see some stuff that looks like this:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/TR/2002/WD-SVG11-20020215/DTD/svg11.dtd">
We will ignore all of this stuff until we see the starting svg tag:
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
xmlns="http://www.w3.org/2000/svg" version="1.1">
Notice that the svg tag has a bunch of attributes (i.e. width="12cm"), again we will ignore these for now. You will know you are at the end of the SVG when you encounter the closing </svg> tag all by it's lonesome:
</svg>
In the PostScript file, you will simply start the file with a single line containing the two characters % and !:
%!
This tells the Printer that what follows is a PostScript file.
Finally, the PostScript file is closed by the command showpage on the very last line of the file:
showpage
Command-line Usage
Finally, your svg2ps utility will take two files as command line arguments:
$ svg2ps <input svg file> <output ps file>
Example:
$ svg2ps sample.svg sample.ps
This example converts a given SVG format file called sample.svg to the output PS format file sample.ps.
Extras
1. GrayScale and Support Color (two parts for the Extra Point) - First Part, convert the color values specified in SVG ("blue", "yellow") to corresponding grayscale numbers (from 0.0 to 1.0). Second Part, implement color ouput in the PostScript format. (read in the PostScript specs on how to specify color) (1 Point)
2. Implement the Ellipse and the Circle SVG tags to PostScript convertion. (1 Point)
3. Implement Ellipse and the Circle SVG tags (1 Point)
4. Implement Text Rendering from SVG to PostScript (1 Point)
Resources
With the Lectures and this very detailed decription, you should be able to implement the svg2ps UNIX utility.
However for more information check the wikipedia links at the beginning of the assignment, and:
Basic Shapes Specified in the WWW Consortium
Sample Input/Output File
Here is a sample input SVG file, and the resulting sample output PS file for your use in testing your utility. You can open these files in a text editor and see how they are formated and converted. I plan on providing more sample files as questions arise on this project.
This is the expected rendered output:
Last Updated 3/12/2007