blob: 979e2f3f20a7cdfe47cbecd7e5c860a2631acc84 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2010 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
*******************************************************************************/
package org.eclipse.draw2d;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.rap.swt.SWT;
/**
* @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 == null)
SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
FontMetrics metrics = FigureUtilities.getFontMetrics(font);
Dimension strSize = FigureUtilities.getStringExtents(string, font);
// UNSUPPORTED - getAscent() not implemented in RAP
// Image srcImage = new Image(display, strSize.width, metrics.getAscent());
Image srcImage = new Image(display, strSize.width, metrics.getHeight());
// UNSUPPORTED - image constructor not implemented in RAP
// GC gc = new GC(srcImage);
GC gc = new GC(srcImage.getDevice());
gc.setFont(font);
gc.setForeground(foreground);
gc.setBackground(background);
gc.fillRectangle(srcImage.getBounds());
// UNSUPPORTED - getLeading() not implemented in RAP
// gc.drawString(string, 0, 0 - metrics.getLeading());
gc.drawString(string, 0, 0);
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 == null)
SWT.error(SWT.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) {
org.eclipse.swt.graphics.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 != 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;
}
}