diff options
| author | Laurent Redor | 2016-04-18 14:15:20 +0000 |
|---|---|---|
| committer | Laurent Redor | 2016-04-22 14:27:49 +0000 |
| commit | ad8c2a23533e04f6744495453307f36028b8470d (patch) | |
| tree | 97e05c81d0f36756875a8dff2e225f023ea67ab7 | |
| parent | 10fd8eabf275d3fd012f1531d9dc76f49022784b (diff) | |
| download | org.eclipse.sirius-ad8c2a23533e04f6744495453307f36028b8470d.tar.gz org.eclipse.sirius-ad8c2a23533e04f6744495453307f36028b8470d.tar.xz org.eclipse.sirius-ad8c2a23533e04f6744495453307f36028b8470d.zip | |
[491913] Copy original classes from GMF
Preparation commit: Duplicate original GMF classes needed for this
bugzilla. This commit allows to have an initial state of these classes
before modifying them for this bugzilla.
Bug: 491913
Change-Id: I7a255313c42bab04dbd13f3f9ed0e1f2560917ec
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
3 files changed, 1873 insertions, 0 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusDiagramSVGGenerator.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusDiagramSVGGenerator.java new file mode 100644 index 0000000000..37626358a9 --- /dev/null +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusDiagramSVGGenerator.java @@ -0,0 +1,185 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation and others. + * 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.sirius.diagram.ui.tools.internal.render; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.gmf.runtime.common.core.util.Log; +import org.eclipse.gmf.runtime.common.core.util.Trace; +import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; +import org.eclipse.gmf.runtime.diagram.ui.l10n.SharedImages; +import org.eclipse.gmf.runtime.diagram.ui.render.clipboard.DiagramGenerator; +import org.eclipse.gmf.runtime.diagram.ui.render.internal.DiagramUIRenderDebugOptions; +import org.eclipse.gmf.runtime.diagram.ui.render.internal.DiagramUIRenderPlugin; +import org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.image.ImageConverter; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.export.GraphicsSVG; +import org.eclipse.gmf.runtime.draw2d.ui.render.factory.RenderedImageFactory; +import org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderedImageDescriptor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.w3c.dom.Element; + +/** + * Supports generation of an SVG DOM for a diagram or a subset of editparts on a + * diagram. + * + * @author jschofie / sshaw + */ +// CHECKSTYLE:OFF +public class SiriusDiagramSVGGenerator extends DiagramGenerator { + + private RenderedImage renderedImage = null; + + private Element svgRoot = null; + + private Rectangle viewBox = null; + + /** + * Creates a new instance. + * + * @param diagramEditPart + * the diagram editpart + */ + public SiriusDiagramSVGGenerator(DiagramEditPart diagramEditPart) { + super(diagramEditPart); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.gmf.runtime.diagram.ui.render.clipboard.DiagramGenerator# + * setUpGraphics(int, int) + */ + protected Graphics setUpGraphics(int width, int height) { + viewBox = new Rectangle(0, 0, width, height); + return GraphicsSVG.getInstance(viewBox); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.gmf.runtime.diagram.ui.render.clipboard.DiagramGenerator# + * getImageDescriptor(org.eclipse.draw2d.Graphics) + */ + protected ImageDescriptor getImageDescriptor(Graphics g) { + try { + GraphicsSVG svgG = (GraphicsSVG) g; + // Get the root element (the svg element) + svgRoot = svgG.getRoot(); + + ByteArrayOutputStream os = new ByteArrayOutputStream(5000); // 5K + // buffer + stream(os); + os.close(); + + setRenderedImage(RenderedImageFactory.getInstance(os.toByteArray())); + + return RenderedImageDescriptor.createFromRenderedImage(getRenderedImage()); + } catch (IOException ex) { + Log.error(DiagramUIRenderPlugin.getInstance(), IStatus.ERROR, ex.getMessage(), ex); + } + + return null; + } + + /** + * Writes the SVG Model out to a file. + * + * @param outputStream + * output stream to store the SVG Model + */ + public void stream(OutputStream outputStream) { + try { + + // Define the view box + svgRoot.setAttributeNS(null, "viewBox", //$NON-NLS-1$ + String.valueOf(viewBox.x) + " " + //$NON-NLS-1$ + String.valueOf(viewBox.y) + " " + //$NON-NLS-1$ + String.valueOf(viewBox.width) + " " + //$NON-NLS-1$ + String.valueOf(viewBox.height)); + + // Write the document to the stream + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ + + DOMSource source = new DOMSource(svgRoot); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + } catch (Exception ex) { + Log.error(DiagramUIRenderPlugin.getInstance(), IStatus.ERROR, ex.getMessage(), ex); + } + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.gmf.runtime.diagram.ui.internal.clipboard.DiagramGenerator# + * createAWTImageForParts(java.util.List) + */ + public Image createAWTImageForParts(List editparts, org.eclipse.swt.graphics.Rectangle sourceRect) { + createSWTImageDescriptorForParts(editparts, sourceRect); + if (getRenderedImage() != null) { + try { + BufferedImage bufImg = (BufferedImage) getRenderedImage().getAdapter(BufferedImage.class); + if (bufImg == null) + bufImg = ImageConverter.convert(getRenderedImage().getSWTImage()); + return bufImg; + } catch (Error e) { + // log the Error but allow execution to continue + Trace.catching(DiagramUIRenderPlugin.getInstance(), DiagramUIRenderDebugOptions.EXCEPTIONS_THROWING, getClass(), "createAWTImageForParts() failed to generate image", //$NON-NLS-1$ + e); + return ImageConverter.convert(SharedImages.get(SharedImages.IMG_ERROR)); + + } catch (Exception ex) { + // log the Exception but allow execution to continue + Trace.catching(DiagramUIRenderPlugin.getInstance(), DiagramUIRenderDebugOptions.EXCEPTIONS_THROWING, getClass(), "createAWTImageForParts() failed to generate image", //$NON-NLS-1$ + ex); + return ImageConverter.convert(SharedImages.get(SharedImages.IMG_ERROR)); + } + } + + return ImageConverter.convert(SharedImages.get(SharedImages.IMG_ERROR)); + } + + /** + * @return Returns the rendered image created by previous call to + * createSWTImageDescriptorForParts + */ + public RenderedImage getRenderedImage() { + return renderedImage; + } + + /** + * @param svgImage + * The svgImage to set. + */ + private void setRenderedImage(RenderedImage renderedImage) { + this.renderedImage = renderedImage; + } +} +// CHECKSTYLE:ON diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsSVG.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsSVG.java new file mode 100644 index 0000000000..b74c96958c --- /dev/null +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsSVG.java @@ -0,0 +1,180 @@ +/****************************************************************************** + * Copyright (c) 2004, 2010 IBM Corporation and others. + * 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.sirius.diagram.ui.tools.internal.render; + +import java.awt.Color; +import java.awt.Dimension; + +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.dom.svg.SVGOMDocument; +import org.apache.batik.dom.util.DOMUtilities; +import org.apache.batik.svggen.DOMTreeManager; +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.batik.util.SVGConstants; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.gmf.runtime.draw2d.ui.render.RenderInfo; +import org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.graphics.GraphicsToGraphics2DAdaptor; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.SVGColorConverter; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.SVGImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.internal.DrawableRenderedImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderingListener; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Objects of this class can be used with draw2d to create an SVG DOM. + * + * @author jschofie / sshaw + */ +// CHECKSTYLE:OFF +public class SiriusGraphicsSVG extends GraphicsToGraphics2DAdaptor implements DrawableRenderedImage { + + private Document doc; + + /** + * Static initializer that will return an instance of + * <code>GraphicsSVG</code> + * + * @param viewPort + * the <code>Rectangle</code> area that is to be rendered. + * @return a new <code>GraphicsSVG</code> object. + */ + public static SiriusGraphicsSVG getInstance(Rectangle viewPort) { + SVGGraphics2D svgGraphics; + + // Get the DOM implementation and create the document + DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); + String svgNameSpace = SVGDOMImplementation.SVG_NAMESPACE_URI; + Document doc = impl.createDocument(svgNameSpace, "svg", null); //$NON-NLS-1$ + + // Create the SVG Graphics Object + svgGraphics = new SVGGraphics2D(doc); + + // Set the precision level to avoid NPEs (issue with Batik 1.5) + svgGraphics.getGeneratorContext().setPrecision(3); + + // Set the Width and Height Attributes on the Root Element + svgGraphics.setSVGCanvasSize(new Dimension(viewPort.width, viewPort.height)); + + return new SiriusGraphicsSVG(svgGraphics, doc, svgNameSpace, viewPort); + } + + /** + * @return <code>SVGGraphics2D</code> object + */ + public SVGGraphics2D getSVGGraphics2D() { + return (SVGGraphics2D) getGraphics2D(); + } + + /** + * @param graphics + * @param doc + * @param svgNameSpace + * @param viewPort + */ + private SiriusGraphicsSVG(SVGGraphics2D graphics, Document doc, String svgNameSpace, Rectangle viewPort) { + + this(graphics, doc, svgNameSpace, new org.eclipse.swt.graphics.Rectangle(viewPort.x, viewPort.y, viewPort.width, viewPort.height)); + } + + /** + * @param graphics + * @param doc + * @param svgNameSpace + * @param viewPort + */ + private SiriusGraphicsSVG(SVGGraphics2D graphics, Document doc, String svgNameSpace, org.eclipse.swt.graphics.Rectangle viewPort) { + + super(graphics, viewPort); + this.doc = doc; + paintNotCompatibleStringsAsBitmaps = false; + } + + /** + * Method used to get the SVG DOM from the Graphics + * + * @return SVG document + */ + public Document getDocument() { + return doc; + } + + /** + * Method used to get the SVG Root element from the document + * + * @return DOM Root element + */ + public Element getRoot() { + return getSVGGraphics2D().getRoot(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.graphics. + * GraphicsToGraphics2DAdaptor#drawRenderedImage(org.eclipse.gmf.runtime. + * draw2d.ui.render.RenderedImage, org.eclipse.draw2d.geometry.Rectangle, + * org.eclipse.gmf.runtime.draw2d.ui.render.RenderingListener) + */ + @Override + public RenderedImage drawRenderedImage(RenderedImage srcImage, Rectangle rect, RenderingListener listener) { + + // Check for a change in the state + checkState(); + + // Get the Tree Manager + DOMTreeManager treeManager = getSVGGraphics2D().getDOMTreeManager(); + + Point trans = getTranslationOffset(); + // Get the Root element of the SVG document to export + if (srcImage instanceof SVGImage) { + Document document = ((SVGImage) srcImage).getDocument(); + + DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); + document = DOMUtilities.deepCloneDocument(document, impl); + + if (document instanceof SVGOMDocument) { + RenderInfo info = srcImage.getRenderInfo(); + if (info != null && info.getBackgroundColor() != null && info.getForegroundColor() != null) { + SVGColorConverter.getInstance().replaceDocumentColors((SVGOMDocument) document, + new Color(info.getBackgroundColor().red, info.getBackgroundColor().green, info.getBackgroundColor().blue), + new Color(info.getForegroundColor().red, info.getForegroundColor().green, info.getForegroundColor().blue)); + + } + } + Element root = document.getDocumentElement(); + + // Create a "deep" copy of the document + Element toAppend = (Element) doc.importNode(root, true); + + // Modify the X Attribute + toAppend.setAttributeNS(null, SVGConstants.SVG_X_ATTRIBUTE, String.valueOf(rect.x + trans.x)); + + // Modify the Y Attribute + toAppend.setAttributeNS(null, SVGConstants.SVG_Y_ATTRIBUTE, String.valueOf(rect.y + trans.y)); + + // Modify the Width Attribute + toAppend.setAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE, String.valueOf(rect.width)); + + // Modify the Height Attribute + toAppend.setAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE, String.valueOf(rect.height)); + + treeManager.appendGroup(toAppend, null); + return srcImage; + } else { + return super.drawRenderedImage(srcImage, rect, listener); + } + } + +} +// CHECKSTYLE:ON diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsToGraphics2DAdaptor.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsToGraphics2DAdaptor.java new file mode 100644 index 0000000000..344310ddcf --- /dev/null +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/render/SiriusGraphicsToGraphics2DAdaptor.java @@ -0,0 +1,1508 @@ +/****************************************************************************** + * Copyright (c) 2004, 2015 IBM Corporation and others. + * 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.sirius.diagram.ui.tools.internal.render; + +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Composite; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Arc2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.util.Stack; + +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.SWTGraphics; +import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.PointList; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.gmf.runtime.common.ui.util.DisplayUtils; +import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeTypes; +import org.eclipse.gmf.runtime.draw2d.ui.render.RenderInfo; +import org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.image.ImageConverter; +import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.metafile.GdiFont; +import org.eclipse.gmf.runtime.draw2d.ui.render.internal.DrawableRenderedImage; +import org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderingListener; +import org.eclipse.gmf.runtime.draw2d.ui.text.TextUtilitiesEx; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.LineAttributes; +import org.eclipse.swt.graphics.Path; +import org.eclipse.swt.graphics.PathData; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.TextLayout; + +//CHECKSTYLE:OFF +/** + * Objects of this class can be used with draw2d to render to a Graphics2D + * object. + * + * @author jschofie / sshaw + */ +public class SiriusGraphicsToGraphics2DAdaptor extends Graphics implements DrawableRenderedImage { + + private static class State { + + /** + * translateX + */ + public int translateX = 0; + + /** + * translateY + */ + public int translateY = 0; + + /** + * clipping rectangle x coordinate + */ + public int clipX = 0; + + /** + * clipping rectangle y coordinate + */ + public int clipY = 0; + + /** + * clipping rectangle width + */ + public int clipW = 0; + + /** + * clipping rectangle height + */ + public int clipH = 0; + + /** Font value **/ + /** + * cached font + */ + public Font font; + + /** + * cached xor mode value + */ + public boolean XorMode = false; + + /** + * cached foreground color + */ + public Color fgColor; + + /** + * cached background color + */ + public Color bgColor; + + /** + * cached alpha value + */ + public int alpha; + + /** + * Line attributes value + */ + public LineAttributes lineAttributes = new LineAttributes(1); + + int graphicHints; + + /** + * Copy the values from a given state to this state + * + * @param state + * the state to copy from + */ + public void copyFrom(State state) { + + translateX = state.translateX; + translateY = state.translateY; + + clipX = state.clipX; + clipY = state.clipY; + clipW = state.clipW; + clipH = state.clipH; + + font = state.font; + fgColor = state.fgColor; + bgColor = state.bgColor; + XorMode = state.XorMode; + alpha = state.alpha; + graphicHints = state.graphicHints; + + lineAttributes = SWTGraphics.clone(state.lineAttributes); + } + } + + static final int ADVANCED_GRAPHICS_MASK; + + static final int ADVANCED_SHIFT; + + static final int FILL_RULE_MASK; + + static final int FILL_RULE_SHIFT; + + static final int FILL_RULE_WHOLE_NUMBER = -1; + + /* + * It's consistent with SWTGraphics flags in case some other flags from + * SWTGraphics need to be here + */ + static { + FILL_RULE_SHIFT = 14; + ADVANCED_SHIFT = 15; + FILL_RULE_MASK = 1 << FILL_RULE_SHIFT; // If changed to more than 1-bit, + // check references! + ADVANCED_GRAPHICS_MASK = 1 << ADVANCED_SHIFT; + } + + private SWTGraphics swtGraphics; + + private Graphics2D graphics2D; + + private BasicStroke stroke; + + private Stack<State> states = new Stack<State>(); + + private final State currentState = new State(); + + private final State appliedState = new State(); + + /** + * Some strings, Asian string in particular, are painted differently between + * SWT and AWT. SWT falls back to some default locale font if Asian string + * cannot be painted with the current font - this is done via the platform. + * AWT, unlike platform biased SWT, does not. Hence, Asian string widths are + * very different between SWT and AWT. To workaround the issue, if the flag + * below is set to <code>true</code> then once SWT and AWT string width are + * not equal, a bitmap of the SWT string will be painted. Otherwise the + * string is always painted with AWT Graphics 2D string rendering. + */ + protected boolean paintNotCompatibleStringsAsBitmaps = true; + + private static final TextUtilitiesEx TEXT_UTILITIES = new TextUtilitiesEx(MapModeTypes.IDENTITY_MM); + + private Rectangle relativeClipRegion; + + private org.eclipse.swt.graphics.Rectangle viewBox; + + private Image image; + + /** + * x coordinate for graphics translation + */ + private int transX = 0; + + /** + * y coordinate for graphics translation + */ + private int transY = 0; + + /** + * Constructor + * + * @param graphics + * the <code>Graphics2D</code> object that this object is + * delegating calls to. + * @param viewPort + * the <code>Rectangle</code> that defines the logical area being + * rendered by the graphics object. + */ + public SiriusGraphicsToGraphics2DAdaptor(Graphics2D graphics, Rectangle viewPort) { + + this(graphics, new org.eclipse.swt.graphics.Rectangle(viewPort.x, viewPort.y, viewPort.width, viewPort.height)); + } + + /** + * Alternate Constructor that takes an swt Rectangle + * + * @param graphics + * the <code>Graphics2D</code> object that this object is + * delegating calls to. + * @param viewPort + * the <code>org.eclipse.swt.graphics.Rectangle</code> that + * defines the logical area being rendered by the graphics + * object. + */ + public SiriusGraphicsToGraphics2DAdaptor(Graphics2D graphics, org.eclipse.swt.graphics.Rectangle viewPort) { + + // Save the ViewPort to add to the root DOM element + viewBox = viewPort; + + // Create the SWT Graphics Object + createSWTGraphics(); + + // Initialize the SVG Graphics Object + initSVGGraphics(graphics); + + // Initialize the States + init(); + } + + /** + * This is a helper method used to create the SWT Graphics object + */ + private void createSWTGraphics() { + + // we need this temp Rect just to instantiate an swt image in order to + // keep + // state, the size of this Rect is of no consequence and we just set it + // to + // such a small size in order to minimize memory allocation + org.eclipse.swt.graphics.Rectangle tempRect = new org.eclipse.swt.graphics.Rectangle(0, 0, 10, 10); + image = new Image(DisplayUtils.getDisplay(), tempRect); + GC gc = new GC(image); + swtGraphics = new SWTGraphics(gc); + } + + /** + * Create the SVG graphics object and initializes it with the current line + * stlye and width + */ + private void initSVGGraphics(Graphics2D graphics) { + this.graphics2D = graphics; + + relativeClipRegion = new Rectangle(viewBox.x, viewBox.y, viewBox.width, viewBox.height); + + // Initialize the line style and width + stroke = new BasicStroke(swtGraphics.getLineWidth(), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 0, null, 0); + LineAttributes lineAttributes = new LineAttributes(1); + swtGraphics.getLineAttributes(lineAttributes); + setLineAttributes(lineAttributes); + setFillRule(swtGraphics.getFillRule()); + setAdvanced(swtGraphics.getAdvanced()); + getGraphics2D().setStroke(stroke); + } + + /** + * This method should only be called by the constructor. Initializes state + * information for the currentState + */ + private void init() { + + // Initialize drawing styles + setForegroundColor(getForegroundColor()); + setBackgroundColor(getBackgroundColor()); + setXORMode(getXORMode()); + + // Initialize Font + setFont(getFont()); + currentState.font = appliedState.font = getFont(); + + // Initialize translations + currentState.translateX = appliedState.translateX = transX; + currentState.translateY = appliedState.translateY = transY; + + // Initialize Clip Regions + currentState.clipX = appliedState.clipX = relativeClipRegion.x; + currentState.clipY = appliedState.clipY = relativeClipRegion.y; + currentState.clipW = appliedState.clipW = relativeClipRegion.width; + currentState.clipH = appliedState.clipH = relativeClipRegion.height; + + currentState.alpha = appliedState.alpha = getAlpha(); + + } + + /** + * Verifies that the applied state is up to date with the current state and + * updates the applied state accordingly. + */ + protected void checkState() { + + if (appliedState.font != currentState.font) { + appliedState.font = currentState.font; + + setFont(currentState.font); + } + + if (appliedState.clipX != currentState.clipX || appliedState.clipY != currentState.clipY || appliedState.clipW != currentState.clipW || appliedState.clipH != currentState.clipH) { + + appliedState.clipX = currentState.clipX; + appliedState.clipY = currentState.clipY; + appliedState.clipW = currentState.clipW; + appliedState.clipH = currentState.clipH; + + // Adjust the clip for SVG + getGraphics2D().setClip(currentState.clipX - 1, currentState.clipY - 1, currentState.clipW + 2, currentState.clipH + 2); + } + + if (appliedState.alpha != currentState.alpha) { + appliedState.alpha = currentState.alpha; + + setAlpha(currentState.alpha); + } + + appliedState.graphicHints = currentState.graphicHints; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#clipRect(org.eclipse.draw2d.geometry. + * Rectangle) + */ + @Override + public void clipRect(Rectangle rect) { + relativeClipRegion.intersect(rect); + setClipAbsolute(relativeClipRegion.x + transX, relativeClipRegion.y + transY, relativeClipRegion.width, relativeClipRegion.height); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#dispose() + */ + @Override + public void dispose() { + swtGraphics.dispose(); + + if (image != null) { + image.dispose(); + } + + states.clear(); + } + + /** + * This method is used to convert an SWT Color to an AWT Color. + * + * @param toConvert + * SWT Color to convert + * @return AWT Color + */ + protected java.awt.Color getColor(Color toConvert) { + + return new java.awt.Color(toConvert.getRed(), toConvert.getGreen(), toConvert.getBlue()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawArc(int, int, int, int, int, int) + */ + @Override + public void drawArc(int x, int y, int width, int height, int startAngle, int endAngle) { + + Arc2D arc = new Arc2D.Float(x + transX, y + transY, width - 1, height, startAngle, endAngle, Arc2D.OPEN); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(arc); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillArc(int, int, int, int, int, int) + */ + @Override + public void fillArc(int x, int y, int w, int h, int offset, int length) { + + Arc2D arc = new Arc2D.Float(x + transX, y + transY, w, h, offset, length, Arc2D.OPEN); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(arc); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawFocus(int, int, int, int) + */ + @Override + public void drawFocus(int x, int y, int w, int h) { + drawRectangle(x, y, w, h); + } + + @Override + public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) { + checkState(); + if (!layout.getBounds().isEmpty()) { + Image image = new Image(DisplayUtils.getDisplay(), layout.getBounds().width, layout.getBounds().height); + GC gc = new GC(image); + cloneGC(gc); + layout.draw(gc, 0, 0, selectionStart, selectionEnd, selectionForeground, selectionBackground); + + ImageData imageData = image.getImageData(); + imageData.transparentPixel = imageData.palette.getPixel(getBackgroundColor().getRGB()); + + gc.dispose(); + image.dispose(); + + getGraphics2D().drawImage(ImageConverter.convertFromImageData(imageData), x + transX, y + transY, null); + } + } + + private void cloneGC(GC gc) { + gc.setAdvanced(getAdvanced()); + gc.setAlpha(getAlpha()); + gc.setAntialias(getAntialias()); + gc.setFillRule(getFillRule()); + gc.setFont(getFont()); + gc.setInterpolation(getInterpolation()); + gc.setLineAttributes(getLineAttributes()); + gc.setTextAntialias(getTextAntialias()); + gc.setBackground(getBackgroundColor()); + gc.setForeground(getForegroundColor()); + } + + @Override + public int getInterpolation() { + return swtGraphics.getInterpolation(); + } + + @Override + public LineAttributes getLineAttributes() { + LineAttributes la = new LineAttributes(1); + swtGraphics.getLineAttributes(la); + return la; + } + + @Override + public int getTextAntialias() { + return swtGraphics.getTextAntialias(); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.draw2d.Graphics#drawImage(org.eclipse.swt.graphics.Image, + * int, int) + */ + @Override + public void drawImage(Image srcImage, int xpos, int ypos) { + + // Translate the Coordinates + xpos += transX; + ypos += transY; + + // Convert the SWT Image into an AWT BufferedImage + BufferedImage toDraw = ImageConverter.convert(srcImage); + + checkState(); + getGraphics2D().drawImage(toDraw, new AffineTransform(1f, 0f, 0f, 1f, xpos, ypos), null); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.draw2d.Graphics#drawImage(org.eclipse.swt.graphics.Image, + * int, int, int, int, int, int, int, int) + */ + @Override + public void drawImage(Image srcImage, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { + + x2 += transX; + y2 += transY; + + BufferedImage toDraw = ImageConverter.convert(srcImage); + checkState(); + getGraphics2D().drawImage(toDraw, x2, y2, w2, h2, null); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawLine(int, int, int, int) + */ + @Override + public void drawLine(int x1, int y1, int x2, int y2) { + + Line2D line = new Line2D.Float(x1 + transX, y1 + transY, x2 + transX, y2 + transY); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(line); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawOval(int, int, int, int) + */ + @Override + public void drawOval(int x, int y, int w, int h) { + + Ellipse2D ellipse = new Ellipse2D.Float(x + transX, y + transY, w, h); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(ellipse); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillOval(int, int, int, int) + */ + @Override + public void fillOval(int x, int y, int w, int h) { + + Ellipse2D ellipse = new Ellipse2D.Float(x + transX, y + transY, w - 1, h - 1); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(ellipse); + } + + private Polygon createPolygon(PointList pointList) { + + Polygon toCreate = new Polygon(); + + for (int i = 0; i < pointList.size(); i++) { + Point pt = pointList.getPoint(i); + + toCreate.addPoint(pt.x + transX, pt.y + transY); + } + + return toCreate; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawPolygon(org.eclipse.draw2d.geometry. + * PointList) + */ + @Override + public void drawPolygon(PointList pointList) { + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(createPolygon(pointList)); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillPolygon(org.eclipse.draw2d.geometry. + * PointList) + */ + @Override + public void fillPolygon(PointList pointList) { + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(createPolygon(pointList)); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.draw2d.Graphics#drawPolyline(org.eclipse.draw2d.geometry. + * PointList) + */ + @Override + public void drawPolyline(PointList pointList) { + + // Draw polylines as a series of lines + for (int x = 1; x < pointList.size(); x++) { + + Point p1 = pointList.getPoint(x - 1); + Point p2 = pointList.getPoint(x); + + drawLine(p1.x, p1.y, p2.x, p2.y); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawRectangle(int, int, int, int) + */ + @Override + public void drawRectangle(int x, int y, int w, int h) { + + Rectangle2D rect = new Rectangle2D.Float(x + transX, y + transY, w, h); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(rect); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillRectangle(int, int, int, int) + */ + @Override + public void fillRectangle(int x, int y, int width, int height) { + + Rectangle2D rect = new Rectangle2D.Float(x + transX, y + transY, width, height); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(rect); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawRoundRectangle(org.eclipse.draw2d. + * geometry.Rectangle, int, int) + */ + @Override + public void drawRoundRectangle(Rectangle rect, int arcWidth, int arcHeight) { + + RoundRectangle2D roundRect = new RoundRectangle2D.Float(rect.x + transX, rect.y + transY, rect.width, rect.height, arcWidth, arcHeight); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(roundRect); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillRoundRectangle(org.eclipse.draw2d. + * geometry.Rectangle, int, int) + */ + @Override + public void fillRoundRectangle(Rectangle rect, int arcWidth, int arcHeight) { + + RoundRectangle2D roundRect = new RoundRectangle2D.Float(rect.x + transX, rect.y + transY, rect.width, rect.height, arcWidth, arcHeight); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(roundRect); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawText(java.lang.String, int, int) + */ + @Override + public void drawText(String s, int x, int y) { + drawString(s, x, y); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawString(java.lang.String, int, int) + */ + @Override + public void drawString(String s, int x, int y) { + + if (s == null || s.length() == 0) + return; + + java.awt.FontMetrics metrics = getGraphics2D().getFontMetrics(); + int stringLength = metrics.stringWidth(s); + Dimension swtStringSize = TEXT_UTILITIES.getStringExtents(s, swtGraphics.getFont()); + + float xpos = x + transX; + float ypos = y + transY; + int lineWidth; + + String drawStringAsImageProperty = System.getProperty("drawStringAsImage");//$NON-NLS-1$ + boolean drawStringAsImage = drawStringAsImageProperty == null ? false : drawStringAsImageProperty.equals("true"); //$NON-NLS-1$ + if (drawStringAsImage || (paintNotCompatibleStringsAsBitmaps && (getGraphics2D().getFont().canDisplayUpTo(s) != -1))) { + // create SWT bitmap of the string then + Image image = new Image(DisplayUtils.getDisplay(), swtStringSize.width, swtStringSize.height); + GC gc = new GC(image); + gc.setForeground(getForegroundColor()); + gc.setBackground(getBackgroundColor()); + gc.setAntialias(getAntialias()); + gc.setFont(getFont()); + gc.drawString(s, 0, 0); + gc.dispose(); + ImageData data = image.getImageData(); + image.dispose(); + RGB backgroundRGB = getBackgroundColor().getRGB(); + for (int i = 0; i < data.width; i++) { + for (int j = 0; j < data.height; j++) { + if (data.palette.getRGB(data.getPixel(i, j)).equals(backgroundRGB)) { + data.setAlpha(i, j, 0); + } else { + data.setAlpha(i, j, 255); + } + } + } + checkState(); + getGraphics2D().drawImage(ImageConverter.convertFromImageData(data), new AffineTransform(1f, 0f, 0f, 1f, xpos, ypos), null); + stringLength = swtStringSize.width; + } else { + + ypos += metrics.getAscent(); + + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().drawString(s, xpos, ypos); + } + + if (isFontUnderlined(getFont())) { + int baseline = y + metrics.getAscent(); + lineWidth = getLineWidth(); + + setLineWidth(1); + drawLine(x, baseline, x + stringLength, baseline); + setLineWidth(lineWidth); + } + + if (isFontStrikeout(getFont())) { + int strikeline = y + (metrics.getHeight() / 2); + lineWidth = getLineWidth(); + + setLineWidth(1); + drawLine(x, strikeline, x + stringLength, strikeline); + setLineWidth(lineWidth); + } + + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillString(java.lang.String, int, int) + */ + @Override + public void fillString(String s, int x, int y) { + // Not implemented + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillText(java.lang.String, int, int) + */ + @Override + public void fillText(String s, int x, int y) { + // Not implemented + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getBackgroundColor() + */ + @Override + public Color getBackgroundColor() { + return swtGraphics.getBackgroundColor(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getClip(org.eclipse.draw2d.geometry. + * Rectangle) + */ + @Override + public Rectangle getClip(Rectangle rect) { + rect.setBounds(relativeClipRegion); + return rect; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getFont() + */ + @Override + public Font getFont() { + return swtGraphics.getFont(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getFontMetrics() + */ + @Override + public FontMetrics getFontMetrics() { + return swtGraphics.getFontMetrics(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getForegroundColor() + */ + @Override + public Color getForegroundColor() { + return swtGraphics.getForegroundColor(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getLineStyle() + */ + @Override + public int getLineStyle() { + return swtGraphics.getLineStyle(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getLineWidth() + */ + @Override + public int getLineWidth() { + return swtGraphics.getLineWidth(); + } + + @Override + public float getLineWidthFloat() { + return swtGraphics.getLineWidthFloat(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getXORMode() + */ + @Override + public boolean getXORMode() { + return swtGraphics.getXORMode(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#popState() + */ + @Override + public void popState() { + swtGraphics.popState(); + + restoreState(states.pop()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#pushState() + */ + @Override + public void pushState() { + swtGraphics.pushState(); + + // Make a copy of the current state and push it onto the stack + State toPush = new State(); + toPush.copyFrom(currentState); + states.push(toPush); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#restoreState() + */ + @Override + public void restoreState() { + swtGraphics.restoreState(); + + restoreState(states.peek()); + } + + private void restoreState(State state) { + + setBackgroundColor(state.bgColor); + setForegroundColor(state.fgColor); + setLineAttributes(state.lineAttributes); + setXORMode(state.XorMode); + + setClipAbsolute(state.clipX, state.clipY, state.clipW, state.clipH); + + transX = currentState.translateX = state.translateX; + transY = currentState.translateY = state.translateY; + + relativeClipRegion.x = state.clipX - transX; + relativeClipRegion.y = state.clipY - transY; + relativeClipRegion.width = state.clipW; + relativeClipRegion.height = state.clipH; + + currentState.font = state.font; + currentState.alpha = state.alpha; + + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#scale(double) + */ + @Override + public void scale(double amount) { + swtGraphics.scale(amount); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.draw2d.Graphics#setBackgroundColor(org.eclipse.swt.graphics. + * Color) + */ + @Override + public void setBackgroundColor(Color rgb) { + currentState.bgColor = rgb; + swtGraphics.setBackgroundColor(rgb); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setClip(org.eclipse.draw2d.geometry. + * Rectangle) + */ + @Override + public void setClip(Rectangle rect) { + + relativeClipRegion.x = rect.x; + relativeClipRegion.y = rect.y; + relativeClipRegion.width = rect.width; + relativeClipRegion.height = rect.height; + + setClipAbsolute(rect.x + transX, rect.y + transY, rect.width, rect.height); + } + + /** + * Sets the current clip values + * + * @param x + * the x value + * @param y + * the y value + * @param width + * the width value + * @param height + * the height value + */ + private void setClipAbsolute(int x, int y, int width, int height) { + currentState.clipX = x; + currentState.clipY = y; + currentState.clipW = width; + currentState.clipH = height; + } + + private boolean isFontUnderlined(Font f) { + return false; + } + + private boolean isFontStrikeout(Font f) { + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setFont(org.eclipse.swt.graphics.Font) + */ + @Override + public void setFont(Font f) { + + swtGraphics.setFont(f); + currentState.font = f; + + FontData[] fontInfo = f.getFontData(); + + if (fontInfo[0] != null) { + + int height = fontInfo[0].getHeight(); + + float fsize = (float) height * (float) DisplayUtils.getDisplay().getDPI().x / 72.0f; + height = Math.round(fsize); + + int style = fontInfo[0].getStyle(); + boolean bItalic = (style & SWT.ITALIC) == SWT.ITALIC; + boolean bBold = (style & SWT.BOLD) == SWT.BOLD; + String faceName = fontInfo[0].getName(); + int escapement = 0; + + boolean bUnderline = isFontUnderlined(f); + boolean bStrikeout = isFontStrikeout(f); + + GdiFont font = new GdiFont(height, bItalic, bUnderline, bStrikeout, bBold, faceName, escapement); + + getGraphics2D().setFont(font.getFont()); + } + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.draw2d.Graphics#setForegroundColor(org.eclipse.swt.graphics. + * Color) + */ + @Override + public void setForegroundColor(Color rgb) { + currentState.fgColor = rgb; + swtGraphics.setForegroundColor(rgb); + } + + /** + * Sets the dash pattern when the custom line style is in use. Because this + * feature is rarely used, the dash pattern may not be preserved when + * calling {@link #pushState()} and {@link #popState()}. + * + * @param dash + * the pixel pattern + * + */ + @Override + public void setLineDash(int[] dash) { + float dashFlt[] = new float[dash.length]; + for (int i = 0; i < dash.length; i++) { + dashFlt[i] = dash[i]; + } + setLineDash(dashFlt); + } + + @Override + public void setLineDash(float[] dash) { + currentState.lineAttributes.dash = dash; + setLineStyle(SWTGraphics.LINE_CUSTOM); + swtGraphics.setLineDash(dash); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setLineStyle(int) + */ + @Override + public void setLineStyle(int style) { + currentState.lineAttributes.style = style; + swtGraphics.setLineStyle(style); + } + + /** + * ignored + */ + @Override + public void setLineMiterLimit(float miterLimit) { + // do nothing + } + + /** + * ignored + */ + @Override + public void setLineCap(int cap) { + // do nothing + } + + /** + * ignored + */ + @Override + public void setLineJoin(int join) { + // do nothing + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setLineWidth(int) + */ + @Override + public void setLineWidth(int width) { + setLineWidthFloat(width); + } + + @Override + public void setLineWidthFloat(float width) { + currentState.lineAttributes.width = width; + swtGraphics.setLineWidthFloat(width); + } + + @Override + public void setLineAttributes(LineAttributes lineAttributes) { + SWTGraphics.copyLineAttributes(currentState.lineAttributes, lineAttributes); + swtGraphics.setLineAttributes(lineAttributes); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setXORMode(boolean) + */ + @Override + public void setXORMode(boolean xorMode) { + currentState.XorMode = xorMode; + swtGraphics.setXORMode(xorMode); + } + + /** + * Sets the current translation values + * + * @param x + * the x translation value + * @param y + * the y translation value + */ + private void setTranslation(int x, int y) { + transX = currentState.translateX = x; + transY = currentState.translateY = y; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#translate(int, int) + */ + @Override + public void translate(int dx, int dy) { + swtGraphics.translate(dx, dy); + + setTranslation(transX + dx, transY + dy); + relativeClipRegion.x -= dx; + relativeClipRegion.y -= dy; + } + + /** + * @return the <code>Graphics2D</code> that this is delegating to. + */ + protected Graphics2D getGraphics2D() { + return graphics2D; + } + + /** + * @return Returns the swtGraphics. + */ + private SWTGraphics getSWTGraphics() { + return swtGraphics; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillGradient(int, int, int, int, + * boolean) + */ + @Override + public void fillGradient(int x, int y, int w, int h, boolean vertical) { + GradientPaint gradient; + + checkState(); + + // Gradients in SWT start with Foreground Color and end at Background + java.awt.Color start = getColor(getSWTGraphics().getForegroundColor()); + java.awt.Color stop = getColor(getSWTGraphics().getBackgroundColor()); + + // Create the Gradient based on horizontal or vertical + if (vertical) { + gradient = new GradientPaint(x + transX, y + transY, start, x + transX, y + h + transY, stop); + } else { + gradient = new GradientPaint(x + transX, y + transY, start, x + w + transX, y + transY, stop); + } + + Paint oldPaint = getGraphics2D().getPaint(); + getGraphics2D().setPaint(gradient); + getGraphics2D().fill(new Rectangle2D.Double(x + transX, y + transY, w, h)); + getGraphics2D().setPaint(oldPaint); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#drawPath(org.eclipse.swt.graphics.Path) + */ + @Override + public void drawPath(Path path) { + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getForegroundColor())); + getGraphics2D().setStroke(createStroke()); + getGraphics2D().draw(createPathAWT(path)); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#fillPath(org.eclipse.swt.graphics.Path) + */ + @Override + public void fillPath(Path path) { + checkState(); + getGraphics2D().setPaint(getColor(swtGraphics.getBackgroundColor())); + getGraphics2D().fill(createPathAWT(path)); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setClip(org.eclipse.swt.graphics.Path) + */ + @Override + public void setClip(Path path) { + if (((appliedState.graphicHints ^ currentState.graphicHints) & FILL_RULE_MASK) != 0) { + // If there is a pending change to the fill rule, apply it first. + // As long as the FILL_RULE is stored in a single bit, just toggling + // it works. + appliedState.graphicHints ^= FILL_RULE_MASK; + } + getGraphics2D().setClip(createPathAWT(path)); + appliedState.clipX = currentState.clipX = 0; + appliedState.clipY = currentState.clipY = 0; + appliedState.clipW = currentState.clipW = 0; + appliedState.clipH = currentState.clipH = 0; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getFillRule() + */ + @Override + public int getFillRule() { + return ((currentState.graphicHints & FILL_RULE_MASK) >> FILL_RULE_SHIFT) - FILL_RULE_WHOLE_NUMBER; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setFillRule(int) + */ + @Override + public void setFillRule(int rule) { + currentState.graphicHints &= ~FILL_RULE_MASK; + currentState.graphicHints |= (rule + FILL_RULE_WHOLE_NUMBER) << FILL_RULE_SHIFT; + } + + private GeneralPath createPathAWT(Path path) { + GeneralPath pathAWT = new GeneralPath(); + PathData pathData = path.getPathData(); + int idx = 0; + for (int i = 0; i < pathData.types.length; i++) { + switch (pathData.types[i]) { + case SWT.PATH_MOVE_TO: + pathAWT.moveTo(pathData.points[idx++] + transX, pathData.points[idx++] + transY); + break; + case SWT.PATH_LINE_TO: + pathAWT.lineTo(pathData.points[idx++] + transX, pathData.points[idx++] + transY); + break; + case SWT.PATH_CUBIC_TO: + pathAWT.curveTo(pathData.points[idx++] + transX, pathData.points[idx++] + transY, pathData.points[idx++] + transX, pathData.points[idx++] + transY, pathData.points[idx++] + transX, + pathData.points[idx++] + transY); + break; + case SWT.PATH_QUAD_TO: + pathAWT.quadTo(pathData.points[idx++] + transX, pathData.points[idx++] + transY, pathData.points[idx++] + transX, pathData.points[idx++] + transY); + break; + case SWT.PATH_CLOSE: + pathAWT.closePath(); + break; + default: + dispose(); + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + } + int swtWindingRule = ((appliedState.graphicHints & FILL_RULE_MASK) >> FILL_RULE_SHIFT) - FILL_RULE_WHOLE_NUMBER; + if (swtWindingRule == SWT.FILL_WINDING) { + pathAWT.setWindingRule(GeneralPath.WIND_NON_ZERO); + } else if (swtWindingRule == SWT.FILL_EVEN_ODD) { + pathAWT.setWindingRule(GeneralPath.WIND_EVEN_ODD); + } else { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return pathAWT; + } + + /* + * (non-Javadoc) + * @see org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal. + * DrawableRenderedImage#drawRenderedImage(org.eclipse.gmf.runtime.draw2d.ui + * .render.RenderedImage, org.eclipse.draw2d.geometry.Rectangle, + * org.eclipse.gmf.runtime.draw2d.ui.render.RenderingListener) + */ + @Override + public RenderedImage drawRenderedImage(RenderedImage srcImage, Rectangle rect, RenderingListener listener) { + RenderInfo info = srcImage.getRenderInfo(); + info.setValues(rect.width, rect.height, info.shouldMaintainAspectRatio(), info.shouldAntiAlias(), info.getBackgroundColor(), info.getForegroundColor()); + + RenderedImage img = srcImage.getNewRenderedImage(info); + + BufferedImage bufImg = (BufferedImage) img.getAdapter(BufferedImage.class); + if (bufImg == null) { + bufImg = ImageConverter.convert(img.getSWTImage()); + } + + // Translate the Coordinates + int x = rect.x + transX; + int y = rect.y + transY + rect.height - bufImg.getHeight(); + + checkState(); + getGraphics2D().drawImage(bufImg, new AffineTransform(1f, 0f, 0f, 1f, x, y), null); + + return img; + } + + /* + * (non-Javadoc) + * @see org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal. + * DrawableRenderedImage#allowDelayRender() + */ + @Override + public boolean shouldAllowDelayRender() { + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal. + * DrawableRenderedImage#getMaximumRenderSize() + */ + @Override + public Dimension getMaximumRenderSize() { + return null; + } + + /** + * Accessor method to return the translation offset for the graphics object + * + * @return <code>Point</code> x coordinate for graphics translation + */ + protected Point getTranslationOffset() { + return new Point(transX, transY); + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#getAntialias() + */ + @Override + public int getAntialias() { + Object antiAlias = getGraphics2D().getRenderingHint(RenderingHints.KEY_ANTIALIASING); + if (antiAlias != null) { + if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_ON)) + return SWT.ON; + else if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_OFF)) + return SWT.OFF; + else if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_DEFAULT)) + return SWT.DEFAULT; + } + + return SWT.DEFAULT; + } + + /* + * (non-Javadoc) + * @see org.eclipse.draw2d.Graphics#setAntialias(int) + */ + @Override + public void setAntialias(int value) { + if (value == SWT.ON) { + getGraphics2D().setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else if (value == SWT.OFF) { + getGraphics2D().setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + setAdvanced(true); + } + + @Override + public int getAlpha() { + return swtGraphics.getAlpha(); + } + + @Override + public void setAlpha(int alpha) { + swtGraphics.setAlpha(alpha); + currentState.alpha = alpha; + + Composite composite = getGraphics2D().getComposite(); + if (composite instanceof AlphaComposite) { + AlphaComposite newComposite = AlphaComposite.getInstance(((AlphaComposite) composite).getRule(), (float) alpha / (float) 255); + getGraphics2D().setComposite(newComposite); + } + } + + protected BasicStroke getStroke() { + return stroke; + } + + protected void setStroke(BasicStroke stroke) { + this.stroke = stroke; + getGraphics2D().setStroke(stroke); + } + + /** + * Sets and retirns AWT Stroke based on the value of + * <code>LineAttributes</code> within the current state object + * + * @return the new AWT stroke + */ + private Stroke createStroke() { + float factor = currentState.lineAttributes.width > 0 ? currentState.lineAttributes.width : 3; + float awt_dash[]; + int awt_cap; + int awt_join; + + switch (currentState.lineAttributes.style) { + case SWTGraphics.LINE_DASH: + awt_dash = new float[] { factor * 6, factor * 3 }; + break; + case SWTGraphics.LINE_DASHDOT: + awt_dash = new float[] { factor * 3, factor, factor, factor }; + break; + case SWTGraphics.LINE_DASHDOTDOT: + awt_dash = new float[] { factor * 3, factor, factor, factor, factor, factor }; + break; + case SWTGraphics.LINE_DOT: + awt_dash = new float[] { factor, factor }; + break; + case SWTGraphics.LINE_CUSTOM: + awt_dash = currentState.lineAttributes.dash; + break; + default: + awt_dash = null; + } + + switch (currentState.lineAttributes.cap) { + case SWT.CAP_FLAT: + awt_cap = BasicStroke.CAP_BUTT; + break; + case SWT.CAP_ROUND: + awt_cap = BasicStroke.CAP_ROUND; + break; + case SWT.CAP_SQUARE: + awt_cap = BasicStroke.CAP_SQUARE; + break; + default: + awt_cap = BasicStroke.CAP_BUTT; + } + + switch (currentState.lineAttributes.join) { + case SWT.JOIN_BEVEL: + awt_join = BasicStroke.JOIN_BEVEL; + break; + case SWT.JOIN_MITER: + awt_join = BasicStroke.JOIN_MITER; + break; + case SWT.JOIN_ROUND: + awt_join = BasicStroke.JOIN_ROUND; + break; + default: + awt_join = BasicStroke.JOIN_MITER; + } + + /* + * SWT paints line width == 0 as if it is == 1, so AWT is synced up with + * that below. + */ + stroke = new BasicStroke(currentState.lineAttributes.width != 0 ? currentState.lineAttributes.width : 1, awt_cap, awt_join, currentState.lineAttributes.miterLimit, awt_dash, + currentState.lineAttributes.dashOffset); + return stroke; + } + + @Override + public boolean getAdvanced() { + return (currentState.graphicHints & ADVANCED_GRAPHICS_MASK) != 0; + } + + @Override + public void setAdvanced(boolean value) { + if (value) { + currentState.graphicHints |= ADVANCED_GRAPHICS_MASK; + } else { + currentState.graphicHints &= ~ADVANCED_GRAPHICS_MASK; + } + } + + @Override + public void clipPath(Path path) { + if (((appliedState.graphicHints ^ currentState.graphicHints) & FILL_RULE_MASK) != 0) { + // If there is a pending change to the fill rule, apply it first. + // As long as the FILL_RULE is stored in a single bit, just toggling + // it works. + appliedState.graphicHints ^= FILL_RULE_MASK; + } + setClip(path); + getGraphics2D().clipRect(relativeClipRegion.x + transX, relativeClipRegion.y + transY, relativeClipRegion.width, relativeClipRegion.height); + java.awt.Rectangle bounds = getGraphics2D().getClip().getBounds(); + relativeClipRegion = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); + } + +} +// CHECKSTYLE:ON |
