Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/.classpath7
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/.cvsignore1
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/.project34
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/META-INF/MANIFEST.MF21
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/build.properties4
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/Activator.java47
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/ImageTranscoderEx.java205
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SVGGraphics2D.java432
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SimpleImageTranscoder.java34
-rw-r--r--plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/runtime/lite/svg/SVGFigure.java135
10 files changed, 920 insertions, 0 deletions
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/.classpath b/plugins/org.eclipse.gmf.runtime.lite.svg/.classpath
new file mode 100644
index 000000000..64c5e31b7
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/.cvsignore b/plugins/org.eclipse.gmf.runtime.lite.svg/.cvsignore
new file mode 100644
index 000000000..5e83119b7
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/.cvsignore
@@ -0,0 +1 @@
+.settings
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/.project b/plugins/org.eclipse.gmf.runtime.lite.svg/.project
new file mode 100644
index 000000000..bba2d3a7e
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.gmf.runtime.lite.svg</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/META-INF/MANIFEST.MF b/plugins/org.eclipse.gmf.runtime.lite.svg/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..67970d5bc
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GMF SVG Support
+Bundle-SymbolicName: org.eclipse.gmf.runtime.lite.svg;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.gmf.internal.runtime.lite.svg.Activator
+Bundle-Vendor: Eclipse.org
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.draw2d,
+ org.apache.batik.bridge,
+ org.apache.batik.dom,
+ org.apache.batik.dom.svg,
+ org.apache.batik.ext.awt,
+ org.apache.batik.svggen,
+ org.apache.batik.transcoder,
+ org.apache.batik.util,
+ org.w3c.dom.svg
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.gmf.runtime.lite.svg
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/build.properties b/plugins/org.eclipse.gmf.runtime.lite.svg/build.properties
new file mode 100644
index 000000000..34d2e4d2d
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/Activator.java b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/Activator.java
new file mode 100644
index 000000000..cff62f6a3
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/Activator.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2008 Borland Software 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:
+ * Dmitry Stadnik - initial API and implementation
+ */
+package org.eclipse.gmf.internal.runtime.lite.svg;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends AbstractUIPlugin {
+
+ public static final String PLUGIN_ID = "org.eclipse.gmf.runtime.lite.svg";
+
+ private static Activator plugin;
+
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ public static void log(int severity, String message, Throwable t) {
+ IStatus status = new Status(severity, PLUGIN_ID, 0, message, t);
+ getDefault().getLog().log(status);
+ }
+
+ public static void logError(String message, Throwable t) {
+ log(IStatus.ERROR, message, t);
+ }
+}
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/ImageTranscoderEx.java b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/ImageTranscoderEx.java
new file mode 100644
index 000000000..a8085be60
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/ImageTranscoderEx.java
@@ -0,0 +1,205 @@
+/**
+ * Copyright (c) 2008 Borland Software 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:
+ * Dmitry Stadnik - initial API and implementation
+ */
+package org.eclipse.gmf.internal.runtime.lite.svg;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.batik.bridge.BaseScriptingEnvironment;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.BridgeException;
+import org.apache.batik.bridge.GVTBuilder;
+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.ext.awt.image.GraphicsUtil;
+import org.apache.batik.gvt.CanvasGraphicsNode;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.ImageTranscoder;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.svg.SVGSVGElement;
+
+public class ImageTranscoderEx extends ImageTranscoder {
+
+ private BufferedImage bufferedImage;
+
+ /**
+ * buildGVTTree This method builds the GVT tree that is used to render the SVG data.
+ *
+ * @param svgDoc SVGOMDocument representing the physical SVG document.
+ * @param context BridgeContext containing information of the render to occur.
+ * @return GraphicsNode object.
+ * @throws TranscoderException thrown if a BridgeException occurs when building the root object.
+ */
+ protected GraphicsNode buildGVTTree(SVGOMDocument svgDoc, BridgeContext context) throws TranscoderException {
+ GVTBuilder gvtBuilder = new GVTBuilder();
+ try {
+ return gvtBuilder.build(context, svgDoc);
+ } catch (BridgeException ex) {
+ throw new TranscoderException(ex);
+ }
+ }
+
+ /**
+ * calculateSizeTransform Calculates the transformation matrix that is applied during the render operation. Specifically,
+ * the transformation for changing the size of the rendered data.
+ *
+ * @param svgRoot SVGSVGElement root element of the SVG tree.
+ * @param gvtRoot GraphicsNode graphic node root
+ * @param docWidth float width values of the original vector.
+ * @param docHeight float height values of the original vector.
+ * @param newWidth float width values of the rendered image.
+ * @param newHeight float height values of the rendered image.
+ * @return AffineTransform object that represents the size transformation to take place.
+ * @throws TranscoderException thrown if a BridgeException occurs when building the root object.
+ */
+ protected AffineTransform calculateSizeTransform(SVGSVGElement svgRoot, GraphicsNode gvtRoot, float docWidth,
+ float docHeight, float newWidth, float newHeight) throws TranscoderException {
+ AffineTransform Px;
+ float xscale = newWidth / docWidth;
+ float yscale = newHeight / docHeight;
+ Px = AffineTransform.getScaleInstance(xscale, yscale);
+
+ // take the AOI into account if any
+ if (hints.containsKey(KEY_AOI)) {
+ Rectangle2D aoi = (Rectangle2D) hints.get(KEY_AOI);
+ // transform the AOI into the image's coordinate system
+ aoi = Px.createTransformedShape(aoi).getBounds2D();
+ AffineTransform Mx = new AffineTransform();
+ double sx = newWidth / aoi.getWidth();
+ double sy = newHeight / aoi.getHeight();
+ Mx.scale(sx, sy);
+ double tx = -aoi.getX();
+ double ty = -aoi.getY();
+ Mx.translate(tx, ty);
+
+ // take the AOI transformation matrix into account
+ // we apply first the preserveAspectRatio matrix
+ Px.preConcatenate(Mx);
+ }
+
+ CanvasGraphicsNode cgn = getCanvasGraphicsNode(gvtRoot);
+ if (cgn != null) {
+ cgn.setViewingTransform(Px);
+ curTxf = new AffineTransform();
+ } else {
+ curTxf = Px;
+ }
+
+ return curTxf;
+ }
+
+ private boolean shouldCopyDocument(Document document) {
+ if (!(document.getImplementation() instanceof SVGDOMImplementation)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Transcodes the specified Document as an image in the specified output.
+ *
+ * @param document the document to transcode
+ * @param uri the uri of the document or null if any
+ * @param output the ouput where to transcode
+ * @exception TranscoderException if an error occured while transcoding
+ */
+ protected void transcode(Document document, String uri, TranscoderOutput output) throws TranscoderException {
+ if (shouldCopyDocument(document)) {
+ DOMImplementation impl;
+ impl = SVGDOMImplementation.getDOMImplementation();
+ document = DOMUtilities.deepCloneDocument(document, impl);
+ if (uri != null) {
+ try {
+ URL url = new URL(uri);
+ ((SVGOMDocument) document).setURLObject(url);
+ } catch (MalformedURLException mue) {
+ //TODO: Implement error handling
+ }
+ }
+ }
+
+ ctx = new BridgeContext(userAgent);
+ SVGOMDocument svgDoc = (SVGOMDocument) document;
+ SVGSVGElement svgRoot = svgDoc.getRootElement();
+
+ // build the GVT tree
+ builder = new GVTBuilder();
+ // flag that indicates if the document is dynamic
+ boolean isDynamic = (hints.containsKey(KEY_EXECUTE_ONLOAD) && ((Boolean) hints.get(KEY_EXECUTE_ONLOAD)).booleanValue() && BaseScriptingEnvironment
+ .isDynamicDocument(ctx, svgDoc));
+
+ if (isDynamic) {
+ ctx.setDynamicState(BridgeContext.DYNAMIC);
+ }
+
+ GraphicsNode gvtRoot;
+ try {
+ gvtRoot = builder.build(ctx, svgDoc);
+ } catch (BridgeException ex) {
+ throw new TranscoderException(ex);
+ }
+
+ // get the 'width' and 'height' attributes of the SVG document
+ float docWidth = (float) ctx.getDocumentSize().getWidth();
+ float docHeight = (float) ctx.getDocumentSize().getHeight();
+
+ setImageSize(docWidth, docHeight);
+
+ //compute the transformation matrix
+ AffineTransform Px = calculateSizeTransform(svgRoot, gvtRoot, docWidth, docHeight, width, height);
+
+ gvtRoot = renderImage(output, gvtRoot, Px, (int) width, (int) height);
+
+ this.root = gvtRoot;
+ }
+
+ private GraphicsNode renderImage(TranscoderOutput output, GraphicsNode gvtRoot, AffineTransform Px, int w, int h)
+ throws TranscoderException {
+ Graphics2D g2d = createGraphics(w, h);
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.clip(new java.awt.Rectangle(0, 0, w, h));
+ g2d.transform(Px);
+ gvtRoot.paint(g2d);
+ postRenderImage(g2d);
+ return null;
+ }
+
+ protected Graphics2D createGraphics(int w, int h) {
+ bufferedImage = createImage(w, h);
+ Graphics2D g2d = GraphicsUtil.createGraphics(bufferedImage);
+ return g2d;
+ }
+
+ protected void postRenderImage(Graphics2D g2d) {
+ g2d.dispose();
+ }
+
+ public BufferedImage getBufferedImage() {
+ return bufferedImage;
+ }
+
+ public BufferedImage createImage(int w, int h) {
+ return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public void writeImage(BufferedImage img, TranscoderOutput output) throws TranscoderException {
+ }
+}
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SVGGraphics2D.java b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SVGGraphics2D.java
new file mode 100644
index 000000000..f86f07866
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SVGGraphics2D.java
@@ -0,0 +1,432 @@
+/**
+ * Copyright (c) 2008 Borland Software 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:
+ * Dmitry Stadnik - initial API and implementation
+ */
+package org.eclipse.gmf.internal.runtime.lite.svg;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+
+import org.apache.batik.ext.awt.g2d.DefaultGraphics2D;
+import org.apache.batik.ext.awt.g2d.GraphicContext;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Path;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class SVGGraphics2D extends DefaultGraphics2D {
+
+ private final AffineTransform IDENTITY = new AffineTransform();
+ private final Stroke DEFAULT_STROKE = new BasicStroke();
+
+ private Graphics swtGraphics;
+ private org.eclipse.swt.graphics.Font currentFont;
+ private org.eclipse.swt.graphics.Color currentColor;
+ private GraphicsConfiguration gconfig; // Used to create proper font metrics
+
+ {
+ BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ gconfig = bi.createGraphics().getDeviceConfiguration();
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return gconfig;
+ }
+
+ public SVGGraphics2D(Graphics swtGraphics) {
+ super(true);
+ gc = new GraphicContext();
+ this.swtGraphics = swtGraphics;
+ }
+
+ public void dispose() {
+ if (currentColor != null) {
+ currentColor.dispose();
+ currentColor = null;
+ }
+ if (currentFont != null) {
+ currentFont.dispose();
+ currentFont = null;
+ }
+ swtGraphics = null;
+ }
+
+ protected Device getDevice() {
+ return Display.getCurrent();
+ }
+
+ protected final boolean configureGraphics() {
+ //swtGraphics.pushState();
+ boolean supported = true;
+ supported &= configureStroke(getStroke());
+ supported &= configureTransformation(getTransform());
+ supported &= configureClipping(getClip());
+ supported &= configureComposite(getComposite());
+ supported &= configurePaintMode(getPaint());
+ supported &= configureRenderingHints();
+ return supported;
+ }
+
+ private boolean configureRenderingHints() {
+ Object antiAlias = getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+ if (antiAlias != null) {
+ if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_ON))
+ swtGraphics.setAntialias(SWT.ON);
+ else if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_OFF))
+ swtGraphics.setAntialias(SWT.OFF);
+ else if (antiAlias.equals(RenderingHints.VALUE_ANTIALIAS_DEFAULT))
+ swtGraphics.setAntialias(SWT.DEFAULT);
+ }
+
+ Object textAntiAlias = getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
+ if (textAntiAlias != null) {
+ if (textAntiAlias.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_ON))
+ swtGraphics.setTextAntialias(SWT.ON);
+ else if (textAntiAlias.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF))
+ swtGraphics.setTextAntialias(SWT.OFF);
+ else if (textAntiAlias.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT))
+ swtGraphics.setTextAntialias(SWT.DEFAULT);
+ }
+
+ Object interpolation = getRenderingHint(RenderingHints.KEY_INTERPOLATION);
+ if (interpolation != null) {
+ if (interpolation.equals(RenderingHints.VALUE_INTERPOLATION_BICUBIC))
+ swtGraphics.setInterpolation(SWT.HIGH);
+ else if (interpolation.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ swtGraphics.setInterpolation(SWT.LOW);
+ else if (interpolation.equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ swtGraphics.setInterpolation(SWT.NONE);
+ }
+ return true;
+ }
+
+ private boolean configureStroke(Stroke s) {
+ if (s instanceof BasicStroke) {
+ BasicStroke basicStroke = (BasicStroke) s;
+ switch (basicStroke.getEndCap()) {
+ case BasicStroke.CAP_BUTT:
+ swtGraphics.setLineCap(SWT.CAP_FLAT);
+ break;
+ case BasicStroke.CAP_ROUND:
+ swtGraphics.setLineCap(SWT.CAP_ROUND);
+ break;
+ case BasicStroke.CAP_SQUARE:
+ swtGraphics.setLineCap(SWT.CAP_SQUARE);
+ break;
+ default:
+ return false;
+ }
+
+ if (basicStroke.getDashArray() != null) {
+ swtGraphics.setLineStyle(SWT.LINE_CUSTOM);
+ float[] currentDash = basicStroke.getDashArray();
+ int[] dash = new int[currentDash.length];
+ for (int i = 0; i < currentDash.length; i++)
+ dash[i] = Math.round(currentDash[i]);
+ swtGraphics.setLineDash(dash);
+ } else {
+ swtGraphics.setLineStyle(SWT.LINE_SOLID);
+ swtGraphics.setLineDash(null);
+ }
+
+ switch (basicStroke.getLineJoin()) {
+ case BasicStroke.JOIN_BEVEL:
+ swtGraphics.setLineJoin(SWT.JOIN_BEVEL);
+ break;
+ case BasicStroke.JOIN_MITER:
+ swtGraphics.setLineJoin(SWT.JOIN_MITER);
+ break;
+ case BasicStroke.JOIN_ROUND:
+ swtGraphics.setLineJoin(SWT.JOIN_ROUND);
+ break;
+ default:
+ return false;
+ }
+
+ // since we don't have precision of less then 1 pixel in
+ // swt, if the image is defined as very small in the original
+ // file, then the linewidth gets scaled out of proportion.
+ if (basicStroke.getLineWidth() < 1 && basicStroke.getLineWidth() > 0) {
+ throw new UnsupportedOperationException();
+ }
+ swtGraphics.setLineWidth(Math.round(basicStroke.getLineWidth()));
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean configurePaintMode(Paint p) {
+ if (p instanceof Color) {
+ Color c = (Color) p;
+ if (c.getAlpha() != 255) {
+ // swt graphics doesn't support blitting onto transparency mask
+ // explicitly.
+ throw new UnsupportedOperationException();
+ }
+ RGB rgb = new RGB(c.getRed(), c.getGreen(), c.getBlue());
+ if (currentColor != null) {
+ currentColor.dispose();
+ }
+ currentColor = new org.eclipse.swt.graphics.Color(null, rgb.red, rgb.green, rgb.blue);
+ swtGraphics.setBackgroundColor(currentColor);
+ swtGraphics.setForegroundColor(currentColor);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean configureComposite(Composite c) {
+ if (c instanceof AlphaComposite) {
+ AlphaComposite ac = (AlphaComposite) c;
+
+ // swt graphics doesn't support blitting onto transparency mask
+ // explicitly.
+ if (ac.getAlpha() != 1.0)
+ throw new UnsupportedOperationException();
+
+ swtGraphics.setAlpha(Math.round(ac.getAlpha() * 255));
+ if (ac.getRule() == AlphaComposite.SRC_OVER) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean configureTransformation(AffineTransform cxPrime) {
+ swtGraphics.rotate((float) getRotation(cxPrime));
+ swtGraphics.translate((float) cxPrime.getTranslateX(), (float) cxPrime.getTranslateY());
+ return true;
+ }
+
+ private static double getRotation(final AffineTransform tr) {
+ final int flip = getFlip(tr);
+ if (flip != 0) {
+ final double scaleX = getScaleX0(tr);
+ final double scaleY = getScaleY0(tr) * flip;
+ return Math.atan2(tr.getShearY() / scaleY - tr.getShearX() / scaleX, tr.getScaleY() / scaleY + tr.getScaleX() / scaleX);
+ }
+ return Double.NaN;
+ }
+
+ private static int getFlip(final AffineTransform tr) {
+ final int scaleX = sgn(tr.getScaleX());
+ final int scaleY = sgn(tr.getScaleY());
+ final int shearX = sgn(tr.getShearX());
+ final int shearY = sgn(tr.getShearY());
+ if (scaleX == scaleY && shearX == -shearY)
+ return +1;
+ if (scaleX == -scaleY && shearX == shearY)
+ return -1;
+ return 0;
+ }
+
+ private static int sgn(double value) {
+ return value > 0 ? 1 : value < 0 ? -1 : 0;
+ }
+
+ private static double getScaleX0(final AffineTransform tr) {
+ final double scale = tr.getScaleX();
+ final double shear = tr.getShearX();
+ if (shear == 0)
+ return Math.abs(scale);
+ if (scale == 0)
+ return Math.abs(shear);
+ return Math.hypot(scale, shear);
+ }
+
+ private static double getScaleY0(final AffineTransform tr) {
+ final double scale = tr.getScaleY();
+ final double shear = tr.getShearY();
+ if (shear == 0)
+ return Math.abs(scale);
+ if (scale == 0)
+ return Math.abs(shear);
+ return Math.hypot(scale, shear);
+ }
+
+ private boolean configureClipping(Shape clipShape) {
+ Path path = getPath(getDevice(), clipShape);
+ if (path != null) {
+ swtGraphics.setClip(path);
+ }
+ return true;
+ }
+
+ protected final void resetGraphics() {
+ configureTransformation(IDENTITY);
+ configurePaintMode(Color.WHITE);
+ configureStroke(DEFAULT_STROKE);
+ configureComposite(AlphaComposite.SrcOver);
+ if (currentColor != null) {
+ currentColor.dispose();
+ currentColor = null;
+ }
+ if (currentFont != null) {
+ currentFont.dispose();
+ currentFont = null;
+ }
+ swtGraphics.setClip((Path) null);
+ //swtGraphics.popState();
+ }
+
+ public void draw(Shape s) {
+ if (!configureGraphics()) {
+ throw new UnsupportedOperationException();
+ }
+ Path path = getPath(getDevice(), s);
+ if (path != null) {
+ swtGraphics.drawPath(path);
+ }
+ resetGraphics();
+ }
+
+ public void fill(Shape s) {
+ if (!configureGraphics()) {
+ throw new UnsupportedOperationException();
+ }
+ Path path = getPath(getDevice(), s);
+ if (path != null) {
+ swtGraphics.fillPath(path);
+ }
+ resetGraphics();
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+ if (img instanceof BufferedImage && configureGraphics()) {
+ BufferedImage bufImg = (BufferedImage) img;
+ drawAWTImage(bufImg, 0, 0, bufImg.getWidth(), bufImg.getHeight(), x, y, bufImg.getWidth(), bufImg.getHeight());
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ resetGraphics();
+ return true;
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+ if (img instanceof BufferedImage && configureGraphics()) {
+ BufferedImage bufImg = (BufferedImage) img;
+ drawAWTImage((BufferedImage) img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), x, y, width, height);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ resetGraphics();
+ return true;
+ }
+
+ private void drawAWTImage(BufferedImage awtImage, int x, int y, int width, int height, int tx, int ty, int twidth, int theight) {
+ org.eclipse.swt.graphics.Image swtImage = toSWT(getDevice(), awtImage);
+ swtGraphics.drawImage(swtImage, x, y, width, height, tx, ty, twidth, theight);
+ swtImage.dispose();
+ }
+
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void drawString(String s, float x, float y) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static Path getPath(Device device, Shape s) {
+ PathIterator pi = s.getPathIterator(null);
+ Path path = new Path(device);
+ float seg[] = new float[6];
+ int segType = 0;
+ while (!pi.isDone()) {
+ segType = pi.currentSegment(seg);
+ switch (segType) {
+ case PathIterator.SEG_LINETO:
+ path.lineTo(seg[0], seg[1]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ path.close();
+ break;
+ case PathIterator.SEG_MOVETO:
+ path.moveTo(seg[0], seg[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ path.quadTo(seg[0], seg[1], seg[2], seg[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ path.cubicTo(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]);
+ break;
+ default:
+ throw new Error();
+ }
+ pi.next();
+ }
+ return path;
+ }
+
+ /**
+ * Converts an AWT based buffered image into an SWT <code>Image</code>. This
+ * will always return an <code>Image</code> that has 24 bit depth regardless
+ * of the type of AWT buffered image that is passed into the method.
+ *
+ * @param awtImage
+ * the {@link java.awt.image.BufferedImage} to be converted to an
+ * <code>Image</code>
+ * @return an <code>Image</code> that represents the same image data as the
+ * AWT <code>BufferedImage</code> type.
+ */
+ public static org.eclipse.swt.graphics.Image toSWT(Device device, BufferedImage awtImage) {
+ // We can force bitdepth to be 24 bit because BufferedImage getRGB
+ // allows us to always
+ // retrieve 24 bit data regardless of source color depth.
+ PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
+ ImageData swtImageData = new ImageData(awtImage.getWidth(), awtImage.getHeight(), 24, palette);
+ // Ensure scansize is aligned on 32 bit.
+ int scansize = (((awtImage.getWidth() * 3) + 3) * 4) / 4;
+ WritableRaster alphaRaster = awtImage.getAlphaRaster();
+ byte[] alphaBytes = new byte[awtImage.getWidth()];
+ for (int y = 0; y < awtImage.getHeight(); y++) {
+ int[] buff = awtImage.getRGB(0, y, awtImage.getWidth(), 1, null, 0, scansize);
+ swtImageData.setPixels(0, y, awtImage.getWidth(), buff, 0);
+ if (alphaRaster != null) {
+ int[] alpha = alphaRaster.getPixels(0, y, awtImage.getWidth(), 1, (int[]) null);
+ for (int i = 0; i < awtImage.getWidth(); i++) {
+ alphaBytes[i] = (byte) alpha[i];
+ }
+ swtImageData.setAlphas(0, y, awtImage.getWidth(), alphaBytes, 0);
+ }
+ }
+ return new org.eclipse.swt.graphics.Image(device, swtImageData);
+ }
+}
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SimpleImageTranscoder.java b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SimpleImageTranscoder.java
new file mode 100644
index 000000000..253bc3f41
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/internal/runtime/lite/svg/SimpleImageTranscoder.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2008 Borland Software 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:
+ * Dmitry Stadnik - initial API and implementation
+ */
+package org.eclipse.gmf.internal.runtime.lite.svg;
+
+import java.awt.image.BufferedImage;
+
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.ImageTranscoder;
+
+public class SimpleImageTranscoder extends ImageTranscoder {
+
+ private BufferedImage bufferedImage;
+
+ public BufferedImage getBufferedImage() {
+ return bufferedImage;
+ }
+
+ public BufferedImage createImage(int w, int h) {
+ return bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public void writeImage(BufferedImage img, TranscoderOutput output) throws TranscoderException {
+ }
+}
diff --git a/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/runtime/lite/svg/SVGFigure.java b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/runtime/lite/svg/SVGFigure.java
new file mode 100644
index 000000000..6b5c7439a
--- /dev/null
+++ b/plugins/org.eclipse.gmf.runtime.lite.svg/src/org/eclipse/gmf/runtime/lite/svg/SVGFigure.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2008 Borland Software 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:
+ * Dmitry Stadnik - initial API and implementation
+ */
+package org.eclipse.gmf.runtime.lite.svg;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
+import org.apache.batik.transcoder.Transcoder;
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.ImageTranscoder;
+import org.apache.batik.util.XMLResourceDescriptor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.gmf.internal.runtime.lite.svg.Activator;
+import org.eclipse.gmf.internal.runtime.lite.svg.ImageTranscoderEx;
+import org.eclipse.gmf.internal.runtime.lite.svg.SVGGraphics2D;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.w3c.dom.Document;
+
+public class SVGFigure extends Figure {
+
+ private String uri;
+ private Document document;
+ private boolean failedToLoadDocument;
+
+ public final String getURI() {
+ return uri;
+ }
+
+ public void setURI(String uri, boolean loadOnDemand) {
+ this.uri = uri;
+ document = null;
+ failedToLoadDocument = false;
+ if (loadOnDemand) {
+ loadDocument();
+ }
+ }
+
+ private void loadDocument() {
+ failedToLoadDocument = true;
+ if (uri == null) {
+ return;
+ }
+ String parser = XMLResourceDescriptor.getXMLParserClassName();
+ SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
+ try {
+ document = factory.createDocument(uri);
+ failedToLoadDocument = false;
+ } catch (IOException e) {
+ Activator.logError("Error loading SVG file", e);
+ }
+ }
+
+ private Document getDocument() {
+ if (failedToLoadDocument) {
+ return null;
+ }
+ if (document == null) {
+ loadDocument();
+ }
+ return document;
+ }
+
+ private void renderDocument(Transcoder transcoder, Document document) {
+ try {
+ transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, new Float(getBounds().width));
+ transcoder.addTranscodingHint(ImageTranscoder.KEY_HEIGHT, new Float(getBounds().height));
+ transcoder.transcode(new TranscoderInput(document), new TranscoderOutput());
+ } catch (TranscoderException e) {
+ Activator.logError("Error rendering SVG image", e);
+ }
+ }
+
+ @Override
+ protected void paintFigure(Graphics graphics) {
+ super.paintFigure(graphics);
+ Document document = getDocument();
+ if (document != null) {
+ try {
+ graphics.pushState();
+ paintDirectly(graphics, document);
+ } catch (RuntimeException e) {
+ Activator.log(IStatus.INFO, "Failed to paint SVG image directly", e);
+ graphics.restoreState();
+ paintUsingAWT(graphics, document);
+ } finally {
+ graphics.popState();
+ }
+ }
+ }
+
+ private void paintDirectly(final Graphics graphics, Document document) {
+ ImageTranscoderEx transcoder = new ImageTranscoderEx() {
+
+ @Override
+ protected Graphics2D createGraphics(int w, int h) {
+ return new SVGGraphics2D(graphics);
+ }
+ };
+ renderDocument(transcoder, document);
+ }
+
+ private void paintUsingAWT(Graphics graphics, Document document) {
+ Image image = null;
+ try {
+ // SimpleImageTranscoder transcoder = new SimpleImageTranscoder();
+ ImageTranscoderEx transcoder = new ImageTranscoderEx();
+ renderDocument(transcoder, document);
+ BufferedImage awtImage = transcoder.getBufferedImage();
+ if (awtImage != null) {
+ image = SVGGraphics2D.toSWT(Display.getCurrent(), awtImage);
+ graphics.drawImage(image, getBounds().x, getBounds().y);
+ }
+ } finally {
+ if (image != null) {
+ image.dispose();
+ }
+ }
+ }
+}

Back to the top