--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+package org.simantics.g2d.chassis;\r
+\r
+import java.awt.Graphics2D;\r
+import java.awt.image.BufferedImage;\r
+\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.ImageData;\r
+import org.eclipse.swt.graphics.PaletteData;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+/**\r
+ * Helper class allowing the use of Java 2D on SWT or Draw2D graphical\r
+ * context.\r
+ * @author Yannick Saillet\r
+ */\r
+public class Graphics2DRenderer {\r
+ private static final PaletteData PALETTE_DATA =\r
+ new PaletteData(0xFF0000, 0xFF00, 0xFF);\r
+\r
+ private BufferedImage awtImage;\r
+ private Image swtImage;\r
+ private ImageData swtImageData;\r
+ private int[] awtPixels;\r
+\r
+ /** RGB value to use as transparent color */\r
+ private static final int TRANSPARENT_COLOR = 0x123456;\r
+\r
+ /**\r
+ * Prepare to render on a SWT graphics context.\r
+ */\r
+ public void prepareRendering(GC gc) {\r
+ org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();\r
+ prepareRendering(clip.x, clip.y, clip.width, clip.height);\r
+ }\r
+\r
+ /**\r
+ * Prepare the AWT offscreen image for the rendering of the rectangular\r
+ * region given as parameter.\r
+ */\r
+ private void prepareRendering(int clipX, int clipY, int clipW, int clipH) {\r
+ // check that the offscreen images are initialized and large enough\r
+ checkOffScreenImages(clipW, clipH);\r
+ // fill the region in the AWT image with the transparent color\r
+ java.awt.Graphics awtGraphics = awtImage.getGraphics();\r
+ awtGraphics.setColor(new java.awt.Color(TRANSPARENT_COLOR));\r
+ awtGraphics.fillRect(clipX, clipY, clipW, clipH);\r
+ }\r
+\r
+ /**\r
+ * Returns the Graphics2D context to use.\r
+ */\r
+ public Graphics2D getGraphics2D() {\r
+ if (awtImage == null) return null;\r
+ return (Graphics2D) awtImage.getGraphics();\r
+ }\r
+\r
+ /**\r
+ * Complete the rendering by flushing the 2D renderer on a SWT graphical\r
+ * context.\r
+ */\r
+ public void render(GC gc) {\r
+ if (awtImage == null) return;\r
+\r
+ org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();\r
+ transferPixels(clip.x, clip.y, clip.width, clip.height);\r
+ gc.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,\r
+ clip.x, clip.y, clip.width, clip.height);\r
+ }\r
+\r
+ /**\r
+ * Transfer a rectangular region from the AWT image to the SWT image.\r
+ */\r
+ private void transferPixels(int clipX, int clipY, int clipW, int clipH) {\r
+ int step = swtImageData.depth / 8;\r
+ byte[] data = swtImageData.data;\r
+ awtImage.getRGB(clipX, clipY, clipW, clipH, awtPixels, 0, clipW);\r
+ for (int i = 0; i < clipH; i++) {\r
+ int idx = (clipY + i) * swtImageData.bytesPerLine + clipX * step;\r
+ for (int j = 0; j < clipW; j++) {\r
+ int rgb = awtPixels[j + i * clipW];\r
+ for (int k = swtImageData.depth - 8; k >= 0; k -= 8) {\r
+ data[idx++] = (byte) ((rgb >> k) & 0xFF);\r
+ }\r
+ }\r
+ }\r
+ if (swtImage != null) swtImage.dispose();\r
+ swtImage = new Image(Display.getDefault(), swtImageData);\r
+ }\r
+\r
+ /**\r
+ * Dispose the resources attached to this 2D renderer.\r
+ */\r
+ public void dispose() {\r
+ if (awtImage != null) awtImage.flush();\r
+ if (swtImage != null) swtImage.dispose();\r
+ awtImage = null;\r
+ swtImageData = null;\r
+ awtPixels = null;\r
+ }\r
+\r
+ /**\r
+ * Ensure that the offscreen images are initialized and are at least\r
+ * as large as the size given as parameter.\r
+ */\r
+ private void checkOffScreenImages(int width, int height) {\r
+ int currentImageWidth = 0;\r
+ int currentImageHeight = 0;\r
+ if (swtImage != null) {\r
+ currentImageWidth = swtImage.getImageData().width;\r
+ currentImageHeight = swtImage.getImageData().height;\r
+ }\r
+\r
+ // if the offscreen images are too small, recreate them\r
+ if (width > currentImageWidth || height > currentImageHeight) {\r
+ dispose();\r
+ width = Math.max(width, currentImageWidth);\r
+ height = Math.max(height, currentImageHeight);\r
+ awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\r
+ swtImageData = new ImageData(width, height, 24, PALETTE_DATA);\r
+ swtImageData.transparentPixel = TRANSPARENT_COLOR;\r
+ awtPixels = new int[width * height];\r
+ }\r
+ }\r
+}\r