]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/chassis/Graphics2DRenderer.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / chassis / Graphics2DRenderer.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 /*\r
13  *\r
14  * @author Toni Kalajainen\r
15  */\r
16 package org.simantics.g2d.chassis;\r
17 \r
18 import java.awt.Graphics2D;\r
19 import java.awt.image.BufferedImage;\r
20 \r
21 import org.eclipse.swt.graphics.GC;\r
22 import org.eclipse.swt.graphics.Image;\r
23 import org.eclipse.swt.graphics.ImageData;\r
24 import org.eclipse.swt.graphics.PaletteData;\r
25 import org.eclipse.swt.widgets.Display;\r
26 \r
27 /**\r
28  * Helper class allowing the use of Java 2D on SWT or Draw2D graphical\r
29  * context.\r
30  * @author Yannick Saillet\r
31  */\r
32 public class Graphics2DRenderer {\r
33   private static final PaletteData PALETTE_DATA =\r
34     new PaletteData(0xFF0000, 0xFF00, 0xFF);\r
35 \r
36   private BufferedImage awtImage;\r
37   private Image swtImage;\r
38   private ImageData swtImageData;\r
39   private int[] awtPixels;\r
40 \r
41   /** RGB value to use as transparent color */\r
42   private static final int TRANSPARENT_COLOR = 0x123456;\r
43 \r
44   /**\r
45    * Prepare to render on a SWT graphics context.\r
46    */\r
47   public void prepareRendering(GC gc) {\r
48     org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();\r
49     prepareRendering(clip.x, clip.y, clip.width, clip.height);\r
50   }\r
51 \r
52   /**\r
53    * Prepare the AWT offscreen image for the rendering of the rectangular\r
54    * region given as parameter.\r
55    */\r
56   private void prepareRendering(int clipX, int clipY, int clipW, int clipH) {\r
57     // check that the offscreen images are initialized and large enough\r
58     checkOffScreenImages(clipW, clipH);\r
59     // fill the region in the AWT image with the transparent color\r
60     java.awt.Graphics awtGraphics = awtImage.getGraphics();\r
61     awtGraphics.setColor(new java.awt.Color(TRANSPARENT_COLOR));\r
62     awtGraphics.fillRect(clipX, clipY, clipW, clipH);\r
63   }\r
64 \r
65   /**\r
66    * Returns the Graphics2D context to use.\r
67    */\r
68   public Graphics2D getGraphics2D() {\r
69     if (awtImage == null) return null;\r
70     return (Graphics2D) awtImage.getGraphics();\r
71   }\r
72 \r
73   /**\r
74    * Complete the rendering by flushing the 2D renderer on a SWT graphical\r
75    * context.\r
76    */\r
77   public void render(GC gc) {\r
78     if (awtImage == null) return;\r
79 \r
80     org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();\r
81     transferPixels(clip.x, clip.y, clip.width, clip.height);\r
82     gc.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,\r
83                  clip.x, clip.y, clip.width, clip.height);\r
84   }\r
85 \r
86   /**\r
87    * Transfer a rectangular region from the AWT image to the SWT image.\r
88    */\r
89   private void transferPixels(int clipX, int clipY, int clipW, int clipH) {\r
90     int step = swtImageData.depth / 8;\r
91     byte[] data = swtImageData.data;\r
92     awtImage.getRGB(clipX, clipY, clipW, clipH, awtPixels, 0, clipW);\r
93     for (int i = 0; i < clipH; i++) {\r
94       int idx = (clipY + i) * swtImageData.bytesPerLine + clipX * step;\r
95       for (int j = 0; j < clipW; j++) {\r
96         int rgb = awtPixels[j + i * clipW];\r
97         for (int k = swtImageData.depth - 8; k >= 0; k -= 8) {\r
98           data[idx++] = (byte) ((rgb >> k) & 0xFF);\r
99         }\r
100       }\r
101     }\r
102     if (swtImage != null) swtImage.dispose();\r
103     swtImage = new Image(Display.getDefault(), swtImageData);\r
104   }\r
105 \r
106   /**\r
107    * Dispose the resources attached to this 2D renderer.\r
108    */\r
109   public void dispose() {\r
110     if (awtImage != null) awtImage.flush();\r
111     if (swtImage != null) swtImage.dispose();\r
112     awtImage = null;\r
113     swtImageData = null;\r
114     awtPixels = null;\r
115   }\r
116 \r
117   /**\r
118    * Ensure that the offscreen images are initialized and are at least\r
119    * as large as the size given as parameter.\r
120    */\r
121   private void checkOffScreenImages(int width, int height) {\r
122     int currentImageWidth = 0;\r
123     int currentImageHeight = 0;\r
124     if (swtImage != null) {\r
125       currentImageWidth = swtImage.getImageData().width;\r
126       currentImageHeight = swtImage.getImageData().height;\r
127     }\r
128 \r
129     // if the offscreen images are too small, recreate them\r
130     if (width > currentImageWidth || height > currentImageHeight) {\r
131       dispose();\r
132       width = Math.max(width, currentImageWidth);\r
133       height = Math.max(height, currentImageHeight);\r
134       awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\r
135       swtImageData = new ImageData(width, height, 24, PALETTE_DATA);\r
136       swtImageData.transparentPixel = TRANSPARENT_COLOR;\r
137       awtPixels = new int[width * height];\r
138     }\r
139   }\r
140 }\r