/* * 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. ) */ protected String headerString(DrawFrame drawFrame) { StringBuffer output = new StringBuffer(); // output.append(""+"\n"); // this is causing access denied in parse xml, applet can access only its own server // output.append(""+"\n"); Hashtable hash = (Hashtable) (DrawControl.drawSettings.get(DrawControl.OPTIONS)); double xMin = ((Double) hash.get("x_min")).doubleValue(); double xMax = ((Double) hash.get("x_max")).doubleValue(); double yMin = ((Double) hash.get("y_min")).doubleValue(); double yMax = ((Double) hash.get("y_max")).doubleValue(); // i guess it wants width and hight output.append("" + "\n"); return output.toString(); } /** * set height (used to change java coordinates to world coord) * @param double height */ protected void setHeight(double height) { this.height = height; } /** * set y (used to change java coordinates to world coord) * @param double y */ protected void setY(double y) { this.y = y; } /** * get end of svg document * @return String () */ protected String footerString() { return "" + "\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; } }