/*
* SVGDocument.java
*
* Created on August 25, 2005, 1:46 AM
*
*/
package draw4free.xml;
import draw4free.cont.DrawControl;
import draw4free.tools.*;
import draw4free.styling.*;
import java.awt.*;
import draw4free.frame.DrawFrame;
import java.util.Hashtable;
import java.util.Vector;
/**
*
* @author Stanislav Hromek
*/
public class SVGDocument extends XMLDocument {
private double y, height;
/** Creates a new instance of SVGDocument */
public SVGDocument() {
}
/**
* create svg header
* @param drawFrame
* @return String (eg. " + "\n";
}
/**
* name of layer, as each layer represents a element
* just name or name and all parents names ?
* @param ml
* @return
*/
protected String idString(MultiLayer ml) {
return "" + "\n";
}
/**
* end of id element
* @return String end of group tag ()
*/
protected String endIdString() {
return "" + "\n";
}
// shapes
/**
* get circle string
* @param gCircle
* @return String (eg. )
*/
protected String circleString(GCircle gCircle) {
StringBuffer output = new StringBuffer();
output.append("" + "\n");
//output.append("");
return output.toString();
}
/**
* point element, as svg doesn't have a point, is given as line with the same points
* @param gPoint
* @return String (eg. )
*/
protected String pointString(GPoint gPoint) {
// svg doesn't have a point, my idea is line starting and ending in the same point
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* arc element (with move)
*
* @see http://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
* @param gArc
* @return String eg.
*/
protected String arcString(GArc gArc) {
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* ellipse element
* @param gEllipse
* @return String eg.
*/
protected String ellipseString(GEllipse gEllipse) {
// eg.
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* rotation for ellipse element, translation not used
* @param gEllipse
* @return String transform="translate(900 200) rotate(-30)"
*/
protected String rotationString(GEllipse gEllipse) {
// eg.
*/
protected String polygonString(GPolygon gPolygon) {
// almost the same code as polyline, refactor ?
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* polyline element
* @param gPolyline
* @return String eg.
*/
protected String polylineString(GPolyline gPolyline) {
// eg.
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* curve element
* @param gCurve
* @return String eg.
* @see http://www.w3.org/TR/SVG/index.html#minitoc
*/
protected String curveString(GCurve gCurve) {
// different formats, see http://www.w3.org/TR/SVG/index.html#minitoc
// eg.
StringBuffer output = new StringBuffer();
output.append("" + "\n");
return output.toString();
}
/**
* text element
* @param gText
* @return String eg. Row, row, row your boat ...
*/
protected String textString(GText gText) {
// eg. Row, row, row your boat ...
StringBuffer output = new StringBuffer();
output.append("");
for (int i = 0; i < gText.getText().length; i++) {
output.append(gText.getText()[i]);
// add line separator ?
if (i > 0) {
output.append("\n");
}
}
output.append("" + "\n");
return output.toString();
}
/**
* group element (in 1.2 svg ?, can be used for 1.1 too, but for joined elements)
* unfortunately in SVG 1.1 we can not do it this way, can it be in 1.2 ?,
* then add java handling shapes
* @param gGroup
* @return StringBuffer
*/
protected StringBuffer groupStringBodySVG12(GGroup gGroup) {
StringBuffer output = new StringBuffer("");
for (int i = 0; i < gGroup.getShapeList().size(); i++) {
Object gShape = gGroup.getShapeList().get(i);
if (gShape instanceof GCircle) {
output.append(circleString((GCircle) gShape));
} else if (gShape instanceof GPoint) {
output.append(pointString((GPoint) gShape));
} else if (gShape instanceof GArc) {
output.append(arcString((GArc) gShape));
} else if (gShape instanceof GEllipse) {
output.append(ellipseString((GEllipse) gShape));
} else if (gShape instanceof GPolygon) {
output.append(polygonString((GPolygon) gShape));
} else if (gShape instanceof GPolyline) // is it closed or opened group ?, we need right order for closed
{
output.append(polylineString((GPolyline) gShape));
} else if (gShape instanceof GCurve) {
output.append(curveString((GCurve) gShape));
} else if (gShape instanceof GText) {
output.append(textString((GText) gShape));
} else if (gShape instanceof GGroup) // not joined takes join flag from each subgroup
{
output.append(groupString((GGroup) gShape, ((GGroup) gShape).getJoin()));
}
}
return output;
}
/**
* sets style fill value in style to none
* @param style
* @return String "fill: rgb(0,0,255);" will be replaced with "fill: none;"
*/
protected String replaceFill(String style) {
// eg.style=\" fill-rule: evenodd; fill: none; stroke: rgb(0,0,255); stroke-width: 1.0; stroke-linecap: square; stroke-linejoin: miter; stroke-miterlimit: 10.0;
int fillIndex = style.indexOf("fill :");
// happens by test when we dont have style, test for this added by calling this method
if (fillIndex < 0) {
return style;
} // this should never happen, assert
String s1 = style.substring(0, fillIndex);
String s2 = "fill: none";
String s3 = style.substring(style.indexOf(";", fillIndex));
return s1 + s2 + s3;
}
/**
* temporary variable needed for group element
*/
StringBuffer textGroupTemp;
/**
* group element
* @param gGroup
* @param isGroupJoined
* @return String
*/
protected String groupString(GGroup gGroup, boolean isGroupJoined) {
// if upper level joined is true, then all groups joined, othersides joined parameter taken from under lying group
textGroupTemp = new StringBuffer();
StringBuffer output = new StringBuffer();
output.append("" + "\n");
// if group not joined, format like 1.2, see upper
if (isGroupJoined) {
// it is first in group element (polyline, curve or not filled arc (todo open arc))
output.append("" + "\n");
output.append("");
} else {
output.append(groupStringBodySVG12(gGroup));
}
// todo add text = textGroupTemp
if (textGroupTemp.length() > 0) {
// System.out.println("textGroupTemp.length()="+textGroupTemp.length());
output.append(textGroupTemp + "\n");
}
output.append("" + "\n");
return output.toString();
}
/**
* group element (we have two methods groupStringBody and groupStringBodySVG12)
* @param gGroup
* @param isFirstElement
* @return StringBuffer
*/
protected StringBuffer groupStringBody(GGroup gGroup, boolean isFirstElement) {
StringBuffer groupPathBody = new StringBuffer("");
// add Z
boolean addZ = false;
for (int i = 0; i < gGroup.getShapeList().size(); i++) {
Object gShape = gGroup.getShapeList().get(i);
if (gShape instanceof GCircle) {
// todo, add addZ to each (except text) ?
addZ = true;
groupPathBody.append(groupCircleString((GCircle) gShape));
} else if (gShape instanceof GPoint) {
groupPathBody.append(groupPointString((GPoint) gShape));
} else if (gShape instanceof GArc) {
boolean takePointsFromStart = ((Boolean) gGroup.getPointsFromStart().get(i)).booleanValue();
groupPathBody.append(groupArcString((GArc) gShape, isFirstElement, takePointsFromStart, true));
isFirstElement = false;
} else if (gShape instanceof GEllipse) {
groupPathBody.append(groupEllipseString((GEllipse) gShape));
} else if (gShape instanceof GPolygon) {
groupPathBody.append(groupPolygonString((GPolygon) gShape));
} else if (gShape instanceof GPolyline) {
addZ = true;
boolean takePointsFromStart = ((Boolean) gGroup.getPointsFromStart().get(i)).booleanValue();
groupPathBody.append(groupPolylineString((GPolyline) gShape, isFirstElement, takePointsFromStart, true));//isTopGroupJoined? true:gGroup.getJoin()
isFirstElement = false;
} else if (gShape instanceof GCurve) {
addZ = true;
boolean takePointsFromStart = ((Boolean) gGroup.getPointsFromStart().get(i)).booleanValue();
groupPathBody.append(groupCurveString((GCurve) gShape, isFirstElement, takePointsFromStart, true)); //isTopGroupJoined? true:gGroup.getJoin()
isFirstElement = false;
} else if (gShape instanceof GText) {
textGroupTemp.append(textString((GText) gShape));
} else if (gShape instanceof GGroup) {
boolean first = true; //isTopGroupJoined? true:gGroup.getJoin();
if (first && addZ) {
groupPathBody.append(" Z");
}
addZ = false;
// ?
//question, this is good if always are lies and curves in group first,
// and then are shapes as polygons , ..., and GROUP, is it always so ??? (I think group tidies it this way)
groupPathBody.append(groupStringBody((GGroup) gShape, true));
}
}
// if joined elements, we have to add Z to close it (close and joined should be independent, now together because of clipping problems)
boolean first = true; //isTopGroupJoined? true:gGroup.getJoin();
if (first && addZ) {
groupPathBody.append(" Z");
}
return groupPathBody;
}
/**
* piece of group for one point
* @param gPoint
* @return String eg. M 3 4 L 5 6
*/
protected String groupPointString(GPoint gPoint) {
// i think point should be as polyline or curve, by clicking points,
// creating group and joined elements in group, it should join points, think
StringBuffer output = new StringBuffer();
output.append(" M " + gPoint.getX() + " " + this.convertY(gPoint.getY()));
output.append(" L " + gPoint.getX() + " " + this.convertY(gPoint.getY()));
return output.toString();
}
/**
* arc element
* @param gArc
* @param isFirstElement
* @param fromStart
* @param joinedElements
* @return String
*/
protected String groupArcString(GArc gArc, boolean isFirstElement, boolean fromStart, boolean joinedElements) {
// for now only closed standalone element, in the future when not fill, like line or curve
// refactor, the same as in arcString()
StringBuffer output = new StringBuffer();
if (isFirstElement) {
// svg arc
output.append(moveArcString(gArc, fromStart)); // starts with M
} else {
if (fromStart) {
if (joinedElements) {
// change L to Q for identification, control point the same as point, its just line
output.append(" Q " + gArc.getStartPoint().getX() + " " + this.convertY(gArc.getStartPoint().getY()));
output.append(" " + gArc.getStartPoint().getX() + " " + this.convertY(gArc.getStartPoint().getY()));
output.append(rawArcString(gArc, fromStart));
} else // svg arc
{
output.append(moveArcString(gArc, fromStart));
} // starts with M
} else {
// todo, solve if not from start
if (joinedElements) {
// change L to Q for identification, control point the same as point, its just line
output.append(" Q " + gArc.getEndPoint().getX() + " " + this.convertY(gArc.getEndPoint().getY()));
output.append(" " + gArc.getEndPoint().getX() + " " + this.convertY(gArc.getEndPoint().getY()));
output.append(rawArcString(gArc, fromStart));
} else // svg arc
{
output.append(moveArcString(gArc, fromStart));
} // starts with M
}
}
return output.toString();
}
/**
* move arc element
* @param gArc
* @param fromStart
* @return String
*/
protected String moveArcString(GArc gArc, boolean fromStart) {
StringBuffer output = new StringBuffer();
// move ( = not joined element)
output.append(moveTo(gArc, fromStart));
// arc
output.append(rawArcString(gArc, fromStart));
return output.toString();
}
/**
* submethod for move arc element
* @param gArc
* @param fromStart
* @return String eg. M 3 4
*/
protected String moveTo(GArc gArc, boolean fromStart) {
StringBuffer output = new StringBuffer();
// m start point (sometimes)
output.append("M ");
if (fromStart) {
output.append(gArc.getStartPoint().getX() + " " + this.convertY(gArc.getStartPoint().getY()));
} else {
output.append(gArc.getEndPoint().getX() + " " + this.convertY(gArc.getEndPoint().getY()));
}
return output.toString();
}
// protected String lineArcString(GArc gArc, GPoint point){
// StringBuffer output = new StringBuffer();
// // fictive line ( = joined element)
// output.append(qTo(gArc, point));
// // arc
// output.append(rawArcString(gArc, fromStart));
//
// return output.toString();
// }
/**
* arc element (only arc values)
* @param gArc
* @param fromStart
* @return String eg. A 150.0,150.0 0 0,0 0.0 -200
*/
protected String rawArcString(GArc gArc, boolean fromStart) {
StringBuffer output = new StringBuffer();
output.append(" A ");
// radius
output.append(gArc.getRadius() + "," + gArc.getRadius());
// x-axis rotation
output.append(" 0");
// large-arc-flag
if (gArc.getArcAngle() > 180) {
output.append(" 1");
} else {
output.append(" 0");
}
// sweep-flag
// sweep-flag
// we always draw in negative direction, todo, positive, egative angle, now i think is not the same
// se properties, where is angle (arc, ellipse, text) in world possitive should be against watch handles
if (fromStart) {
output.append(",0 ");
// if from start, arc need the end point at the end of its string
output.append(gArc.getEndPoint().getX() + " " + this.convertY(gArc.getEndPoint().getY()));
} else {
output.append(",1 ");
output.append(gArc.getStartPoint().getX() + " " + this.convertY(gArc.getStartPoint().getY()));
}
return output.toString();
}
/**
* circle in group element ()
* @param gCircle
* @return
*/
protected String groupCircleString(GCircle gCircle) {
StringBuffer output = new StringBuffer();
output.append(" M ");
// we start at left point
output.append((gCircle.getX() - gCircle.getRadius()) + "," + this.convertY(gCircle.getY()));
output.append(" A");
// radius
output.append(gCircle.getRadius() + "," + gCircle.getRadius());
// x-axis rotation
output.append(" 0");
// large-arc-flag
output.append(" 1");
// sweep-flag
output.append(",0 ");
// right point
output.append((gCircle.getX() + gCircle.getRadius()) + "," + this.convertY(gCircle.getY()));
output.append(" A");
// radius
output.append(gCircle.getRadius() + "," + gCircle.getRadius());
// x-axis rotation
output.append(" 0");
// large-arc-flag
output.append(" 1");
// sweep-flag
output.append(",0 ");
// back to left point
output.append((gCircle.getX() - gCircle.getRadius()) + "," + this.convertY(gCircle.getY()));
// output.append(" Z");
return output.toString();
}
/**
* ellipse in group
* @param gEllipse
* @return String
*/
protected String groupEllipseString(GEllipse gEllipse) {
if(gEllipse == null) return "";
// center, top, right, bottom, left
Vector selectPoints = gEllipse.getSelectPoints();
GPoint left = ((GPoint) selectPoints.get(4));
GPoint right = ((GPoint) selectPoints.get(2));
StringBuffer output = new StringBuffer();
output.append(" M ");
// we start at left point (meaned by by zero angle, by angle it could be easily right one)
output.append(left.getX() + "," + this.convertY(left.getY()));
output.append(" A");
// axises, abstract or ba ?
output.append(gEllipse.getB() + "," + gEllipse.getA());
// x-axis rotation
output.append(" " + gEllipse.getAngle());
// large-arc-flag
output.append(" 1");
// sweep-flag
output.append(",0 ");
// right point
output.append(right.getX() + "," + this.convertY(right.getY()));
output.append(" A");
// axises
output.append(gEllipse.getB() + "," + gEllipse.getA());
// x-axis rotation
output.append(" " + gEllipse.getAngle());
// large-arc-flag
output.append(" 1");
// sweep-flag
output.append(",0 ");
// back to left point
output.append(left.getX() + "," + this.convertY(left.getY()));
// output.append(" Z");
return output.toString();
}
/**
* polygon in group
* @param gPolygon
* @return String
*/
protected String groupPolygonString(GPolygon gPolygon) {
StringBuffer output = new StringBuffer();
output.append(" M " + gPolygon.xpoints[0] + " " + this.convertY(gPolygon.ypoints[0]));
// first is always from start , this if and else useless
for (int j = 1; j < gPolygon.xpoints.length; j++) {
output.append(" L " + gPolygon.xpoints[j] + " " + this.convertY(gPolygon.ypoints[j]));
}
output.append(" L " + gPolygon.xpoints[0] + " " + this.convertY(gPolygon.ypoints[0]) + " Z");
return output.toString();
}
/**
* polyline in group
* @param gPolyline
* @param isFirstElement
* @param fromStart
* @param joinedElements
* @return String
*/
protected String groupPolylineString(GPolyline gPolyline, boolean isFirstElement, boolean fromStart, boolean joinedElements) {
StringBuffer output = new StringBuffer();
if (isFirstElement) {
output.append(" M " + gPolyline.xpoints[0] + " " + this.convertY(gPolyline.ypoints[0]));
// first is always from start , this if and else useless
for (int j = 1; j < gPolyline.xpoints.length; j++) {
output.append(" L " + gPolyline.xpoints[j] + " " + this.convertY(gPolyline.ypoints[j]));
}
} else {
if (fromStart) {
if (joinedElements) {
// change L to Q for identification, control point the same as point, its just line
output.append(" Q " + gPolyline.xpoints[0] + " " + this.convertY(gPolyline.ypoints[0]));
output.append(" " + gPolyline.xpoints[0] + " " + this.convertY(gPolyline.ypoints[0]));
} else {
output.append(" M " + gPolyline.xpoints[0] + " " + this.convertY(gPolyline.ypoints[0]));
}
for (int j = 1; j < gPolyline.xpoints.length; j++) {
output.append(" L " + gPolyline.xpoints[j] + " " + this.convertY(gPolyline.ypoints[j]));
}
} else {
if (joinedElements) {
// change L to Q for identification, control point the same as point, its just line
output.append(" Q " + gPolyline.xpoints[gPolyline.xpoints.length - 1] + " " + this.convertY(gPolyline.ypoints[gPolyline.xpoints.length - 1]));
output.append(" " + gPolyline.xpoints[gPolyline.xpoints.length - 1] + " " + this.convertY(gPolyline.ypoints[gPolyline.xpoints.length - 1]));
} else {
output.append(" M " + gPolyline.xpoints[gPolyline.xpoints.length - 1] + " " + this.convertY(gPolyline.ypoints[gPolyline.xpoints.length - 1]));
}
for (int j = gPolyline.xpoints.length - 2; j >= 0; j--) {
output.append(" L " + gPolyline.xpoints[j] + " " + this.convertY(gPolyline.ypoints[j]));
}
}
}
return output.toString();
}
/**
* curve in group
* @param gCurve
* @param isFirstElement
* @param fromStart
* @param joinedElements
* @return String
*/
protected String groupCurveString(GCurve gCurve, boolean isFirstElement, boolean fromStart, boolean joinedElements) {
double[] tempX = gCurve.getX();
double[] tempY = gCurve.getY();
double[] tempFirstControlX = gCurve.getFirstCtrlX();
double[] tempFirstControlY = gCurve.getFirstCtrlY();
double[] tempSecondControlX = gCurve.getSecondCtrlX();
double[] tempSecondControlY = gCurve.getSecondCtrlY();
StringBuffer output = new StringBuffer();
if (isFirstElement) {
output.append(" M " + tempX[0] + " " + this.convertY(tempY[0]));
// first is always from start
// start at one
for (int j = 1; j < tempX.length; j++) {
output.append(" C " + tempSecondControlX[j - 1] + " " + this.convertY(tempSecondControlY[j - 1]));
output.append(" " + tempFirstControlX[j] + " " + this.convertY(tempFirstControlY[j]));
output.append(" " + tempX[j] + " " + this.convertY(tempY[j]));
}
} else {
if (fromStart) {
if (joinedElements) {
// change L to Q for identification
output.append(" Q " + tempX[0] + " " + this.convertY(tempY[0]));
output.append(" " + tempX[0] + " " + this.convertY(tempY[0]));
} else {
output.append(" M " + tempX[0] + " " + this.convertY(tempY[0]));
}
for (int j = 1; j < tempX.length; j++) {
output.append(" C " + tempSecondControlX[j - 1] + " " + this.convertY(tempSecondControlY[j - 1]));
output.append(" " + tempFirstControlX[j] + " " + this.convertY(tempFirstControlY[j]));
output.append(" " + tempX[j] + " " + this.convertY(tempY[j]));
}
} else {
if (joinedElements) {
// change L to Q for identification
output.append(" Q " + tempX[tempX.length - 1] + " " + this.convertY(tempY[tempX.length - 1]));
output.append(" " + tempX[tempX.length - 1] + " " + this.convertY(tempY[tempX.length - 1]));
} else {
output.append(" M " + tempX[tempX.length - 1] + " " + this.convertY(tempY[tempX.length - 1]));
}
for (int j = tempX.length - 1; j > 0; j--) {
output.append(" C " + tempFirstControlX[j] + " " + this.convertY(tempFirstControlY[j]));
output.append(" " + tempSecondControlX[j - 1] + " " + this.convertY(tempSecondControlY[j - 1]));
output.append(" " + tempX[j - 1] + " " + this.convertY(tempY[j - 1]));
}
}
}
return output.toString();
}
/*
} else if(gShape instanceof GCurve){
// refactor, test
if(debug)System.out.println("GroupLayer: paintScaled: found curve");
int[] firstPoint, lastPoint, secondControlOfFirstPoint, firstControlOfSecondPoint, secondPoint=null;
GCurve gCurve = (GCurve)gShape;
// we need point for curve
double[] tempX = gCurve.getX();
double[] tempY = gCurve.getY();
double[] tempFirstControlX = gCurve.getFirstCtrlX();
double[] tempFirstControlY = gCurve.getFirstCtrlY();
double[] tempSecondControlX = gCurve.getSecondCtrlX();
double[] tempSecondControlY = gCurve.getSecondCtrlY();
for(int k = 0; k0; j--){
// and change them to graphics from world
secondControlOfFirstPoint = scale.toGraphics(tempSecondControlX[j-1], tempSecondControlY[j-1]);
secondPoint = scale.toGraphics(tempX[j-1], tempY[j-1]);
firstControlOfSecondPoint = scale.toGraphics(tempFirstControlX[j], tempFirstControlY[j]);
generalPathCurves.curveTo(firstControlOfSecondPoint[0], firstControlOfSecondPoint[1],
secondControlOfFirstPoint[0], secondControlOfFirstPoint[1],
secondPoint[0], secondPoint[1]);
}
}
}
*/
/**
* get line style
* @param style
* @return String
*/
protected String getLineStyle(Style style) {
// test for null
if (style == null || style.getStroke() == null) {
return null; // return some default ?
}
StringBuffer output = new StringBuffer();
// stroke
output.append(getStrokeColor(style));
// stroke-width
output.append(getStrokeWidth(style.getStroke()));
// stroke-linecap
output.append(getLineCap(style.getStroke()));
// stroke-linejoin
output.append(getLineJoin(style.getStroke()));
// mitterlimit
output.append(getMiterlimit(style.getStroke()));
// dasharray
output.append(getDasharray(style.getStroke()));
return output.toString();
}
/**
* get style
* @param style
* @return String
*/
protected String getStyle(Style style) {
if (style == null) {
return "";
} // is never, but is convinient for test
StringBuffer output = new StringBuffer();
output.append(" style=\"");
if (style instanceof PolygonStyle) {
output.append(getPolygonStyle((PolygonStyle) style));
} else if (style instanceof LineStyle) {
output.append(getLineStyle((LineStyle) style));
} else if (style instanceof TextStyle) {
output.append(getTextStyle((TextStyle) style));
} else // assert ?
{
return "";
}
output.append("\"");
return output.toString();
}
/**
* get polygon style
* @param style
* @return String
*/
protected String getPolygonStyle(PolygonStyle style) {
StringBuffer output = new StringBuffer();
// fill
output.append(getFillColor(style));
output.append(getLineStyle(style));
return output.toString();
}
/**
* get text style (line width = 0.0 and not 1.0,
* line width in draw4free not implemented, only fill taken
* after it is imlemented, delete getTextLineStyle and use getLineStyle)
* @param style
* @return String
*/
protected String getTextStyle(TextStyle style) {
StringBuffer output = new StringBuffer();
// todo, fill
//output.append(getFillColor(style));
// todo, line width = 0.0 and not 1.0, line width in draw4free not implemented, only fill taken
// after it is imlemented, delete getTextLineStyle and use getLineStyle
output.append(getTextLineStyle(style));
output.append(getFontFamily(style));
output.append(getFontWeight(style));
output.append(getFontStyle(style));
output.append(getFontHeight(style));
return output.toString();
}
/**
* get text line style
* @param style
* @return String
*/
protected String getTextLineStyle(Style style) {
// test for null
if (style == null || style.getStroke() == null) {
return null; // return some default ?
}
StringBuffer output = new StringBuffer();
// stroke
output.append(getStrokeColor(style));
// stroke-width
output.append(" stroke-width: 0.0;");
// stroke-linecap
output.append(getLineCap(style.getStroke()));
// stroke-linejoin
output.append(getLineJoin(style.getStroke()));
// mitterlimit
output.append(getMiterlimit(style.getStroke()));
// dasharray
output.append(getDasharray(style.getStroke()));
return output.toString();
}
/**
* get font family
* @param style
* @return String
*/
protected String getFontFamily(TextStyle style) {
StringBuffer output = new StringBuffer();
if (style.getFont() == null) {
output.append("");
} else {
output.append(" font-family: ");
output.append(style.getFont().getFamily());
output.append(";");
}
return output.toString();
}
/**
* get font height
* @param textStyle
* @return String
*/
protected String getFontHeight(TextStyle textStyle) {
StringBuffer output = new StringBuffer();
if (textStyle.getFont() == null) {
output.append("");
} else {
output.append(" font-size: ");
// todo, test, if it is what we want
output.append(textStyle.getHeight());
output.append(";");
}
return output.toString();
}
/**
* get font style
* @param style
* @return String
*/
protected String getFontStyle(TextStyle style) {
StringBuffer output = new StringBuffer();
if (style.getFont() == null) {
output.append("");
} else {
output.append(" font-style: ");
//
if (style.getFont().isItalic()) {
output.append("italic");
} else {
output.append("normal");
}
output.append(";");
}
return output.toString();
}
/**
* get font weight
* @param style
* @return String
*/
protected String getFontWeight(TextStyle style) {
StringBuffer output = new StringBuffer();
if (style == null || style.getFont() == null) {
output.append("");
} else {
output.append(" font-weight: ");
//
if (style.getFont().isBold()) {
output.append("bold");
} else {
output.append("normal");
}
output.append(";");
}
return output.toString();
}
/**
* get fill color
* @param style
* @return String
*/
protected String getFillColor(PolygonStyle style) {
StringBuffer output = new StringBuffer();
// fill, change to shorter form ?
if (style.getFillColor() == null) {
output.append(" fill: none;");
} else {
// fill rule should be defined in style ?
output.append(" fill-rule: evenodd;");
output.append(" fill: rgb(");
output.append(style.getFillColor().getRed());
output.append(",");
output.append(style.getFillColor().getGreen());
output.append(",");
output.append(style.getFillColor().getBlue());
output.append(");");
}
return output.toString();
}
/**
* get stroke color
* @param style
* @return String
*/
protected String getStrokeColor(Style style) {
StringBuffer output = new StringBuffer();
// stroke
if (style.getLineColor() == null) {
output.append(" stroke: none;");
} else {
output.append(" stroke: rgb(");
output.append(style.getLineColor().getRed());
output.append(",");
output.append(style.getLineColor().getGreen());
output.append(",");
output.append(style.getLineColor().getBlue());
output.append(");");
}
return output.toString();
}
/**
* get line width
* @param style
* @return String
*/
protected String getStrokeWidth(Stroke stroke) {
// test for null
if (stroke == null || !(stroke instanceof BasicStroke)) {
return "";
}
StringBuffer output = new StringBuffer();
output.append(" stroke-width: ");
output.append(((BasicStroke) stroke).getLineWidth());
output.append(";");
return output.toString();
}
/**
* get line cap
* @param style
* @return String
*/
protected String getLineCap(Stroke stroke) {
// test for null
if (stroke == null || !(stroke instanceof BasicStroke)) {
return "";
}
StringBuffer output = new StringBuffer();
output.append(" stroke-linecap: ");
if (((BasicStroke) stroke).getEndCap() == 0) {
output.append("butt");
} else if (((BasicStroke) stroke).getEndCap() == 1) {
output.append("round");
} else if (((BasicStroke) stroke).getEndCap() == 2) {
output.append("square");
}
output.append(";");
return output.toString();
}
/**
* get line join
* @param style
* @return String
*/
protected String getLineJoin(Stroke stroke) {
// test for null
if (stroke == null || !(stroke instanceof BasicStroke)) {
return "";
}
StringBuffer output = new StringBuffer();
output.append(" stroke-linejoin: ");
if (((BasicStroke) stroke).getLineJoin() == 0) {
output.append("miter");
} else if (((BasicStroke) stroke).getLineJoin() == 1) {
output.append("round");
} else if (((BasicStroke) stroke).getLineJoin() == 2) {
output.append("bevel");
}
output.append(";");
return output.toString();
}
/**
* get miter limit
* @param style
* @return String
*/
protected String getMiterlimit(Stroke stroke) {
// test for null
if (stroke == null || !(stroke instanceof BasicStroke)) {
return "";
}
StringBuffer output = new StringBuffer();
output.append(" stroke-miterlimit: ");
output.append(((BasicStroke) stroke).getMiterLimit());
output.append(";");
return output.toString();
}
/**
* get dash array
* @param style
* @return String
*/
protected String getDasharray(Stroke stroke) {
// test for null
if (stroke == null ||
!(stroke instanceof BasicStroke) ||
((BasicStroke) stroke).getDashArray() == null) {
return "";
}
StringBuffer output = new StringBuffer();
output.append(" stroke-dasharray: ");
for (int i = 0; i < ((BasicStroke) stroke).getDashArray().length; i++) {
if (i != 0) {
output.append(",");
}
output.append(((BasicStroke) stroke).getDashArray()[i]);
}
output.append(";");
return output.toString();
}
/**
* SVG is like java, y coordinate starts in upper left corner and goes down
* basicly, this should be somewhere as class Scaler, the reason why is here is as folowes
* only his class uses it, there is only translation, no scale, independency from scale,
* takes input coord. (now map extent, will change in future, eg. A4 format), encapsulation
* @param worldY
* @return
*/
protected double convertY(double worldY) {
// converted y is height minus y
return y + height - worldY;
}
}