Mercurial > projects > dwt-addons
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/ImageUtilities.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2003, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.draw2d.ImageUtilities; + +import dwt.dwthelper.utils; + + +static import dwt.graphics.Rectangle; +import dwt.DWT; +import dwt.graphics.Color; +import dwt.graphics.Font; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.PaletteData; +import dwt.graphics.RGB; +import dwt.widgets.Display; +import dwtx.draw2d.geometry.Dimension; +import dwtx.draw2d.FigureUtilities; + +/** + * @author Pratik Shah + * @since 3.0 + */ +public class ImageUtilities { + +/** + * Returns a new Image with the given String rotated left (by 90 degrees). The String + * will be rendered using the provided colors and fonts. The client is responsible for + * disposing the returned Image. Strings cannot contain newline or tab characters. This + * method MUST be invoked from the user-interface (Display) thread. + * + * @param string the String to be rendered + * @param font the font + * @param foreground the text's color + * @param background the background color + * @return an Image which must be disposed + */ +public static Image createRotatedImageOfString(String string, Font font, + Color foreground, Color background) { + Display display = Display.getCurrent(); + if (display is null) + DWT.error(DWT.ERROR_THREAD_INVALID_ACCESS); + + FontMetrics metrics = FigureUtilities.getFontMetrics(font); + Dimension strSize = FigureUtilities.getStringExtents(string, font); + Image srcImage = new Image(display, strSize.width, metrics.getAscent()); + GC gc = new GC(srcImage); + gc.setFont(font); + gc.setForeground(foreground); + gc.setBackground(background); + gc.fillRectangle(srcImage.getBounds()); + gc.drawString(string, 0, 0 - metrics.getLeading()); + Image result = createRotatedImage(srcImage); + gc.dispose(); + srcImage.dispose(); + return result; +} + +/** + * Returns a new Image that is the given Image rotated left by 90 degrees. The client is + * responsible for disposing the returned Image. This method MUST be invoked from the + * user-interface (Display) thread. + * + * @param srcImage the Image that is to be rotated left + * @return the rotated Image (the client is responsible for disposing it) + */ +public static Image createRotatedImage(Image srcImage) { + Display display = Display.getCurrent(); + if (display is null) + DWT.error(DWT.ERROR_THREAD_INVALID_ACCESS); + + ImageData srcData = srcImage.getImageData(); + ImageData destData; + if (srcData.depth < 8) + destData = rotatePixelByPixel(srcData); + else + destData = rotateOptimized(srcData); + + return new Image(display, destData); +} + +/** + * Creates an ImageData representing the given <code>Image</code> shaded with the given + * <code>Color</code>. + * + * @param fromImage Image that has to be shaded + * @param shade The Color to be used for shading + * @return A new ImageData that can be used to create an Image. + */ +public static ImageData createShadedImage(Image fromImage, Color shade) { + dwt.graphics.Rectangle.Rectangle r = fromImage.getBounds(); + ImageData data = fromImage.getImageData(); + PaletteData palette = data.palette; + if (!palette.isDirect) { + /* Convert the palette entries */ + RGB [] rgbs = palette.getRGBs(); + for (int i = 0; i < rgbs.length; i++) { + if (data.transparentPixel !is i) { + RGB color = rgbs [i]; + color.red = determineShading(color.red, shade.getRed()); + color.blue = determineShading(color.blue, shade.getBlue()); + color.green = determineShading(color.green, shade.getGreen()); + } + } + data.palette = new PaletteData(rgbs); + } else { + /* Convert the pixels. */ + int[] scanline = new int[r.width]; + int redMask = palette.redMask; + int greenMask = palette.greenMask; + int blueMask = palette.blueMask; + int redShift = palette.redShift; + int greenShift = palette.greenShift; + int blueShift = palette.blueShift; + for (int y = 0; y < r.height; y++) { + data.getPixels(0, y, r.width, scanline, 0); + for (int x = 0; x < r.width; x++) { + int pixel = scanline[x]; + int red = pixel & redMask; + red = (redShift < 0) ? red >>> -redShift : red << redShift; + int green = pixel & greenMask; + green = (greenShift < 0) ? green >>> -greenShift : green << greenShift; + int blue = pixel & blueMask; + blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift; + red = determineShading(red, shade.getRed()); + blue = determineShading(blue, shade.getBlue()); + green = determineShading(green, shade.getGreen()); + red = (redShift < 0) ? red << -redShift : red >> redShift; + red &= redMask; + green = (greenShift < 0) ? green << -greenShift : green >> greenShift; + green &= greenMask; + blue = (blueShift < 0) ? blue << -blueShift : blue >> blueShift; + blue &= blueMask; + scanline[x] = red | blue | green; + } + data.setPixels(0, y, r.width, scanline, 0); + } + } + return data; +} + +private static int determineShading(int origColor, int shadeColor) { + return (origColor + shadeColor) / 2; +} + +private static ImageData rotateOptimized(ImageData srcData) { + int bytesPerPixel = Math.max(1, srcData.depth / 8); + int destBytesPerLine = ((srcData.height * bytesPerPixel - 1) / srcData.scanlinePad + 1) + * srcData.scanlinePad; + byte[] newData = new byte[destBytesPerLine * srcData.width]; + for (int srcY = 0; srcY < srcData.height; srcY++) { + for (int srcX = 0; srcX < srcData.width; srcX++) { + int destX = srcY; + int destY = srcData.width - srcX - 1; + int destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel); + int srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel); + System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel); + } + } + return new ImageData(srcData.height, srcData.width, srcData.depth, srcData.palette, + srcData.scanlinePad, newData); +} + +private static ImageData rotatePixelByPixel(ImageData srcData) { + ImageData destData = new ImageData(srcData.height, srcData.width, srcData.depth, + srcData.palette); + for (int y = 0; y < srcData.height; y++) { + for (int x = 0; x < srcData.width; x++) { + destData.setPixel(y, srcData.width - x - 1, srcData.getPixel(x, y)); + } + } + return destData; +} + +}