Java tutorial
/*********************************************************************** * Copyright (c) 2005, 2006 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation ***********************************************************************/ package org.eclipse.birt.chart.device.svg; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.RenderingHints.Key; import java.awt.Shape; import java.awt.Stroke; import java.awt.TexturePaint; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.font.TextAttribute; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.io.ByteArrayOutputStream; import java.text.AttributedCharacterIterator; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import javax.imageio.IIOImage; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import org.apache.commons.codec.binary.Base64; import org.eclipse.birt.chart.device.ImageWriterFactory; import org.eclipse.birt.chart.device.svg.i18n.Messages; import org.eclipse.birt.chart.device.util.ChartGraphics2D; import org.eclipse.birt.chart.log.ILogger; import org.eclipse.birt.chart.log.Logger; import org.eclipse.birt.chart.util.SecurityUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * This class provides the graphic context to draw primitive svg drawing * elements such as lines, rectangles, polygons, etc. */ public class SVGGraphics2D extends ChartGraphics2D { protected Document dom; protected Paint paint; protected Color color; protected Font font; protected Shape clip; protected Stroke stroke; protected Color background; protected Element currentElement; protected Stack<Element> parentStack = new Stack<Element>(); protected Element currentParent; protected FontRenderContext fontRenderContext; protected AffineTransform transforms; protected List<SVGGradientPaint> paints = new ArrayList<SVGGradientPaint>(); protected Set<TexturePaint> textures = new HashSet<TexturePaint>(); protected Element definitions; protected Element styles; protected Element codeScript; protected String styleClass; protected String id; protected StringBuffer scriptBuffer = new StringBuffer(); protected StringBuffer styleBuffer = new StringBuffer(); protected Element deferStrokColor = null; protected String primitiveId = null; private RenderingHints renderingHints = new RenderingHints(null); protected boolean scriptable = true; protected static final String defaultStyles = "fill:none;stroke:none"; //$NON-NLS-1$ // Unicode Bidi Control char protected static final char chRLE = '\u202b'; // RIGHT-TO-LEFT EMBEDDING protected static final char chPDF = '\u202c'; // POP DIRECTIONAL FORMATTING // Style of text to support bidi protected static final String sStyleBidi = "direction:rtl; unicode-bidi:embed; "; //$NON-NLS-1$ private static ILogger logger = Logger.getLogger("org.eclipse.birt.chart.device.svg/trace"); //$NON-NLS-1$ public SVGGraphics2D(Document dom) { this(dom, true); } public SVGGraphics2D(Document dom, boolean scriptable) { this.dom = dom; this.scriptable = scriptable; fontRenderContext = new FontRenderContext(new AffineTransform(), true, false); currentElement = dom.getDocumentElement(); parentStack.push(currentElement); currentParent = currentElement; // add default styles currentElement = dom.createElement("g"); //$NON-NLS-1$ definitions = dom.createElement("defs"); //$NON-NLS-1$ // give the outer group element an ID currentElement.setAttribute("id", "outerG"); //$NON-NLS-1$ //$NON-NLS-2$ currentElement.appendChild(definitions); currentElement.setAttribute("style", defaultStyles); //$NON-NLS-1$ pushParent(currentElement); transforms = new AffineTransform(); initializeScriptStyles(); } public void pushParent(Element parent) { appendChild(parent); parentStack.push(parent); currentParent = parent; } public Element popParent() { Element popElement = null; if (!parentStack.isEmpty()) popElement = parentStack.pop(); if (!parentStack.isEmpty()) currentParent = parentStack.peek(); return popElement; } protected void appendChild(Element child) { currentParent.appendChild(child); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#draw(java.awt.Shape) */ public void draw(Shape shape) { currentElement = createGeneralPath(shape); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#drawImage(java.awt.Image, * java.awt.geom.AffineTransform, java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, AffineTransform arg1, ImageObserver arg2) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawImage.image"))); //$NON-NLS-1$ return false; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#drawImage(java.awt.image.BufferedImage, * java.awt.image.BufferedImageOp, int, int) */ public void drawImage(BufferedImage arg0, BufferedImageOp arg1, int arg2, int arg3) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawImage.buffer"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics2D#drawRenderedImage(java.awt.image.RenderedImage, * java.awt.geom.AffineTransform) */ public void drawRenderedImage(RenderedImage arg0, AffineTransform arg1) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawRenderImage.RenderImage"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @seejava.awt.Graphics2D#drawRenderableImage(java.awt.image.renderable. * RenderableImage, java.awt.geom.AffineTransform) */ public void drawRenderableImage(RenderableImage arg0, AffineTransform arg1) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawRenderableImage.RenderableImage"))); //$NON-NLS-1$ } private void drawString(String arg0, String sX, String sY) { currentElement = this.createText(arg0); currentElement.setAttribute("x", sX); //$NON-NLS-1$ currentElement.setAttribute("y", sY); //$NON-NLS-1$ appendChild(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawString(java.lang.String, int, int) */ public void drawString(String arg0, int arg1, int arg2) { drawString(arg0, Integer.toString(arg1), Integer.toString(arg2)); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#drawString(java.lang.String, float, float) */ public void drawString(String arg0, float arg1, float arg2) { drawString(arg0, toString(arg1), toString(arg2)); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawString(java.text.AttributedCharacterIterator, * int, int) */ public void drawString(AttributedCharacterIterator arg0, int arg1, int arg2) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawString.AttributeInt"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see * java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, * float, float) */ public void drawString(AttributedCharacterIterator arg0, float arg1, float arg2) { logger.log(new Exception(Messages.getString("SVGGraphics2D.drawString.AttributeFloat"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics2D#drawGlyphVector(java.awt.font.GlyphVector, * float, float) */ public void drawGlyphVector(GlyphVector glyph, float x, float y) { translate(x, y); Element currentElement = dom.createElement("g");//$NON-NLS-1$ Element transElement = createElement("g"); //$NON-NLS-1$ currentElement.appendChild(transElement); // need to defer clipping for each glyph setFillColor(transElement, true); for (int idx = 0; idx < glyph.getNumGlyphs(); idx++) { Element glyphElem = createShape(glyph.getGlyphOutline(idx)); transElement.appendChild(glyphElem); } // should add clipping to the group element that is not transformed if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); translate(-x, -y); } public void fill(Shape shape, boolean defered) { Element tempDeferred = null; if (!defered) { tempDeferred = deferStrokColor; deferStrokColor = null; } currentElement = createGeneralPath(shape); appendChild(currentElement); setFillColor(currentElement); if (!defered) { deferStrokColor = tempDeferred; } } /* * (non-Javadoc) * * @see java.awt.Graphics2D#fill(java.awt.Shape) */ public void fill(Shape shape) { currentElement = createGeneralPath(shape); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#hit(java.awt.Rectangle, java.awt.Shape, boolean) */ public boolean hit(Rectangle arg0, Shape arg1, boolean arg2) { logger.log(new Exception(Messages.getString("SVGGraphics2D.hit.Rectangle"))); //$NON-NLS-1$ return false; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getDeviceConfiguration() */ public GraphicsConfiguration getDeviceConfiguration() { logger.log(new Exception(Messages.getString("SVGGraphics2D.getDeviceConfig"))); //$NON-NLS-1$ return null; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#setComposite(java.awt.Composite) */ public void setComposite(Composite arg0) { logger.log(new Exception(Messages.getString("SVGGraphics2D.setComposite"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics2D#setRenderingHint(java.awt.RenderingHints.Key, * java.lang.Object) */ public void setRenderingHint(Key arg0, Object arg1) { renderingHints.put(arg0, arg1); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getRenderingHint(java.awt.RenderingHints.Key) */ public Object getRenderingHint(Key arg0) { return renderingHints.get(arg0); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#setRenderingHints(java.util.Map) */ public void setRenderingHints(Map arg0) { renderingHints = new RenderingHints(arg0); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#addRenderingHints(java.util.Map) */ public void addRenderingHints(Map arg0) { renderingHints.add(new RenderingHints(arg0)); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getRenderingHints() */ public RenderingHints getRenderingHints() { return renderingHints; } /* * (non-Javadoc) * * @see java.awt.Graphics#translate(int, int) */ public void translate(int arg0, int arg1) { String transform = currentElement.getAttribute("transform"); //$NON-NLS-1$ if (transform == null) transform = ""; //$NON-NLS-1$ currentElement.setAttribute("transform", transform + " translate(" + arg0 + " " + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } /* * (non-Javadoc) * * @see java.awt.Graphics2D#translate(double, double) */ public void translate(double arg0, double arg1) { transforms.translate(arg0, arg1); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#rotate(double) */ public void rotate(double arg0) { transforms.rotate(arg0); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#rotate(double, double, double) */ public void rotate(double arg0, double arg1, double arg2) { transforms.rotate(arg0, arg1, arg2); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#scale(double, double) */ public void scale(double arg0, double arg1) { transforms.scale(arg0, arg1); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#shear(double, double) */ public void shear(double arg0, double arg1) { transforms.shear(arg0, arg1); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#transform(java.awt.geom.AffineTransform) */ public void transform(AffineTransform arg0) { transforms.concatenate((AffineTransform) arg0.clone()); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#setTransform(java.awt.geom.AffineTransform) */ public void setTransform(AffineTransform transform) { this.transforms = transform; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getTransform() */ public AffineTransform getTransform() { return transforms; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getPaint() */ public Paint getPaint() { return paint; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getComposite() */ public Composite getComposite() { logger.log(new Exception(Messages.getString("SVGGraphics2D.getComposite"))); //$NON-NLS-1$ return null; } /* * (non-Javadoc) * * @see java.awt.Graphics2D#clip(java.awt.Shape) */ public void clip(Shape shape) { setClip(shape); } /* * (non-Javadoc) * * @see java.awt.Graphics2D#getFontRenderContext() */ public FontRenderContext getFontRenderContext() { return fontRenderContext; } /* * (non-Javadoc) * * @see java.awt.Graphics#create() */ public Graphics create() { return new SVGGraphics2D(dom); } /* * (non-Javadoc) * * @see java.awt.Graphics#setPaintMode() */ public void setPaintMode() { logger.log(new Exception(Messages.getString("SVGGraphics2D.setPaintMode"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics#setXORMode(java.awt.Color) */ public void setXORMode(Color xorColor) { if ((color == null) || (xorColor == null)) return; int newColor = ((xorColor.getRed() << 16) + (xorColor.getGreen() << 8) + xorColor.getBlue()) ^ ((color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue()); int r = newColor >> 16 & 0x0000FF; int g = (0x00FF00 & newColor) >> 8; int b = 0x0000FF & newColor; color = new Color(r, g, b); } /* * (non-Javadoc) * * @see java.awt.Graphics#getFontMetrics(java.awt.Font) */ public FontMetrics getFontMetrics(Font arg0) { logger.log(new Exception(Messages.getString("SVGGraphics2D.getFontMetrics.Font"))); //$NON-NLS-1$ return null; } /* * (non-Javadoc) * * @see java.awt.Graphics#getClipBounds() */ public Rectangle getClipBounds() { return clip.getBounds(); } /* * (non-Javadoc) * * @see java.awt.Graphics#clipRect(int, int, int, int) */ public void clipRect(int arg0, int arg1, int arg2, int arg3) { Rectangle2D.Double rect = new Rectangle2D.Double(arg0, arg1, arg2, arg3); setClip(rect); } /* * (non-Javadoc) * * @see java.awt.Graphics#setClip(int, int, int, int) */ public void setClip(int arg0, int arg1, int arg2, int arg3) { Rectangle2D.Double rect = new Rectangle2D.Double(arg0, arg1, arg2, arg3); setClip(rect); } /* * (non-Javadoc) * * @see java.awt.Graphics#copyArea(int, int, int, int, int, int) */ public void copyArea(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { logger.log(new Exception(Messages.getString("SVGGraphics2D.CopyArea.Int"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics#drawLine(int, int, int, int) */ public void drawLine(int arg0, int arg1, int arg2, int arg3) { drawLine((double) arg0, (double) arg1, (double) arg2, (double) arg3); } public void drawLine(double arg0, double arg1, double arg2, double arg3) { currentElement = createLine(arg0, arg1, arg2, arg3); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawRect(int, int, int, int) */ public void drawRect(int arg0, int arg1, int arg2, int arg3) { drawRect((double) arg0, (double) arg1, (double) arg2, (double) arg3); } public void drawRect(double arg0, double arg1, double arg2, double arg3) { currentElement = createRect(arg0, arg1, arg2, arg3); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#fillRect(int, int, int, int) */ public void fillRect(int arg0, int arg1, int arg2, int arg3) { fillRect((double) arg0, (double) arg1, (double) arg2, (double) arg3); } public void fillRect(double arg0, double arg1, double arg2, double arg3) { currentElement = createRect(arg0, arg1, arg2, arg3); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#clearRect(int, int, int, int) */ public void clearRect(int arg0, int arg1, int arg2, int arg3) { logger.log(new Exception(Messages.getString("SVGGraphics2D.clearRect.Int"))); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see java.awt.Graphics#drawRoundRect(int, int, int, int, int, int) */ public void drawRoundRect(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { currentElement = createRoundRect(arg0, arg1, arg2, arg3, arg4, arg5); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#fillRoundRect(int, int, int, int, int, int) */ public void fillRoundRect(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { currentElement = createRoundRect(arg0, arg1, arg2, arg3, arg4, arg5); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawOval(int, int, int, int) */ public void drawOval(int arg0, int arg1, int arg2, int arg3) { drawOval((double) arg0, (double) arg1, (double) arg2, (double) arg3); } public void drawOval(double arg0, double arg1, double arg2, double arg3) { currentElement = createOval(arg0, arg1, arg2, arg3); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#fillOval(int, int, int, int) */ public void fillOval(int arg0, int arg1, int arg2, int arg3) { fillOval((double) arg0, (double) arg1, (double) arg2, (double) arg3); } public void fillOval(double arg0, double arg1, double arg2, double arg3) { currentElement = createOval(arg0, arg1, arg2, arg3); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawArc(int, int, int, int, int, int) */ public void drawArc(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { drawArc((double) arg0, (double) arg1, (double) arg2, (double) arg3, (double) arg4, (double) arg5); } public void drawArc(double arg0, double arg1, double arg2, double arg3, double arg4, double arg5) { currentElement = createArc(arg0, arg1, arg2, arg3, arg4, arg5); appendChild(currentElement); setStrokeStyle(currentElement); } protected void setStrokeStyle(Element currentElement) { setStrokeStyle(currentElement, false); } /** * Adds stroke color and style information to the element passed in. * * @param currentElement * the element to add style information to. * @param isClipped * boolean that determines whether to defer the clipping of the * element */ protected void setStrokeStyle(Element currentElement, boolean deferClipped) { Element element = currentElement; if (deferStrokColor != null) { // Need to get the parent element. element = deferStrokColor; } String style = element.getAttribute("style"); //$NON-NLS-1$ if (style == null) style = ""; //$NON-NLS-1$ if (color != null) { style += "stroke:" + serializeToString(color) + ";"; //$NON-NLS-1$ //$NON-NLS-2$ } if ((stroke != null) && (stroke instanceof BasicStroke)) { BasicStroke bs = (BasicStroke) stroke; if (bs.getLineWidth() > 0) style += "stroke-width:" + bs.getLineWidth() + ";"; //$NON-NLS-1$ //$NON-NLS-2$ if (bs.getDashArray() != null) { StringBuffer dashArrayStr = new StringBuffer(); for (int x = 0; x < bs.getDashArray().length; x++) { dashArrayStr.append(" ").append(bs.getDashArray()[x]); //$NON-NLS-1$ } if (!(dashArrayStr.toString().equals(""))) //$NON-NLS-1$ style += "stroke-dasharray:" + dashArrayStr + ";"; //$NON-NLS-1$ //$NON-NLS-2$ } style += "stroke-miterlimit:" + bs.getMiterLimit() + ";"; //$NON-NLS-1$ //$NON-NLS-2$ switch (bs.getLineJoin()) { case BasicStroke.JOIN_BEVEL: style += "stroke-linejoin:bevel;"; //$NON-NLS-1$ break; case BasicStroke.JOIN_ROUND: style += "stroke-linejoin:round;"; //$NON-NLS-1$ break; } switch (bs.getEndCap()) { case BasicStroke.CAP_ROUND: style += "stroke-linecap:round;"; //$NON-NLS-1$ break; case BasicStroke.CAP_SQUARE: style += "stroke-linecap:square;"; //$NON-NLS-1$ break; } } element.setAttribute("style", style); //$NON-NLS-1$ if (styleClass != null) element.setAttribute("class", styleClass); //$NON-NLS-1$ if (id != null) element.setAttribute("id", id); //$NON-NLS-1$ if ((clip != null) && (!deferClipped)) element.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } protected void setFillColor(Element currentElement) { setFillColor(currentElement, false); } /** * Adds no fill color and style information to the element passed in. * * @param currentElement * the element to add style information to. */ protected void setNoFillColor(Element currentElement) { // should set the fill color to none on the currentElement String style = currentElement.getAttribute("style"); //$NON-NLS-1$ if (style == null) style = ""; //$NON-NLS-1$ currentElement.setAttribute("style", style + "fill:none;"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Adds fill color and style information to the element passed in. * * @param currentElement * the element to add style information to. * @param isClipped * boolean that determines whether to defer the clipping of the * element */ protected void setFillColor(Element currentElement, boolean deferClipped) { Element element = currentElement; if (deferStrokColor != null) { // Need to get the parent element. element = deferStrokColor; } String style = element.getAttribute("style"); //$NON-NLS-1$ if (style == null) style = ""; //$NON-NLS-1$ if (paint == null) { if (color == null) return; String alpha = alphaToString(color); if (alpha != null) style += "fill-opacity:" + alpha + ";"; //$NON-NLS-1$ //$NON-NLS-2$ element.setAttribute("style", style + "fill:" + serializeToString(color) + ";stroke:none;"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } else if (paint instanceof SVGGradientPaint) { element.setAttribute("style", //$NON-NLS-1$ style + "fill:url(#" + ((SVGGradientPaint) paint).getId() + ");stroke:none;fill-opacity:1.0"); //$NON-NLS-1$ //$NON-NLS-2$ } else if (paint instanceof TexturePaint) { element.setAttribute("style", //$NON-NLS-1$ style + "fill:url(#" + getTextureId((TexturePaint) paint) + ");stroke:none;fill-opacity:1.0"); //$NON-NLS-1$ //$NON-NLS-2$ } if (styleClass != null) element.setAttribute("class", styleClass); //$NON-NLS-1$ if (id != null) element.setAttribute("id", id); //$NON-NLS-1$ if ((clip != null) && (!deferClipped)) element.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } /** * @returns the color definition in a string with the format: #RRGGBBAA: * RRGGBB are the color components in hexa in the range 00..FF AA * is the transparency value in hexa in the range 00..FF ex: Solid * light gray : #777777 */ protected String serializeToString(Color color) { String r = Integer.toHexString(color.getRed()); if (color.getRed() <= 0xF) r = "0" + r; //$NON-NLS-1$ String g = Integer.toHexString(color.getGreen()); if (color.getGreen() <= 0xF) g = "0" + g; //$NON-NLS-1$ String b = Integer.toHexString(color.getBlue()); if (color.getBlue() <= 0xF) b = "0" + b; //$NON-NLS-1$ String ret = "#" + r + g + b; //$NON-NLS-1$ return ret; } protected String alphaToString(Color color) { double a = 1; if (color.getAlpha() < 0xFF) { a = color.getAlpha() / 255.0; } return toString(a); } /* * (non-Javadoc) * * @see java.awt.Graphics#fillArc(int, int, int, int, int, int) */ public void fillArc(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { fillArc((double) arg0, (double) arg1, (double) arg2, (double) arg3, (double) arg4, (double) arg5); } public void fillArc(double arg0, double arg1, double arg2, double arg3, double arg4, double arg5) { currentElement = createArc(arg0, arg1, arg2, arg3, arg4, arg5); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawPolyline(int[], int[], int) */ public void drawPolyline(int[] arg0, int[] arg1, int arg2) { currentElement = createPolyline(arg0, arg1, arg2); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawPolygon(int[], int[], int) */ public void drawPolygon(int[] arg0, int[] arg1, int arg2) { currentElement = createPolygon(arg0, arg1, arg2); appendChild(currentElement); setStrokeStyle(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#fillPolygon(int[], int[], int) */ public void fillPolygon(int[] arg0, int[] arg1, int arg2) { currentElement = createPolygon(arg0, arg1, arg2); appendChild(currentElement); setFillColor(currentElement); } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, * java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, ImageObserver arg3) { SVGImage image = (SVGImage) arg0; Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("xlink:href", image.getUrl()); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", Integer.toString(arg0.getWidth(arg3))); //$NON-NLS-1$ currentElement.setAttribute("height", Integer.toString(arg0.getHeight(arg3))); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, * java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, ImageObserver arg5) { SVGImage image = (SVGImage) arg0; Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("xlink:href", image.getUrl()); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", toString(arg3)); //$NON-NLS-1$ currentElement.setAttribute("height", toString(arg4)); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, * java.awt.Color, java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, Color arg3, ImageObserver arg4) { SVGImage image = (SVGImage) arg0; image.getUrl(); Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", Integer.toString(arg0.getWidth(arg4))); //$NON-NLS-1$ currentElement.setAttribute("height", Integer.toString(arg0.getHeight(arg4))); //$NON-NLS-1$ currentElement.setAttribute("fill", serializeToString(arg3)); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, * java.awt.Color, java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, Color arg5, ImageObserver arg6) { SVGImage image = (SVGImage) arg0; Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("xlink:href", image.getUrl()); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", toString(arg3)); //$NON-NLS-1$ currentElement.setAttribute("height", toString(arg4)); //$NON-NLS-1$ currentElement.setAttribute("fill", serializeToString(arg5)); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, int, * int, int, int, java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, ImageObserver arg9) { SVGImage image = (SVGImage) arg0; Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("xlink:href", image.getUrl()); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", toString(arg3)); //$NON-NLS-1$ currentElement.setAttribute("height", toString(arg4)); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /* * (non-Javadoc) * * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, int, * int, int, int, java.awt.Color, java.awt.image.ImageObserver) */ public boolean drawImage(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, Color arg9, ImageObserver arg10) { SVGImage image = (SVGImage) arg0; Element currentElement = createElement("image"); //$NON-NLS-1$ currentElement.setAttribute("xlink:href", image.getUrl()); //$NON-NLS-1$ currentElement.setAttribute("x", toString(arg1)); //$NON-NLS-1$ currentElement.setAttribute("y", toString(arg2)); //$NON-NLS-1$ currentElement.setAttribute("width", toString(arg3)); //$NON-NLS-1$ currentElement.setAttribute("height", toString(arg4)); //$NON-NLS-1$ currentElement.setAttribute("fill", serializeToString(arg9)); //$NON-NLS-1$ if (clip != null) currentElement.setAttribute("clip-path", "url(#clip" + clip.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ appendChild(currentElement); return true; } /** * Unload any resources associated with the graphic context */ public void flush() { // Use a temporary buffer to ensure the original string immutable StringBuffer buffer = new StringBuffer(EventHandlers.getJSMenuLib()); codeScript.appendChild(dom.createCDATASection(buffer.append(scriptBuffer).toString())); buffer = new StringBuffer(EventHandlers.STYLES.toString()); styles.appendChild(dom.createCDATASection(buffer.append(styleBuffer).toString())); // clear buffer scriptBuffer = new StringBuffer(); styleBuffer = new StringBuffer(); } /* * (non-Javadoc) * * @see java.awt.Graphics#dispose() */ @Override public void dispose() { paints.clear(); textures.clear(); } /** * @return Returns the background. */ public Color getBackground() { return background; } /** * @param backgroundColor * The backgroundColor to set. */ public void setBackground(Color background) { this.background = background; } /** * @return Returns the clip. */ public Shape getClip() { return clip; } /** * @param clip * The clip to set. */ public void setClip(Shape clip) { this.clip = clip; if (clip != null) { Element clipPath = dom.createElement("clipPath"); //$NON-NLS-1$ clipPath.setAttribute("id", "clip" + clip.hashCode()); //$NON-NLS-1$ //$NON-NLS-2$ clipPath.appendChild(createGeneralPath(clip)); definitions.appendChild(clipPath); } } /** * @return Returns the color. */ public Color getColor() { return color; } /** * @param color * The color to set. */ public void setColor(Color color) { this.color = color; this.paint = null; } /** * @return Returns the font. */ public Font getFont() { return font; } /** * @param font * The font to set. */ public void setFont(Font font) { this.font = font; } /** * @return Returns the stroke. */ public Stroke getStroke() { return stroke; } /** * @param stroke * The stroke to set. */ @Override public void setStroke(Stroke stroke) { this.stroke = stroke; } private Element createEmbeddeImage(BufferedImage img) { if (img == null) { return null; } int width = img.getWidth(); int height = img.getHeight(); ImageWriter iw = ImageWriterFactory.instance().createByFormatName("png"); //$NON-NLS-1$ ByteArrayOutputStream baos = new ByteArrayOutputStream(8192 * 2); String sUrl = null; try { final ImageOutputStream ios = SecurityUtil.newImageOutputStream(baos); ImageWriteParam iwp = iw.getDefaultWriteParam(); iw.setOutput(ios); iw.write((IIOMetadata) null, new IIOImage(img, null, null), iwp); img.flush(); ios.close(); sUrl = SVGImage.BASE64 + new String(Base64.encodeBase64(baos.toByteArray())); } catch (Exception ex) { logger.log(ex); } finally { iw.dispose(); } Element elemG = dom.createElement("g"); //$NON-NLS-1$ elemG.setAttribute("id", "img_" + img.hashCode()); //$NON-NLS-1$//$NON-NLS-2$ Element elem = dom.createElement("image"); //$NON-NLS-1$ elem.setAttribute("x", "0"); //$NON-NLS-1$//$NON-NLS-2$ elem.setAttribute("y", "0"); //$NON-NLS-1$ //$NON-NLS-2$ elem.setAttribute("width", Integer.toString(width)); //$NON-NLS-1$ elem.setAttribute("height", Integer.toString(height)); //$NON-NLS-1$ elem.setAttribute("xlink:href", sUrl); //$NON-NLS-1$ elemG.appendChild(elem); return elemG; } /** * @param paint * The paint to set. */ @Override public void setPaint(Paint paint) { if (paint instanceof GradientPaint) { SVGGradientPaint gp = new SVGGradientPaint((GradientPaint) paint); int index = paints.indexOf(gp); if (index == -1) { paints.add(gp); definitions.appendChild(createGradientPaint(gp, false)); definitions.appendChild(createGradientPaint(gp, true)); } else { gp = paints.get(index); } this.paint = gp; } else if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; if (!textures.contains(tp)) { textures.add(tp); Element elemImg = createEmbeddeImage(tp.getImage()); if (elemImg != null) { definitions.appendChild(elemImg); String imgId = elemImg.getAttribute("id"); //$NON-NLS-1$ definitions.appendChild(createTexturePaint(tp, imgId, false)); definitions.appendChild(createTexturePaint(tp, imgId, true)); } } this.paint = tp; } else this.paint = paint; } /*************************************************************************** * Factory Methods **************************************************************************/ protected Element createGradientPaint(SVGGradientPaint paint, boolean highlight) { Element elem = dom.createElement("linearGradient"); //$NON-NLS-1$ if (highlight) elem.setAttribute("id", paint.getId() + "h"); //$NON-NLS-1$ //$NON-NLS-2$ else elem.setAttribute("id", paint.getId()); //$NON-NLS-1$ elem.setAttribute("x1", toString(paint.getPoint1().getX())); //$NON-NLS-1$ elem.setAttribute("y1", toString(paint.getPoint1().getY())); //$NON-NLS-1$ elem.setAttribute("x2", toString(paint.getPoint2().getX())); //$NON-NLS-1$ elem.setAttribute("y2", toString(paint.getPoint2().getY())); //$NON-NLS-1$ elem.setAttribute("gradientUnits", "userSpaceOnUse"); //$NON-NLS-1$ //$NON-NLS-2$ if (paint.isCyclic()) elem.setAttribute("spreadMethod", "repeat"); //$NON-NLS-1$ //$NON-NLS-2$ Element startColor = dom.createElement("stop"); //$NON-NLS-1$ startColor.setAttribute("offset", "0%"); //$NON-NLS-1$ //$NON-NLS-2$ if (highlight) { startColor.setAttribute("stop-color", serializeHighlightToString(paint.getColor1())); //$NON-NLS-1$ } else { startColor.setAttribute("stop-color", serializeToString(paint.getColor1())); //$NON-NLS-1$ } String alpha = alphaToString(paint.getColor1()); if (alpha != null) startColor.setAttribute("stop-opacity", alpha); //$NON-NLS-1$ elem.appendChild(startColor); Element endColor = dom.createElement("stop"); //$NON-NLS-1$ endColor.setAttribute("offset", "100%"); //$NON-NLS-1$ //$NON-NLS-2$ if (highlight) endColor.setAttribute("stop-color", serializeHighlightToString(paint.getColor2())); //$NON-NLS-1$ else endColor.setAttribute("stop-color", serializeToString(paint.getColor2())); //$NON-NLS-1$ alpha = alphaToString(paint.getColor2()); if (alpha != null) endColor.setAttribute("stop-opacity", alpha); //$NON-NLS-1$ elem.appendChild(endColor); return elem; } private String getTextureId(TexturePaint paint) { return "tp" + paint.hashCode(); //$NON-NLS-1$ } protected Element createTexturePaint(TexturePaint paint, String imgId, boolean highlight) { Element elem = dom.createElement("pattern"); //$NON-NLS-1$ if (highlight) elem.setAttribute("id", getTextureId(paint) + "h"); //$NON-NLS-1$ //$NON-NLS-2$ else elem.setAttribute("id", getTextureId(paint)); //$NON-NLS-1$ BufferedImage img = paint.getImage(); int width = img.getWidth(); int height = img.getHeight(); elem.setAttribute("patternUnits", "userSpaceOnUse"); //$NON-NLS-1$//$NON-NLS-2$ elem.setAttribute("width", Integer.toString(width)); //$NON-NLS-1$ elem.setAttribute("height", Integer.toString(height)); //$NON-NLS-1$ Element elemUse = dom.createElement("use"); //$NON-NLS-1$ elemUse.setAttribute("x", "0"); //$NON-NLS-1$//$NON-NLS-2$ elemUse.setAttribute("y", "0"); //$NON-NLS-1$//$NON-NLS-2$ elemUse.setAttribute("xlink:href", "#" + imgId); //$NON-NLS-1$//$NON-NLS-2$ elem.appendChild(elemUse); return elem; } private String serializeHighlightToString(Color cd) { if (cd != null) { int red = (cd.getRed() + 255) / 2; int green = (cd.getGreen() + 255) / 2; int blue = (cd.getBlue() + 255) / 2; String r = Integer.toHexString(red); if (red <= 0xF) r = "0" + r; //$NON-NLS-1$ String g = Integer.toHexString(green); if (green <= 0xF) g = "0" + g; //$NON-NLS-1$ String b = Integer.toHexString(blue); if (blue <= 0xF) b = "0" + b; //$NON-NLS-1$ return "#" + r + g + b; //$NON-NLS-1$ } return ""; //$NON-NLS-1$ } protected Element createLine(double arg0, double arg1, double arg2, double arg3) { Element elem = createElement("line"); //$NON-NLS-1$ elem.setAttribute("x1", toString(arg0)); //$NON-NLS-1$ elem.setAttribute("y1", toString(arg1)); //$NON-NLS-1$ elem.setAttribute("x2", toString(arg2)); //$NON-NLS-1$ elem.setAttribute("y2", toString(arg3)); //$NON-NLS-1$ return elem; } protected Element createShape(Shape shape) { PathIterator pathIter = shape.getPathIterator(null); StringBuffer pathStr = new StringBuffer(); while (!pathIter.isDone()) { float[] points = new float[6]; int TYPE = pathIter.currentSegment(points); switch (TYPE) { case PathIterator.SEG_CLOSE: pathStr.append(" Z"); //$NON-NLS-1$ break; case PathIterator.SEG_LINETO: pathStr.append(" L").append(toString(points, 2, ' ')); //$NON-NLS-1$ break; case PathIterator.SEG_QUADTO: pathStr.append(" Q").append(toString(points, 4, ' ')); //$NON-NLS-1$ break; case PathIterator.SEG_CUBICTO: pathStr.append(" C").append(toString(points, 6, ' ')); //$NON-NLS-1$ break; case PathIterator.SEG_MOVETO: pathStr.append(" M").append(toString(points, 2, ' ')); //$NON-NLS-1$ break; } pathIter.next(); } Element elem = dom.createElement("path"); //$NON-NLS-1$ elem.setAttribute("d", pathStr.toString()); //$NON-NLS-1$ return elem; } protected Element createGeneralPath(Shape path) { Element elem = createShape(path); if (transforms.getType() != AffineTransform.TYPE_IDENTITY) { double[] matrix = new double[6]; transforms.getMatrix(matrix); elem.setAttribute("transform", "matrix(" + toString(matrix, ',') + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return elem; } protected Element createText(String text) { // #232718 to support bidi boolean bRtl = false; if (text.length() > 0) { int iEnd = text.length(); if (chPDF == text.charAt(text.length() - 1)) { iEnd--; } if (chRLE == text.charAt(0)) { bRtl = true; text = text.substring(1, iEnd); } } Element elem = dom.createElement("text"); //$NON-NLS-1$ elem.appendChild(dom.createTextNode(text)); switch (getFont().getStyle()) { case Font.BOLD: elem.setAttribute("font-weight", "bold"); //$NON-NLS-1$ //$NON-NLS-2$ break; case Font.ITALIC: elem.setAttribute("font-style", "italic"); //$NON-NLS-1$ //$NON-NLS-2$ break; case (Font.BOLD + Font.ITALIC): elem.setAttribute("font-style", "italic"); //$NON-NLS-1$ //$NON-NLS-2$ elem.setAttribute("font-weight", "bold"); //$NON-NLS-1$ //$NON-NLS-2$ break; } String textDecorator = null; Map<TextAttribute, ?> attributes = getFont().getAttributes(); if (attributes.get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON) { textDecorator = "underline"; //$NON-NLS-1$ } if (attributes.get(TextAttribute.STRIKETHROUGH) == TextAttribute.STRIKETHROUGH_ON) { if (textDecorator == null) textDecorator = "line-through"; //$NON-NLS-1$ else textDecorator += ",line-through"; //$NON-NLS-1$ } if (textDecorator != null) elem.setAttribute("text-decoration", textDecorator); //$NON-NLS-1$ // for now just preserve space for text elements Bug 182159 elem.setAttribute("xml:space", "preserve"); //$NON-NLS-1$ //$NON-NLS-2$ elem.setAttribute("stroke", "none"); //$NON-NLS-1$ //$NON-NLS-2$ // Here we still use Font.getName() as font-family for SVG instead of // Font.getFaimly(), since if current code is running on linux and there // isn't a valid font family to fit the font setting in chart model, // the call of Font.getFamily() will get a default 'Dialog' font family, // it will caused that the svg in client system can't correct display // mulitple-characters text(Chinese, Jpanese and so on). // We just need to set the original font family setting of chart model // into svg document, if the font family is valid in client system // and can support current text character, it will correct display. elem.setAttribute("font-family", getFont().getName()); //$NON-NLS-1$ elem.setAttribute("font-size", Integer.toString(getFont().getSize())); //$NON-NLS-1$ String style = getRenderingStyle(RenderingHints.KEY_TEXT_ANTIALIASING); if (color != null) { String alpha = alphaToString(color); if (alpha != null) style += "fill-opacity:" + alpha + ";"; //$NON-NLS-1$ //$NON-NLS-2$ style += "fill:" + serializeToString(color) + ";"; //$NON-NLS-1$ //$NON-NLS-2$ } if (bRtl) { style += sStyleBidi; } elem.setAttribute("style", style); //$NON-NLS-1$ if (transforms.getType() != AffineTransform.TYPE_IDENTITY) { double[] matrix = new double[6]; transforms.getMatrix(matrix); elem.setAttribute("transform", "matrix(" + toString(matrix, ',') + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return elem; } protected String getRenderingStyle(Object key) { Object value = renderingHints.get(key); if (key.equals(RenderingHints.KEY_TEXT_ANTIALIASING)) { if (value.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) { // Adobe SVG viewer 3 bug. Rotated text with optimizelegibility // disappears. Replace // with optimizespeed for rotated text. if (transforms.getType() != AffineTransform.TYPE_IDENTITY) return "text-rendering:optimizeSpeed;";//$NON-NLS-1$ else return "text-rendering:optimizeLegibility;";//$NON-NLS-1$ } else // SVG always turns on antialias return ""; //$NON-NLS-1$ } return "";//$NON-NLS-1$ } protected Element createRect(double arg0, double arg1, double arg2, double arg3) { Element elem = createElement("rect"); //$NON-NLS-1$ elem.setAttribute("x", toString(arg0)); //$NON-NLS-1$ elem.setAttribute("y", toString(arg1)); //$NON-NLS-1$ elem.setAttribute("width", toString(arg2)); //$NON-NLS-1$ elem.setAttribute("height", toString(arg3)); //$NON-NLS-1$ return elem; } protected Element createRoundRect(double arg0, double arg1, double arg2, double arg3, double arg4, double arg5) { Element elem = createElement("rect"); //$NON-NLS-1$ elem.setAttribute("x", toString(arg0)); //$NON-NLS-1$ elem.setAttribute("y", toString(arg1)); //$NON-NLS-1$ elem.setAttribute("width", toString(arg2)); //$NON-NLS-1$ elem.setAttribute("height", toString(arg3)); //$NON-NLS-1$ elem.setAttribute("rx", toString(arg2)); //$NON-NLS-1$ elem.setAttribute("ry", toString(arg3)); //$NON-NLS-1$ return elem; } protected Element createOval(double arg0, double arg1, double arg2, double arg3) { Element elem = createElement("ellipse"); //$NON-NLS-1$ elem.setAttribute("cx", toString(arg0)); //$NON-NLS-1$ elem.setAttribute("cy", toString(arg1)); //$NON-NLS-1$ elem.setAttribute("rx", toString(arg2)); //$NON-NLS-1$ elem.setAttribute("ry", toString(arg3)); //$NON-NLS-1$ return elem; } protected Element createArc(double x, double y, double width, double height, double startAngle, double arcAngle) { Element elem = createElement("path"); //$NON-NLS-1$ double startX = x * Math.cos(startAngle); double startY = y * Math.sin(startAngle); double endX = x * Math.cos(startAngle + arcAngle); double endY = y * Math.sin(startAngle + arcAngle); int sweepFlag = (arcAngle < 0) ? 0 : 1; elem.setAttribute("d", //$NON-NLS-1$ "M" + toString(startX) + "," + toString(startY) + " a" + toString(width / 2) + "," //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ + toString(height / 2) + " " + toString(Math.abs(arcAngle)) + " 0 " + sweepFlag + " " //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + toString(endX) + " " + toString(endY)); //$NON-NLS-1$ return elem; } public Element createPolyline(int[] arg0, int[] arg1, int arg2) { Element elem = createElement("polyline"); //$NON-NLS-1$ StringBuffer pointsStr = new StringBuffer(); ; for (int x = 0; x < arg2; x++) { pointsStr.append(arg0[x]).append(",").append(arg1[x]).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ } elem.setAttribute("points", pointsStr.toString()); //$NON-NLS-1$ return elem; } public Element createPolygon(int[] arg0, int[] arg1, int arg2) { Element elem = createElement("polygon"); //$NON-NLS-1$ StringBuffer pointsStr = new StringBuffer(); ; for (int x = 0; x < arg2; x++) { pointsStr.append(arg0[x]).append(",").append(arg1[x]).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ } elem.setAttribute("points", pointsStr.toString()); //$NON-NLS-1$ return elem; } public Element createPolygon(double[] arg0, double[] arg1, int arg2) { Element elem = createElement("polygon"); //$NON-NLS-1$ StringBuffer pointsStr = new StringBuffer(); ; for (int x = 0; x < arg2; x++) { pointsStr.append(arg0[x]).append(",").append(arg1[x]).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ } elem.setAttribute("points", pointsStr.toString()); //$NON-NLS-1$ return elem; } protected void initializeScriptStyles() { codeScript = dom.createElement("script"); //$NON-NLS-1$ if (scriptable) appendChild(codeScript); styles = dom.createElement("style"); //$NON-NLS-1$ styles.setAttribute("type", "text/css"); //$NON-NLS-1$ //$NON-NLS-2$ appendChild(styles); } protected Element createElement(String id) { Element elem = dom.createElement(id); if (this.primitiveId != null) elem.setAttribute("id", primitiveId); //$NON-NLS-1$ if (transforms.getType() != AffineTransform.TYPE_IDENTITY) { double[] matrix = new double[6]; transforms.getMatrix(matrix); elem.setAttribute("transform", "matrix(" + toString(matrix, ',') + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return elem; } public void drawTooltip(String tooltip) { Element title = dom.createElement("title"); //$NON-NLS-1$ title.appendChild(dom.createTextNode(tooltip)); appendChild(title); currentParent.setAttribute("onmouseout", "TM.remove()"); //$NON-NLS-1$ //$NON-NLS-2$ currentParent.setAttribute("onmouseover", "TM.show(evt)"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * @return Returns the currentParent. */ public Element getCurrentParent() { return currentParent; } /** * @return Returns the currentElement. */ public Element getCurrentElement() { return currentElement; } public String getStyleClass() { return styleClass; } public void setStyleClass(String styleClass) { this.styleClass = styleClass; } public void addCSSStyle(String className, String styleName, String styleValue) { styleBuffer.append(className).append("{").append(styleName).append(":").append(styleValue).append(";}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } /** * Inlines the script code in the generated svg output * * @param script * the code that will be inlined in the generated svg output */ public void addScript(String script) { scriptBuffer.append(script); } /** * Adds a script reference in the generated svg output. * * @param ref * the script reference that will be added to the generated svg * output. */ public void addScriptRef(String ref) { Element rootElem = dom.getDocumentElement(); Element scriptElem = dom.createElement("script"); //$NON-NLS-1$ if (scriptable) rootElem.appendChild(scriptElem); scriptElem.setAttribute("language", "JavaScript"); //$NON-NLS-1$ //$NON-NLS-2$ scriptElem.setAttribute("xlink:href", ref); //$NON-NLS-1$ } public String getId() { return id; } public void setId(String id) { this.id = id; } /** * Defer setting the stroke and color on an SVG element. * * @return the state of the flag that ignores setting the stroke style and * color on a svg element. */ public Element getDeferStrokColor() { return deferStrokColor; } /** * Defer setting the stroke and color on an SVG element. * * @param deferStrokColor * set to true if the stroke style and color should be ignored * when drawing the svg element. */ public void setDeferStrokColor(Element deferStrokColor) { this.deferStrokColor = deferStrokColor; } /** * Returns the current id that is used to identify a svg drawing primitive * * @return id */ public String getPrimitiveId() { return primitiveId; } /** * Sets the current primitive id * * @param primitiveId */ public void setPrimitiveId(String primitiveId) { this.primitiveId = primitiveId; } /** * Returns whether the generated output should contain javascript code. * * @return true if the generated output should contain javascript code, * false otherwise */ public boolean isScriptable() { return scriptable; } /** * Sets the flag to determine if the output should contain javascript code * * @param scriptable */ public void setScriptable(boolean scriptable) { this.scriptable = scriptable; } static String toString(double v) { if (Double.isNaN(v)) { return "0"; //$NON-NLS-1$ } return String.valueOf(v); } static String toString(float v) { if (Float.isNaN(v)) { return "0"; //$NON-NLS-1$ } return String.valueOf(v); } static String toString(double[] v, char separator) { return toString(v, v.length, separator); } static String toString(double[] v, int length, char separator) { if (v.length == 0) { return ""; //$NON-NLS-1$ } if (v.length == 1) { return toString(v[0]); } if (length > v.length) { length = v.length; } StringBuffer buffer = new StringBuffer(toString(v[0])); for (int i = 1; i < length; i++) { buffer.append(separator); buffer.append(toString(v[i])); } return buffer.toString(); } static String toString(float[] v, int length, char separator) { if (v.length == 0) { return ""; //$NON-NLS-1$ } if (v.length == 1) { return toString(v[0]); } if (length > v.length) { length = v.length; } StringBuffer buffer = new StringBuffer(toString(v[0])); for (int i = 1; i < length; i++) { buffer.append(separator); buffer.append(toString(v[i])); } return buffer.toString(); } }