comparison dwtx/draw2d/ImageUtilities.d @ 98:95307ad235d9

Added Draw2d code, still work in progress
author Frank Benoit <benoit@tionex.de>
date Sun, 03 Aug 2008 00:52:14 +0200
parents
children
comparison
equal deleted inserted replaced
96:b492ba44e44d 98:95307ad235d9
1 /*******************************************************************************
2 * Copyright (c) 2003, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.draw2d.ImageUtilities;
14
15 import dwt.dwthelper.utils;
16
17
18 static import dwt.graphics.Rectangle;
19 import dwt.DWT;
20 import dwt.graphics.Color;
21 import dwt.graphics.Font;
22 import dwt.graphics.FontMetrics;
23 import dwt.graphics.GC;
24 import dwt.graphics.Image;
25 import dwt.graphics.ImageData;
26 import dwt.graphics.PaletteData;
27 import dwt.graphics.RGB;
28 import dwt.widgets.Display;
29 import dwtx.draw2d.geometry.Dimension;
30 import dwtx.draw2d.FigureUtilities;
31
32 /**
33 * @author Pratik Shah
34 * @since 3.0
35 */
36 public class ImageUtilities {
37
38 /**
39 * Returns a new Image with the given String rotated left (by 90 degrees). The String
40 * will be rendered using the provided colors and fonts. The client is responsible for
41 * disposing the returned Image. Strings cannot contain newline or tab characters. This
42 * method MUST be invoked from the user-interface (Display) thread.
43 *
44 * @param string the String to be rendered
45 * @param font the font
46 * @param foreground the text's color
47 * @param background the background color
48 * @return an Image which must be disposed
49 */
50 public static Image createRotatedImageOfString(String string, Font font,
51 Color foreground, Color background) {
52 Display display = Display.getCurrent();
53 if (display is null)
54 DWT.error(DWT.ERROR_THREAD_INVALID_ACCESS);
55
56 FontMetrics metrics = FigureUtilities.getFontMetrics(font);
57 Dimension strSize = FigureUtilities.getStringExtents(string, font);
58 Image srcImage = new Image(display, strSize.width, metrics.getAscent());
59 GC gc = new GC(srcImage);
60 gc.setFont(font);
61 gc.setForeground(foreground);
62 gc.setBackground(background);
63 gc.fillRectangle(srcImage.getBounds());
64 gc.drawString(string, 0, 0 - metrics.getLeading());
65 Image result = createRotatedImage(srcImage);
66 gc.dispose();
67 srcImage.dispose();
68 return result;
69 }
70
71 /**
72 * Returns a new Image that is the given Image rotated left by 90 degrees. The client is
73 * responsible for disposing the returned Image. This method MUST be invoked from the
74 * user-interface (Display) thread.
75 *
76 * @param srcImage the Image that is to be rotated left
77 * @return the rotated Image (the client is responsible for disposing it)
78 */
79 public static Image createRotatedImage(Image srcImage) {
80 Display display = Display.getCurrent();
81 if (display is null)
82 DWT.error(DWT.ERROR_THREAD_INVALID_ACCESS);
83
84 ImageData srcData = srcImage.getImageData();
85 ImageData destData;
86 if (srcData.depth < 8)
87 destData = rotatePixelByPixel(srcData);
88 else
89 destData = rotateOptimized(srcData);
90
91 return new Image(display, destData);
92 }
93
94 /**
95 * Creates an ImageData representing the given <code>Image</code> shaded with the given
96 * <code>Color</code>.
97 *
98 * @param fromImage Image that has to be shaded
99 * @param shade The Color to be used for shading
100 * @return A new ImageData that can be used to create an Image.
101 */
102 public static ImageData createShadedImage(Image fromImage, Color shade) {
103 dwt.graphics.Rectangle.Rectangle r = fromImage.getBounds();
104 ImageData data = fromImage.getImageData();
105 PaletteData palette = data.palette;
106 if (!palette.isDirect) {
107 /* Convert the palette entries */
108 RGB [] rgbs = palette.getRGBs();
109 for (int i = 0; i < rgbs.length; i++) {
110 if (data.transparentPixel !is i) {
111 RGB color = rgbs [i];
112 color.red = determineShading(color.red, shade.getRed());
113 color.blue = determineShading(color.blue, shade.getBlue());
114 color.green = determineShading(color.green, shade.getGreen());
115 }
116 }
117 data.palette = new PaletteData(rgbs);
118 } else {
119 /* Convert the pixels. */
120 int[] scanline = new int[r.width];
121 int redMask = palette.redMask;
122 int greenMask = palette.greenMask;
123 int blueMask = palette.blueMask;
124 int redShift = palette.redShift;
125 int greenShift = palette.greenShift;
126 int blueShift = palette.blueShift;
127 for (int y = 0; y < r.height; y++) {
128 data.getPixels(0, y, r.width, scanline, 0);
129 for (int x = 0; x < r.width; x++) {
130 int pixel = scanline[x];
131 int red = pixel & redMask;
132 red = (redShift < 0) ? red >>> -redShift : red << redShift;
133 int green = pixel & greenMask;
134 green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
135 int blue = pixel & blueMask;
136 blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
137 red = determineShading(red, shade.getRed());
138 blue = determineShading(blue, shade.getBlue());
139 green = determineShading(green, shade.getGreen());
140 red = (redShift < 0) ? red << -redShift : red >> redShift;
141 red &= redMask;
142 green = (greenShift < 0) ? green << -greenShift : green >> greenShift;
143 green &= greenMask;
144 blue = (blueShift < 0) ? blue << -blueShift : blue >> blueShift;
145 blue &= blueMask;
146 scanline[x] = red | blue | green;
147 }
148 data.setPixels(0, y, r.width, scanline, 0);
149 }
150 }
151 return data;
152 }
153
154 private static int determineShading(int origColor, int shadeColor) {
155 return (origColor + shadeColor) / 2;
156 }
157
158 private static ImageData rotateOptimized(ImageData srcData) {
159 int bytesPerPixel = Math.max(1, srcData.depth / 8);
160 int destBytesPerLine = ((srcData.height * bytesPerPixel - 1) / srcData.scanlinePad + 1)
161 * srcData.scanlinePad;
162 byte[] newData = new byte[destBytesPerLine * srcData.width];
163 for (int srcY = 0; srcY < srcData.height; srcY++) {
164 for (int srcX = 0; srcX < srcData.width; srcX++) {
165 int destX = srcY;
166 int destY = srcData.width - srcX - 1;
167 int destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel);
168 int srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel);
169 System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel);
170 }
171 }
172 return new ImageData(srcData.height, srcData.width, srcData.depth, srcData.palette,
173 srcData.scanlinePad, newData);
174 }
175
176 private static ImageData rotatePixelByPixel(ImageData srcData) {
177 ImageData destData = new ImageData(srcData.height, srcData.width, srcData.depth,
178 srcData.palette);
179 for (int y = 0; y < srcData.height; y++) {
180 for (int x = 0; x < srcData.width; x++) {
181 destData.setPixel(y, srcData.width - x - 1, srcData.getPixel(x, y));
182 }
183 }
184 return destData;
185 }
186
187 }