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