view 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 source

/*******************************************************************************
 * 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;
}

}