技术开发 频道

标准窗口小部件工具箱的 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

  这个渲染器包含在一个实用程序类中。这个类包含并管理屏外图像技术所需要的 AWT 和 SWT 屏外图像的引用。还要注意:

  字段 swtImageData 和 awtPixels 分别是在像素转移时包含 SWT 图像的像素值的缓冲区和用于包含 AWT 图像的像素值的缓冲区。

  常量 TRANSPARENT_COLOR 包含一个作为 SWT 图像中透明颜色的 RGB 值。因为必须定义作为透明度信道的颜色以绘制背景,所以必须为此保留一个颜色值。在代码中我使用了随机值 0x123456 。所有使用这个颜色值的像素都按透明处理。如果这个值所表示的颜色有可能在绘制操作中用到,可以用另一个值表示透明度。

0
相关文章