标准窗口小部件工具箱的 Java 二维作图
清单 1 显示实现了屏外图像技术的一般性渲染器(renderer)的源代码。这个渲染器可以在 SWT 组件或者 Draw2D 图像上绘制时透明地使用 Java 2D 例程。
清单 1. SWT/Draw2D Java 2D renderer
1 package swtgraphics2d;
2 import java.awt.Graphics2D;
3 import java.awt.image.BufferedImage;
4 import org.eclipse.swt.graphics.GC;
5 import org.eclipse.swt.graphics.Image;
6 import org.eclipse.swt.graphics.ImageData;
7 import org.eclipse.swt.graphics.PaletteData;
8 import org.eclipse.swt.widgets.Display;
9 /**
10 * Helper class allowing the use of Java 2D on SWT or Draw2D graphical
11 * context.
12 * @author Yannick Saillet
13 */
14 public class Graphics2DRenderer {
15 private static final PaletteData PALETTE_DATA =
16 new PaletteData(0xFF0000, 0xFF00, 0xFF);
17 private BufferedImage awtImage;
18 private Image swtImage;
19 private ImageData swtImageData;
20 private int[] awtPixels;
21 /** RGB value to use as transparent color */
22 private static final int TRANSPARENT_COLOR = 0x123456;
23 /**
24 * Prepare to render on a SWT graphics context.
25 */
26 public void prepareRendering(GC gc) {
27 org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
28 prepareRendering(clip.x, clip.y, clip.width, clip.height);
29 }
30 /**
31 * Prepare to render on a Draw2D graphics context.
32 */
33 public void prepareRendering(org.eclipse.draw2d.Graphics graphics) {
34 org.eclipse.draw2d.geometry.Rectangle clip =
35 graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
36 prepareRendering(clip.x, clip.y, clip.width, clip.height);
37 }
38 /**
39 * Prepare the AWT offscreen image for the rendering of the rectangular
40 * region given as parameter.
41 */
42 private void prepareRendering(int clipX, int clipY, int clipW, int clipH) {
43 // check that the offscreen images are initialized and large enough
44 checkOffScreenImages(clipW, clipH);
45 // fill the region in the AWT image with the transparent color
46 java.awt.Graphics awtGraphics = awtImage.getGraphics();
47 awtGraphics.setColor(new java.awt.Color(TRANSPARENT_COLOR));
48 awtGraphics.fillRect(clipX, clipY, clipW, clipH);
49 }
50 /**
51 * Returns the Graphics2D context to use.
52 */
53 public Graphics2D getGraphics2D() {
54 if (awtImage == null) return null;
55 return (Graphics2D) awtImage.getGraphics();
56 }
57 /**
58 * Complete the rendering by flushing the 2D renderer on a SWT graphical
59 * context.
60 */
61 public void render(GC gc) {
62 if (awtImage == null) return;
63 org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
64 transferPixels(clip.x, clip.y, clip.width, clip.height);
65 gc.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,
66 clip.x, clip.y, clip.width, clip.height);
67 }
68 /**
69 * Complete the rendering by flushing the 2D renderer on a Draw2D
70 * graphical context.
71 */
72 public void render(org.eclipse.draw2d.Graphics graphics) {
73 if (awtImage == null) return;
74 org.eclipse.draw2d.geometry.Rectangle clip =
75 graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
76 transferPixels(clip.x, clip.y, clip.width, clip.height);
77 graphics.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,
78 clip.x, clip.y, clip.width, clip.height);
79 }
80 /**
81 * Transfer a rectangular region from the AWT image to the SWT image.
82 */
83 private void transferPixels(int clipX, int clipY, int clipW, int clipH) {
84 int step = swtImageData.depth / 8;
85 byte[] data = swtImageData.data;
86 awtImage.getRGB(clipX, clipY, clipW, clipH, awtPixels, 0, clipW);
87 for (int i = 0; i < clipH; i++) {
88 int idx = (clipY + i) * swtImageData.bytesPerLine + clipX * step;
89 for (int j = 0; j < clipW; j++) {
90 int rgb = awtPixels[j + i * clipW];
91 for (int k = swtImageData.depth - 8; k >= 0; k -= 8) {
92 data[idx++] = (byte) ((rgb >> k) & 0xFF);
93 }
94 }
95 }
96 if (swtImage != null) swtImage.dispose();
97 swtImage = new Image(Display.getDefault(), swtImageData);
98 }
99 /**
100 * Dispose the resources attached to this 2D renderer.
101 */
102 public void dispose() {
103 if (awtImage != null) awtImage.flush();
104 if (swtImage != null) swtImage.dispose();
105 awtImage = null;
106 swtImageData = null;
107 awtPixels = null;
108 }
109 /**
110 * Ensure that the offscreen images are initialized and are at least
111 * as large as the size given as parameter.
112 */
113 private void checkOffScreenImages(int width, int height) {
114 int currentImageWidth = 0;
115 int currentImageHeight = 0;
116 if (swtImage != null) {
117 currentImageWidth = swtImage.getImageData().width;
118 currentImageHeight = swtImage.getImageData().height;
119 }
120 // if the offscreen images are too small, recreate them
121 if (width > currentImageWidth || height > currentImageHeight) {
122 dispose();
123 width = Math.max(width, currentImageWidth);
124 height = Math.max(height, currentImageHeight);
125 awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
126 swtImageData = new ImageData(width, height, 24, PALETTE_DATA);
127 swtImageData.transparentPixel = TRANSPARENT_COLOR;
128 awtPixels = new int[width * height];
129 }
130 }
131 }
132
2 import java.awt.Graphics2D;
3 import java.awt.image.BufferedImage;
4 import org.eclipse.swt.graphics.GC;
5 import org.eclipse.swt.graphics.Image;
6 import org.eclipse.swt.graphics.ImageData;
7 import org.eclipse.swt.graphics.PaletteData;
8 import org.eclipse.swt.widgets.Display;
9 /**
10 * Helper class allowing the use of Java 2D on SWT or Draw2D graphical
11 * context.
12 * @author Yannick Saillet
13 */
14 public class Graphics2DRenderer {
15 private static final PaletteData PALETTE_DATA =
16 new PaletteData(0xFF0000, 0xFF00, 0xFF);
17 private BufferedImage awtImage;
18 private Image swtImage;
19 private ImageData swtImageData;
20 private int[] awtPixels;
21 /** RGB value to use as transparent color */
22 private static final int TRANSPARENT_COLOR = 0x123456;
23 /**
24 * Prepare to render on a SWT graphics context.
25 */
26 public void prepareRendering(GC gc) {
27 org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
28 prepareRendering(clip.x, clip.y, clip.width, clip.height);
29 }
30 /**
31 * Prepare to render on a Draw2D graphics context.
32 */
33 public void prepareRendering(org.eclipse.draw2d.Graphics graphics) {
34 org.eclipse.draw2d.geometry.Rectangle clip =
35 graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
36 prepareRendering(clip.x, clip.y, clip.width, clip.height);
37 }
38 /**
39 * Prepare the AWT offscreen image for the rendering of the rectangular
40 * region given as parameter.
41 */
42 private void prepareRendering(int clipX, int clipY, int clipW, int clipH) {
43 // check that the offscreen images are initialized and large enough
44 checkOffScreenImages(clipW, clipH);
45 // fill the region in the AWT image with the transparent color
46 java.awt.Graphics awtGraphics = awtImage.getGraphics();
47 awtGraphics.setColor(new java.awt.Color(TRANSPARENT_COLOR));
48 awtGraphics.fillRect(clipX, clipY, clipW, clipH);
49 }
50 /**
51 * Returns the Graphics2D context to use.
52 */
53 public Graphics2D getGraphics2D() {
54 if (awtImage == null) return null;
55 return (Graphics2D) awtImage.getGraphics();
56 }
57 /**
58 * Complete the rendering by flushing the 2D renderer on a SWT graphical
59 * context.
60 */
61 public void render(GC gc) {
62 if (awtImage == null) return;
63 org.eclipse.swt.graphics.Rectangle clip = gc.getClipping();
64 transferPixels(clip.x, clip.y, clip.width, clip.height);
65 gc.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,
66 clip.x, clip.y, clip.width, clip.height);
67 }
68 /**
69 * Complete the rendering by flushing the 2D renderer on a Draw2D
70 * graphical context.
71 */
72 public void render(org.eclipse.draw2d.Graphics graphics) {
73 if (awtImage == null) return;
74 org.eclipse.draw2d.geometry.Rectangle clip =
75 graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
76 transferPixels(clip.x, clip.y, clip.width, clip.height);
77 graphics.drawImage(swtImage, clip.x, clip.y, clip.width, clip.height,
78 clip.x, clip.y, clip.width, clip.height);
79 }
80 /**
81 * Transfer a rectangular region from the AWT image to the SWT image.
82 */
83 private void transferPixels(int clipX, int clipY, int clipW, int clipH) {
84 int step = swtImageData.depth / 8;
85 byte[] data = swtImageData.data;
86 awtImage.getRGB(clipX, clipY, clipW, clipH, awtPixels, 0, clipW);
87 for (int i = 0; i < clipH; i++) {
88 int idx = (clipY + i) * swtImageData.bytesPerLine + clipX * step;
89 for (int j = 0; j < clipW; j++) {
90 int rgb = awtPixels[j + i * clipW];
91 for (int k = swtImageData.depth - 8; k >= 0; k -= 8) {
92 data[idx++] = (byte) ((rgb >> k) & 0xFF);
93 }
94 }
95 }
96 if (swtImage != null) swtImage.dispose();
97 swtImage = new Image(Display.getDefault(), swtImageData);
98 }
99 /**
100 * Dispose the resources attached to this 2D renderer.
101 */
102 public void dispose() {
103 if (awtImage != null) awtImage.flush();
104 if (swtImage != null) swtImage.dispose();
105 awtImage = null;
106 swtImageData = null;
107 awtPixels = null;
108 }
109 /**
110 * Ensure that the offscreen images are initialized and are at least
111 * as large as the size given as parameter.
112 */
113 private void checkOffScreenImages(int width, int height) {
114 int currentImageWidth = 0;
115 int currentImageHeight = 0;
116 if (swtImage != null) {
117 currentImageWidth = swtImage.getImageData().width;
118 currentImageHeight = swtImage.getImageData().height;
119 }
120 // if the offscreen images are too small, recreate them
121 if (width > currentImageWidth || height > currentImageHeight) {
122 dispose();
123 width = Math.max(width, currentImageWidth);
124 height = Math.max(height, currentImageHeight);
125 awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
126 swtImageData = new ImageData(width, height, 24, PALETTE_DATA);
127 swtImageData.transparentPixel = TRANSPARENT_COLOR;
128 awtPixels = new int[width * height];
129 }
130 }
131 }
132
这个渲染器包含在一个实用程序类中。这个类包含并管理屏外图像技术所需要的 AWT 和 SWT 屏外图像的引用。还要注意:
字段 swtImageData 和 awtPixels 分别是在像素转移时包含 SWT 图像的像素值的缓冲区和用于包含 AWT 图像的像素值的缓冲区。
常量 TRANSPARENT_COLOR 包含一个作为 SWT 图像中透明颜色的 RGB 值。因为必须定义作为透明度信道的颜色以绘制背景,所以必须为此保留一个颜色值。在代码中我使用了随机值 0x123456 。所有使用这个颜色值的像素都按透明处理。如果这个值所表示的颜色有可能在绘制操作中用到,可以用另一个值表示透明度。
0
相关文章