<< Chapter < Page | Chapter >> Page > |
Note that the strange comments in Listing 26 were placed there so that the program named javadoc could be used to produce standard Java documentation for the graphic library.
Listing 26 . The program named SvgLib21.java. |
---|
import java.io.*;
import org.jdom.*;import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;/**
File SvgLib21.java<p>Copyright 2011, R.G.Baldwin<p>Revised 08/11/11 to add a method named setDescription
that can be called to add a<desc>element to any other
element. The description can be spoken in IVEO by firstselecting the element an pressing Ctrl+d.<p>Revised 08/07/11 to add a parameter for the title to
allow the user to pass in a string for the title element.<p>Revised 08/06/11 to add a title element to each shape
element. As a result, when the SVG file isopened in IVEO and you click on the shape, the name of
the shape is spoken by IVEO. Note, however, that youmust be careful about the order in which you add the
shapes to the drawing. For example, a rectangle thatis added after a line is added can cover the line
and prevent the information about the line from beingspoken even though the rectangle may be transparent.
Therefore, for IVEO compatibility, you must not allowone shape object to cover another shape object.<p>DESCRIPTION<p>This is a graphics library that is designed to eliminate
much of the pain involved in writing JDOM code tocreate SVG output. The library contains individual
static methods that are used to construct and returnall of the SVG basic shape elements, text elements,
description elements and comment elements.<p>In addition there are methods to set various attributes
on shape elements and text elements.This library provides methods to instantiate, return,
and manipulate the following types of SVG elements:<ul><li>line</li><li>rect</li><li>circle</li><li>ellipse</li><li>polyline</li><li>polygon</li><li>desc</li><li>comment</li><li>text</li></ul><p>Methods that return elements set the stroke attribute
value to black and set the stroke-width attributevalue to 1.<p>All of the methods that accept coordinate values or
dimensions as input require those values to be ininches or fractions thereof. They are then converted
to svg units using a scale factor of 90 svg unitsper inch.<p>All incoming vertical coordinate values are modified
to cause the origin to be at the lower-left corner.Positive x is to the right and positive y is up the
page. Therefore, the user can think in terms of atypical graphing assignment with the origin at the
lower-left corner.<p>One svg unit equals approximately 0.011 inch. An svg
unit is not necessarily the same size as a pixel on amonitor or a printer. However, dimensions specified in
inches should be very close when you print the image.<p>In addition to the methods mentioned above, this library
provides two different methods for writing the final
SVG/XML out to a file. One is named writePrettyFile andthe other is named writeCompactFile.<p>Tested using J2SE 6.0, JDOM 1.1.1, Firefox 5, running
under Windows Vista Home Premius Edition.<p>author: Richard G. Baldwin
*/public class SvgLib21{/*The following instance variable is used to cause the
origin to be at the bottom left corner of thedrawing.
*/private static double svgHeight = 11.0;//----------------------------------------------------///**This method constructs and returns a circle node for
*a given parent in a given namespace. By default,the*stroke is black, the stroke-width is 1, and the fill
*is none. Other methods can be called to change these*default values later.
** @param parent the SVG parent element
* @param namespace the SVG namespace* @param elementTitle the title for IVEO compatibility
* @param cx the x-coordinate of the center in inches* @param cy the y-coordinate of the center in inches
* @param r the radius of the circle in inches*
* @return A reference to an object that represents an*SVG circle element
*/public static Element makeCircle(
Element parent,String namespace,
String elementTitle,double cx,//Center coordinate in inches
double cy,//Center coordinate in inchesdouble r //Radius in inches
){Element circle = new Element("circle",namespace);
parent.addContent(circle);//Set default attribute valescircle.setAttribute("fill","none");
circle.setAttribute("stroke","black");circle.setAttribute("stroke-width","1");//Set user specified attribute values.
int cxInPix = (int)(Math.round(cx*90));int cyInPix =
(int)(Math.round((svgHeight-cy)*90));int rInPix = (int)(Math.round(r*90));
circle.setAttribute("cx",""+cxInPix);circle.setAttribute("cy",""+cyInPix);
circle.setAttribute("r",""+rInPix);//Add a title element for IVEO compatibilityElement title = new Element("title",namespace);
title.addContent(elementTitle);circle.addContent(title);return circle;
}//end makeCircle//----------------------------------------------------///**This method constructs and returns a comment node
*for a given given parent.*
* @param parent the SVG parent element* @param text the text content for this comment element
**@return A reference to an object that represents an
*SVG comment element.*/
public static Comment makeComment(Element parent,//The parent of this element.
String text//Text content for this element.){
Comment comment = new Comment(text);parent.addContent(comment);
return comment;}//end makeComment
//----------------------------------------------------///***DEPRECATED This method has been deprecated Use the
*method named setDescription instead.*
*This method constructs and returns a description node*for a given namespace and a given parent.
** @param parent the SVG parent element
* @param nameSpace the SVG namespace* @param text the text content for this desc element
**@return A reference to an object that represents an
*SVG desc element.*/
public static Element makeDescription(Element parent,//The parent of this element.
String nameSpace,//The namespace.String text//Text content for this element.
){Element desc = new Element("desc",nameSpace);
parent.addContent(desc);desc.setText(text);
return desc;}//end makeDescription
//----------------------------------------------------///**This method constructs and returns an ellipse node
*for a given parent in a given namespace. By default,*the stroke is black, the stroke-width is 1, and the
*fill is none.*
* @param parent the SVG parent element* @param namespace the SVG namespace
* @param elementTitle the title for IVEO compatibility* @param cx the x-coordinate of the center in inches
* @param cy the y-coordinate of the center in inches* @param rx the horizontal radius of the ellipse
* in inches* @param ry the vertical radius of the ellipse
* in inches*
* @return A reference to an object that represents an*SVG ellipse element
*/public static Element makeEllipse(
Element parent,String namespace,
String elementTitle,double cx,//Center coordinate in inches
double cy,//Center coordinate in inchesdouble rx,//Horizontal radius in inches
double ry //Vertical radius in inches){
Element ellipse = new Element("ellipse",namespace);parent.addContent(ellipse);//Set default attribute vales
ellipse.setAttribute("fill","none");ellipse.setAttribute("stroke","black");
ellipse.setAttribute("stroke-width","1");//Set user specified attribute values.int cxInPix = (int)(Math.round(cx*90));
int cyInPix =(int)(Math.round((svgHeight-cy)*90));
int rxInPix = (int)(Math.round(rx*90));int ryInPix = (int)(Math.round(ry*90));
ellipse.setAttribute("cx",""+cxInPix);ellipse.setAttribute("cy",""+cyInPix);
ellipse.setAttribute("rx",""+rxInPix);ellipse.setAttribute("ry",""+ryInPix);//Add a title element for IVEO compatibility
Element title = new Element("title",namespace);title.addContent(elementTitle);
ellipse.addContent(title);return ellipse;}//end makeEllipse
//----------------------------------------------------///**This method constructs and returns a line node for a*given parent in a given namespace. By default, the
*stroke is black and the stroke-width is 1.*
* @param parent the SVG parent element* @param namespace the SVG namespace
* @param elementTitle the title for IVEO compatibility* @param x1 start x-coordinate in inches
* @param y1 start y-coordinate in inches* @param x2 end x-coordinate in inches
* @param y2 end y-coordinate in inches*
* @return A reference to an object that represents an*SVG line element
*/public static Element makeLine(
Element parent,String namespace,
String elementTitle,double x1,//Start coordinate in inches
double y1,//Start coordinate in inchesdouble x2,//End coordinate in inches
double y2 //End coordinate in inches){
Element line = new Element("line",namespace);parent.addContent(line);//Set default attribute vales
line.setAttribute("stroke","black");line.setAttribute("stroke-width","1");//Set user specified attribute values.
int x1InPix = (int)(Math.round(x1*90));int y1InPix =
(int)(Math.round((svgHeight-y1)*90));int x2InPix = (int)(Math.round(x2*90));
int y2InPix =(int)(Math.round((svgHeight-y2)*90));
line.setAttribute("x1",""+x1InPix);line.setAttribute("y1",""+y1InPix);
line.setAttribute("x2",""+x2InPix);line.setAttribute("y2",""+y2InPix);//Add a title element for IVEO compatibility
Element title = new Element("title",namespace);title.addContent(elementTitle);
line.addContent(title);return line;}//end makeLine
//----------------------------------------------------///**This method constructs and returns a polygon node for*a given parent in a given namespace.
*<p>*The array of type double[], which contains the*coordinates for each point in the polygon, must
*contain an even number of values for the polygon*to be drawn correctly. Otherwise, it simply won't be
*drawn.*<p>*The values are extracted from the array, converted
*to svg units as type int,and treated as coordinate
*values x1,y1, x2,y2, x3,y3 ... etc.*<p>*The stroke is set to black one pixel wide with no
*fill.*<p>*The main difference between a polygon and a polyline
*is that a polygon is automatically closed by*connecting the last point to the first point.
** @param parent the SVG parent element
* @param namespace the SVG namespace* @param elementTitle the title for IVEO compatibility
* @param points an array of x-y coordinate pairs in* inches that define the locations of the vertices of
* the polygon.*
* @return A reference to an object that represents an*SVG polygon element
*/public static Element makePolygon(Element parent,
String namespace,String elementTitle,
double[]points){
Element polygon = new Element("polygon",namespace);parent.addContent(polygon);//Set default attributes.
polygon.setAttribute("stroke","black");polygon.setAttribute("stroke-width","1");
polygon.setAttribute("fill","none");//Set user specified attributes.String dataPoints = "";
for(int cnt=0;cnt<points.length;cnt++){
//Correct all of the y coordinates to place the// origin at the bottom left.
if(cnt%2==0){//even values
dataPoints += "" +(int)(Math.round(points[cnt]*90)) + " ";}else{
//odd valuesdataPoints += "" +
(int)(Math.round((svgHeight-points[cnt])
*90)) + " ";}//end else
}//end for looppolygon.setAttribute("points",dataPoints);//Add a title element for IVEO compatibilityElement title = new Element("title",namespace);
title.addContent(elementTitle);polygon.addContent(title);
return polygon;}//end makePolygon
//----------------------------------------------------///**This method constructs and returns a polyline node
*for a given parent in a given namespace.*<p>*The array of type double[], which contains the*coordinates for each point in the polyline, must
*contain an even number of values for the polyline*to be drawn correctly. Otherwise, it simply won't be
*drawn.*<p>*The values are extracted from the array, converted
*to svg units as type int, and treated as coordinate*values x1,y1, x2,y2, x3,y3 ... etc.
*<p>*The stroke is set to black one pixel wide with no
*fill.*<p>*The main difference between a polyline and a polygon
*is that a polygon is automatically closed by*connecting the last point to the first point.
** @param parent the SVG parent element
* @param namespace the SVG namespace* @param elementTitle the title for IVEO compatibility
* @param points an array of x-y coordinate pairs in* inches that define the locations of the end points
* and the vertices of the polyline.*
* @return A reference to an object that represents an*SVG polyline element
*/public static Element makePolyline(Element parent,
String namespace,String elementTitle,
double[]points){
Element polyline = new Element("polyline",namespace);parent.addContent(polyline);
//Set default attributespolyline.setAttribute("stroke","black");
polyline.setAttribute("stroke-width","1");polyline.setAttribute("fill","none");//Set user specified attributes.
String dataPoints = "";for(int cnt=0;cnt<points.length;cnt++){
//Correct all of the y coordinates to place the// origin at the bottom left.
if(cnt%2==0){//even values
dataPoints += "" +(int)(Math.round(points[cnt]*90)) + " ";}else{
//odd valuesdataPoints += "" +
(int)(Math.round((svgHeight-points[cnt])
*90)) + " ";}//end else
}//end for looppolyline.setAttribute("points",dataPoints);//Add a title element for IVEO compatibilityElement title = new Element("title",namespace);
title.addContent(elementTitle);polyline.addContent(title);return polyline;
}//end makePolyline//----------------------------------------------------//
/**This method constructs and returns a rect node for a*given parent in a given namespace. By default,the
*stroke is black, the stroke-width is 1, and the fill*is none.
** @param parent the SVG parent element
* @param namespace the SVG namespace* @param elementTitle the title for IVEO compatibility
* @param x x-coordinate of lower left corner in inches* @param y y-coordinate of lower left corner in inches
* @param width width in inches* @param height height in inches
** @return A reference to an object that represents an
*SVG rect element*/
public static Element makeRect(Element parent,
String namespace,String elementTitle,
double x,//Lower-left corner in inches.double y,//Lower-left corner in inches.
double width,//in inchesdouble height//in inches
){Element rect = new Element("rect",namespace);
parent.addContent(rect);//Set default attribute values.rect.setAttribute("fill","none");
rect.setAttribute("stroke","black");rect.setAttribute("stroke-width","1");//Set user specified attribute values.
int xInPix = (int)(Math.round(x*90));int yInPix =
(int)(Math.round((svgHeight-y-height)*90));int widthInPix = (int)(Math.round(width*90));
int heightInPix = (int)(Math.round(height*90));rect.setAttribute("x",""+xInPix);
rect.setAttribute("y",""+yInPix);rect.setAttribute("width",""+widthInPix);
rect.setAttribute("height",""+heightInPix);//Add a title element for IVEO compatibilityElement title = new Element("title",namespace);
title.addContent(elementTitle);rect.addContent(title);return rect;
}//end makeRect//----------------------------------------------------///**This method constructs and returns a reference to an
*SVG root element node named svg.*
*The svg element represents the canvas on which*various shapes can be drawn. The width and height
*attribute values of the svg element establish the*physical size of the canvas on the screen and on
*the printer.*
*The preserveAspectRatio defaults to none.*
* @param ns the SVG namespace URI* @param documentTitle the title for IVEO compatibility
* @param dWidth the width of the canvas in inches* @param dHeight the height of the canvas in inches
** @return A reference to an SVG element object
*/public static Element makeSvg(
String ns,//namespace URIString documentTitle,
double dWidth,double dHeight
){Element svg = new Element("svg",ns);//Save the height of the canvas. This is used later
// to make corrections to y-coordinate values to put// the origin at the lower-left corner of the canvas.
svgHeight = dHeight;int width = (int)(Math.round(dWidth*90));int height = (int)(Math.round(dHeight*90));//Set default attribute values.
svg.setAttribute("version","1.1");svg.setAttribute("width",""+width);
svg.setAttribute("height",""+height);//Add a title element for IVEO compatibilityElement title = new Element("title",ns);
title.addContent(documentTitle);svg.addContent(title);return svg;
}//end makeSvg//----------------------------------------------------//
/**This method constructs and returns a text node for a*given parent in a given namespace. By default,the
*stroke is black, and the fill is none.*
* @param parent the SVG parent element
* @param namespace the SVG namespace* @param x x-coordinate of lower left corner of first
* character in inches* @param y y-coordinate of lower left corner of first
* character in inches* @param fontFamily font family such as arial
* @param fontSize font size in points such as 32* @param textIn the text to be displayed
** @return A reference to an object that represents an
*SVG text element*/
public static Element makeText(Element parent,
String namespace,double x,//Beginning coordinate in inches
double y,//Beginning coordinate in inchesString fontFamily, //Font face
int fontSize, //font size in pointsString textIn //text to be displayed
){Element text = new Element("text",namespace);
parent.addContent(text);//Set default attribute valuestext.setAttribute("fill","black");
text.setAttribute("stroke","black");//Set user specified attribute values.int xInPix = (int)(Math.round(x*90));
int yInPix = (int)(Math.round((svgHeight-y)*90));text.setAttribute("x",""+xInPix);text.setAttribute("y",""+yInPix);
text.addContent(textIn);text.setAttribute("font-size","" +fontSize);
text.setAttribute("font-family",fontFamily);return text;}//end makeText
//----------------------------------------------------///**This method can be used to set the fill color for
*closed shapes such as rectangles, circles, ellipses,*and polygons. It can also be applied to polylines,
*but the results may not be what you expect.*<p>*The fill color can be set to "none" or to any of the
*color names at*<p><a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a>*<p>*There may be other possibilities as well.
**@param element the element for which the fill will be
*set*@param fillColor the new color for the fill
*/public static void setFill(Element element,
String fillColor){element.setAttribute("fill",fillColor);
}//end setFill//----------------------------------------------------///**This method can be used to set the fill opacity for
*all closed shapes such as rectangles, circles,*ellipses, and polygons.
*<p>*The fill opacity can be set to any value between
*0,0 and 1.0 inclusive, where 0.0 is totally*transparent and 1.0 is totally opaque.
**@param element the element for which the opacity
*will be set*@param opacity the numeric opacity value
*/public static void setFillOpacity(Element element,
double opacity){element.setAttribute("fill-opacity","" + opacity);
}//end setFillOpacity//----------------------------------------------------//
/**This method can be used to set the font style*for text.
*<p>*The font-style can be set to
*<p>*normal | italic | oblique
**@param element the text element for which the font
*style will be set*@param fontStyle the new font style
*/public static void setFontStyle(Element element,
String fontStyle){element.setAttribute("font-style","" + fontStyle);
}//end setFontStyle//----------------------------------------------------//
/**This method can be used to set the font weight*for text.
*<p>*The font-weight can be set to
*<p>*normal | bold | bolder | lighter | 100 | 200 | 300|
*400 | 500 | 600 | 700 | 800 | 900 |*
*@param element the text element for which the font*weight will be set
*@param fontWeight the new font weight*/
public static void setFontWeight(Element element,String fontWeight){
element.setAttribute("font-weight","" + fontWeight);}//end setFontWeight
//----------------------------------------------------///**This method can be used to set the stroke color for
*all shapes.*<p>*The stroke color can be set to "none" or any of the
*color names at*<p><a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a>*<p>*There may be other possibilities as well.
**@param element the element for which the stroke color
*will be set*@param strokeColor the new stroke color
*/public static void setStroke(Element element,
String strokeColor){element.setAttribute("stroke",strokeColor);
}//end setStroke//----------------------------------------------------//
/**This method can be used to set the stroke opacity*for all shapes.
*<p>*The stroke opacity can be set to any value between
*0,0 and 1.0 inclusive, where 0.0 is totally*transparent and 1.0 is totally opaque.
**@param element the element for which the stroke color
*will be set*@param opacity the numeric opacity value
*/public static void setStrokeOpacity(Element element,
double opacity){element.setAttribute("stroke-opacity","" + opacity);
}//end setStrokeOpacity//----------------------------------------------------///**This method can be used to set the stroke width
*for rectangles, circles, ellipses, lines, polylines,*and polygons.
**@param element the element for which the stroke color
*will be set*@param widthInInches the new stroke width in inches
*or parts thereof*/
public static void setStrokeWidth(Element element,double widthInInches){
//Scale and round the double width value to an// int value in svg units where there are 90 svg
// units per inch.int widthInPix =
(int)(Math.round(widthInInches*90));element.setAttribute("stroke-width","" + widthInPix);
}//end setStrokeWidth//----------------------------------------------------///**This method can be used to add a description<desc>*element to any other element
** @param parent the element to which the description
*will be added* @param namespace the SVG namespace
*@param description the text for the new description.*/
public static void setDescription(Element parent,String namespace,
String description){Element desc = new Element("desc",namespace);
parent.addContent(desc);desc.addContent(description);
}//end setStrokeWidth//----------------------------------------------------///**This method writes the SVG code into an output file
*in whitespace-normalized format, which is more*efficient than the prettyPrint format.
*@param fname path and name of output SVG file*including the .svg filename extension
*@param doc a reference to an object of type Document*which was instantiated as
*<p>*new Document(svg,docType)
*<p>*where svg is the root element of the SVG document
*<p>*and docType was instantiated as
*<p>*DocType docType = new DocType(
* dtdConstrainedElement,dtdPublicID,dtdSystemID);*/
public static void writeCompactFile(String fname, Document doc){
try{FileOutputStream out = new FileOutputStream(fname);
XMLOutputter xmlOut =new XMLOutputter(Format.getCompactFormat());
xmlOut.output(doc,out);out.flush();
out.close();}catch (IOException e){
System.err.println(e);}//end catch
}//end writePrettyFile//----------------------------------------------------//
/**This method writes the SVG code into an output file*in pretty-print format. The pretty-print format
*is less efficient than the compact format, but it*is very useful during test and debugging because
*you can view source in your browser and the XML
*code will be reasonably well formatted.*<p>*Note that the extension is automatically appended to
*the output file name, so it should not be included*in the file name input parameter.
**@param fname path and name of output SVG file
*excluding the .svg filename extension*@param doc a reference to an object of type Document
*which was instantiated as*<p>*new Document(svg,docType)
*<p>*where svg is the root element of the SVG document
*<p>*and docType was instantiated as
*<p>*DocType docType = new DocType(
* dtdConstrainedElement,dtdPublicID,dtdSystemID);*/
public static void writePrettyFile(String fname, Document doc){
try{FileOutputStream out =
new FileOutputStream(fname + ".svg");XMLOutputter xmlOut =
new XMLOutputter(Format.getPrettyFormat());xmlOut.output(doc,out);
out.flush();out.close();
}catch (IOException e){System.err.println(e);
}//end catch}//end writePrettyFile
//----------------------------------------------------//}//end class SvgLib21 |
Notification Switch
Would you like to follow the 'Accessible physics concepts for blind students' conversation and receive update notifications?