blob: b8747c68bde682308bdee53d067a35e5ca4b8836 [file] [log] [blame]
package org.eclipse.swt.graphics;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import java.io.*;
import java.util.*;
import org.eclipse.swt.*;
import org.eclipse.swt.internal.image.*;
/**
* Instances of this class are device-independent descriptions
* of images. They are typically used as an intermediate format
* between loading from or writing to streams and creating an
* <code>Image</code>.
* <p>
* Note that the public fields <code>x</code>, <code>y</code>,
* <code>disposalMethod</code> and <code>delayTime</code> are
* typically only used when the image is in a set of images used
* for animation.
*
* @see Image
* @see ImageLoader
*/
public final class ImageData implements Cloneable {
/**
* the width of the image, in pixels
*/
public int width;
/**
* the height of the image, in pixels
*/
public int height;
/**
* the color depth of the image, in bits per pixel
*/
public int depth;
/**
* the scanline padding. If one scanline of the image
* is not a multiple of this number, it will be padded
* with zeros until it is
*/
public int scanlinePad;
/**
* the number of bytes per scanline. This is a multiple
* of the scanline padding
*/
public int bytesPerLine;
/**
* the pixel data of the image
*/
public byte[] data;
/**
* the color table for the image
*/
public PaletteData palette;
/**
* the transparent pixel. Pixels with this value are transparent.
* The default is -1 which means 'no transparency'
*/
public int transparentPixel;
/**
* icon-specific field containing the data from the icon mask
*/
public byte[] maskData;
/**
* icon-specific field containing the scanline pad of the mask
*/
public int maskPad;
/**
* the alpha data of the image. Every pixel can have an
* <em>alpha blending</em> value that varies from 0, meaning
* fully transparent, to 255 meaning fully opaque
*/
public byte[] alphaData;
/**
* the global alpha value to be used for every pixel.
* If this value is set the <code>alphaData</code> field
* is ignored. The default is -1 which means 'no global alpha
* value'
*/
public int alpha;
/**
* the type of file that the image was read in from,
* expressed as one of the following values:
* <dl>
* <dt><code>IMAGE_BMP</code></dt>
* <dd>Windows BMP file format, no compression</dd>
* <dt><code>IMAGE_BMP_RLE</code></dt>
* <dd>Windows BMP file format, RLE compression if appropriate</dd>
* <dt><code>IMAGE_GIF</code></dt>
* <dd>GIF file format</dd>
* <dt><code>IMAGE_ICO</code></dt>
* <dd>Windows ICO file format</dd>
* <dt><code>IMAGE_JPEG</code></dt>
* <dd>JPEG file format</dd>
* <dt><code>IMAGE_PNG</code></dt>
* <dd>PNG file format</dd>
* </dl>
*/
public int type;
/**
* the x coordinate of the top left corner of the image
* within the logical screen (this field corresponds to
* the GIF89a Image Left Position value)
*/
public int x;
/**
* The y coordinate of the top left corner of the image
* within the logical screen (this field corresponds to
* the GIF89a Image Top Position value)
*/
public int y;
/**
* a description of how to dispose of the current image
* before displaying the next, expressed as one of the
* following values:
* <dl>
* <dt><code>DM_UNSPECIFIED</code></dt>
* <dd>disposal method not specified</dd>
* <dt><code>DM_FILL_NONE</code></dt>
* <dd>do nothing - leave the image in place</dd>
* <dt><code>DM_FILL_BACKGROUND</code></dt>
* <dd>fill with the background color</dd>
* <dt><code>DM_FILL_PREVIOUS</code></dt>
* <dd>restore the previous picture</dd>
* </dl>
* (this field corresponds to the GIF89a Disposal Method value)
*/
public int disposalMethod;
/**
* the time to delay before displaying the next image
* in an animation (this field corresponds to the GIF89a
* Delay Time value)
*/
public int delayTime;
/**
* Constructs a new, empty ImageData with the given width, height,
* depth and palette. The data will be initialized to an (all zero)
* array of the appropriate size.
*
* @param width the width of the image
* @param height the height of the image
* @param depth the depth of the image
* @param palette the palette of the image (must not be null)
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the width or height is negative</li>
* <li>ERROR_NULL_ARGUMENT - if the palette is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH - if the depth argument is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public ImageData(int width, int height, int depth, PaletteData palette) {
this(width, height, depth, palette,
4, null, 0, null,
null, -1, -1, SWT.IMAGE_UNDEFINED,
0, 0, 0, 0);
}
/**
* Constructs a new, empty ImageData with the given width, height,
* depth, palette, scanlinePad and data.
*
* @param width the width of the image
* @param height the height of the image
* @param depth the depth of the image
* @param palette the palette of the image
* @param scanlinePad the padding of each line, in bytes
* @param data the data of the image
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the width or height is negative</li>
* <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH - if the depth argument is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public ImageData(int width, int height, int depth, PaletteData palette, int scanlinePad, byte[] data) {
this(width, height, depth, palette,
scanlinePad, checkData(data), 0, null,
null, -1, -1, SWT.IMAGE_UNDEFINED,
0, 0, 0, 0);
}
/**
* Constructs an <code>ImageData</code> loaded from the specified
* input stream. Throws an error if an error occurs while loading
* the image, or if the image has an unsupported type.
* <p>
* This constructor is provided for convenience when loading a single
* image only. If the stream contains multiple images, only the first
* one will be loaded. To load multiple images, use
* <code>ImageLoader.load()</code>.
* </p>
*
* @param stream the input stream to load the image from (must not be null)
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
* <li>ERROR_IO - if an IO error occurs while reading data</li>
* </ul>
*
* @see ImageLoader#load
*/
public ImageData(InputStream stream) {
ImageData[] data = new ImageLoader().load(stream);
if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
ImageData i = data[0];
setAllFields(
i.width,
i.height,
i.depth,
i.scanlinePad,
i.bytesPerLine,
i.data,
i.palette,
i.transparentPixel,
i.maskData,
i.maskPad,
i.alphaData,
i.alpha,
i.type,
i.x,
i.y,
i.disposalMethod,
i.delayTime);
}
/**
* Constructs an <code>ImageData</code> loaded from a file with the
* specified name. Throws an error if an error occurs loading the
* image, or if the image has an unsupported type.
* <p>
* This constructor is provided for convenience when loading a single
* image only. If the file contains multiple images, only the first
* one will be loaded. To load multiple images, use
* <code>ImageLoader.load()</code>.
* </p>
*
* @param filename the name of the file to load the image from (must not be null)
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
* <li>ERROR_IO if an IO error occurs while reading data</li>
* </ul>
*/
public ImageData(String filename) {
ImageData[] data = new ImageLoader().load(filename);
if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
ImageData i = data[0];
setAllFields(
i.width,
i.height,
i.depth,
i.scanlinePad,
i.bytesPerLine,
i.data,
i.palette,
i.transparentPixel,
i.maskData,
i.maskPad,
i.alphaData,
i.alpha,
i.type,
i.x,
i.y,
i.disposalMethod,
i.delayTime);
}
/**
* Prevents uninitialized instances from being created outside the package.
*/
ImageData() {
}
/**
* Constructs an image data by giving values for all non-computable fields.
* <p>
* This method is for internal use, and is not described further.
* </p>
*/
ImageData(
int width, int height, int depth, PaletteData palette,
int scanlinePad, byte[] data, int maskPad, byte[] maskData,
byte[] alphaData, int alpha, int transparentPixel, int type,
int x, int y, int disposalMethod, int delayTime)
{
if (palette == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (!(depth == 1 || depth == 2 || depth == 4 || depth == 8
|| depth == 16 || depth == 24 || depth == 32)) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (width <= 0 || height <= 0) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
/ scanlinePad * scanlinePad;
setAllFields(
width,
height,
depth,
scanlinePad,
bytesPerLine,
data != null ? data : new byte[bytesPerLine * height],
palette,
transparentPixel,
maskData,
maskPad,
alphaData,
alpha,
type,
x,
y,
disposalMethod,
delayTime);
}
/**
* Initializes all fields in the receiver. This method must be called
* by all public constructors to ensure that all fields are initialized
* for a new ImageData object. If a new field is added to the class,
* then it must be added to this method.
* <p>
* This method is for internal use, and is not described further.
* </p>
*/
void setAllFields(int width, int height, int depth, int scanlinePad,
int bytesPerLine, byte[] data, PaletteData palette, int transparentPixel,
byte[] maskData, int maskPad, byte[] alphaData, int alpha,
int type, int x, int y, int disposalMethod, int delayTime) {
this.width = width;
this.height = height;
this.depth = depth;
this.scanlinePad = scanlinePad;
this.bytesPerLine = bytesPerLine;
this.data = data;
this.palette = palette;
this.transparentPixel = transparentPixel;
this.maskData = maskData;
this.maskPad = maskPad;
this.alphaData = alphaData;
this.alpha = alpha;
this.type = type;
this.x = x;
this.y = y;
this.disposalMethod = disposalMethod;
this.delayTime = delayTime;
}
/**
* Invokes internal SWT functionality to create a new instance of
* this class.
* <p>
* <b>IMPORTANT:</b> This method is <em>not</em> part of the public
* API for <code>ImageData</code>. It is marked public only so that it
* can be shared within the packages provided by SWT. It is subject
* to change without notice, and should never be called from
* application code.
* </p>
* <p>
* This method is for internal use, and is not described further.
* </p>
*
* @private
*/
public static ImageData internal_new(
int width, int height, int depth, PaletteData palette,
int scanlinePad, byte[] data, int maskPad, byte[] maskData,
byte[] alphaData, int alpha, int transparentPixel, int type,
int x, int y, int disposalMethod, int delayTime)
{
return new ImageData(
width, height, depth, palette, scanlinePad, data, maskPad, maskData,
alphaData, alpha, transparentPixel, type, x, y, disposalMethod, delayTime);
}
ImageData colorMaskImage(int pixel) {
ImageData mask = new ImageData(width, height, 1, bwPalette(),
Image.DEFAULT_SCANLINE_PAD, null, 0, null,
null, -1, -1, SWT.IMAGE_UNDEFINED,
0, 0, 0, 0);
int[] row = new int[width];
for (int y = 0; y < height; y++) {
getPixels(0, y, width, row, 0);
for (int i = 0; i < width; i++) {
if (pixel != -1 && row[i] == pixel) {
row[i] = 0;
} else {
row[i] = 1;
}
}
mask.setPixels(0, y, width, row, 0);
}
return mask;
}
static byte[] checkData(byte [] data) {
if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
return data;
}
/**
* Returns a new instance of the same class as the receiver,
* whose slots have been filled in with <em>copies</em> of
* the values in the slots of the receiver. That is, the
* returned object is a <em>deep copy</em> of the receiver.
*
* @return a copy of the receiver.
*/
public Object clone() {
byte[] cloneData = new byte[data.length];
System.arraycopy(data, 0, cloneData, 0, data.length);
byte[] cloneMaskData = null;
if (maskData != null) {
cloneMaskData = new byte[maskData.length];
System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length);
}
byte[] cloneAlphaData = null;
if (alphaData != null) {
cloneAlphaData = new byte[alphaData.length];
System.arraycopy(alphaData, 0, cloneAlphaData, 0, alphaData.length);
}
return new ImageData(
width,
height,
depth,
palette,
scanlinePad,
cloneData,
maskPad,
cloneMaskData,
cloneAlphaData,
alpha,
transparentPixel,
type,
x,
y,
disposalMethod,
delayTime);
}
/**
* Returns the alpha value at offset <code>x</code> in
* scanline <code>y</code> in the receiver's alpha data.
*
* @param x the x coodinate of the pixel to get the alpha value of
* @param y the y coordinate of the pixel to get the alpha value of
* @return the alpha value at the given coordinates
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if either argument is out of range</li>
* </ul>
*/
public int getAlpha(int x, int y) {
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (alphaData == null) return 255;
return alphaData[y * width + x] & 0xFF;
}
/**
* Returns <code>getWidth</code> alpha values starting at offset
* <code>x</code> in scanline <code>y</code> in the receiver's alpha
* data starting at <code>startIndex</code>.
*
* @param x the x position of the pixel to begin getting alpha values
* @param y the y position of the pixel to begin getting alpha values
* @param getWidth the width of the data to get
* @param alphas the buffer in which to put the alpha values
* @param startIndex the offset into the image to begin getting alpha values
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if <code>x</code> or <code>y</code> is out of bounds</li>
* </ul>
*/
public void getAlphas(int x, int y, int getWidth, byte[] alphas, int startIndex) {
if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (getWidth <= 0) return;
if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (alphaData == null) {
int endIndex = startIndex + getWidth;
for (int i = startIndex; i < endIndex; i++) {
alphas[i] = (byte)255;
}
return;
}
System.arraycopy(alphaData, y * width + x, alphas, startIndex, getWidth);
}
/**
* Returns the pixel value at offset <code>x</code> in
* scanline <code>y</code> in the receiver's data.
*
* @param x the x position of the pixel to get
* @param y the y position of the pixel to get
* @return the pixel at the given coordinates
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if either argument is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public int getPixel(int x, int y) {
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
int theByte;
int mask;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
theByte = data[index] & 0xFF;
mask = 1 << (7 - (x & 0x7));
if ((theByte & mask) == 0) {
return 0;
} else {
return 1;
}
}
if (depth == 2) {
index = (y * bytesPerLine) + (x >> 2);
theByte = data[index] & 0xFF;
int offset = 3 - (x % 4);
mask = 3 << (offset * 2);
return (theByte & mask) >> (offset * 2);
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
theByte = data[index] & 0xFF;
if ((x & 0x1) == 0) {
return theByte >> 4;
} else {
return theByte & 0x0F;
}
}
if (depth == 8) {
index = (y * bytesPerLine) + x ;
return data[index] & 0xFF;
}
if (depth == 16) {
index = (y * bytesPerLine) + (x * 2);
return ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
}
if (depth == 24) {
index = (y * bytesPerLine) + (x * 3);
return ((data[index] & 0xFF) << 16) + ((data[index+1] & 0xFF) << 8) +
(data[index+2] & 0xFF);
}
if (depth == 32) {
index = (y * bytesPerLine) + (x * 4);
return ((data[index] & 0xFF) << 24) + ((data[index+1] & 0xFF) << 16) +
((data[index+2] & 0xFF) << 8) + (data[index+3] & 0xFF);
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
return 0;
}
/**
* Returns <code>getWidth</code> pixel values starting at offset
* <code>x</code> in scanline <code>y</code> in the receiver's
* data starting at <code>startIndex</code>.
*
* @param x the x position of the first pixel to get
* @param y the y position of the first pixel to get
* @param getWidth the width of the data to get
* @param pixels the buffer in which to put the pixels
* @param startIndex the offset into the byte array to begin storing pixels
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4 or 8
* (For higher depths, use the int[] version of this method.)</li>
* </ul>
*/
public void getPixels(int x, int y, int getWidth, byte[] pixels, int startIndex) {
if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (getWidth <= 0) return;
if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
int theByte;
int mask = 0;
int n = getWidth;
int i = startIndex;
int srcX = x, srcY = y;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
theByte = data[index] & 0xFF;
while (n > 1) {
mask = 1 << (7 - (srcX & 0x7));
if ((theByte & mask) == 0) {
pixels[i] = 0;
} else {
pixels[i] = 1;
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
if (n > 0) theByte = data[index] & 0xFF;
srcX = 0;
} else {
if (mask == 1) {
index++;
if (n > 0) theByte = data[index] & 0xFF;
}
}
}
return;
}
if (depth == 2) {
index = (y * bytesPerLine) + (x >> 2);
theByte = data[index] & 0xFF;
int offset;
while (n > 0) {
offset = 3 - (srcX % 4);
mask = 3 << (offset * 2);
pixels[i] = (byte)((theByte & mask) >> (offset * 2));
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
if (n > 0) theByte = data[index] & 0xFF;
srcX = 0;
} else {
if (offset == 0) {
index++;
theByte = data[index] & 0xFF;
}
}
}
return;
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
if ((x & 0x1) == 1) {
theByte = data[index] & 0xFF;
pixels[i] = (byte)(theByte & 0x0F);
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
while (n > 1) {
theByte = data[index] & 0xFF;
pixels[i] = (byte)(theByte >> 4);
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
pixels[i] = (byte)(theByte & 0x0F);
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
}
if (n > 0) {
theByte = data[index] & 0xFF;
pixels[i] = (byte)(theByte >> 4);
}
return;
}
if (depth == 8) {
index = (y * bytesPerLine) + x;
for (int j = 0; j < getWidth; j++) {
pixels[i] = data[index];
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
return;
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
/**
* Returns <code>getWidth</code> pixel values starting at offset
* <code>x</code> in scanline <code>y</code> in the receiver's
* data starting at <code>startIndex</code>.
*
* @param x the x position of the first pixel to get
* @param y the y position of the first pixel to get
* @param getWidth the width of the data to get
* @param pixels the buffer in which to put the pixels
* @param startIndex the offset into the buffer to begin storing pixels
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public void getPixels(int x, int y, int getWidth, int[] pixels, int startIndex) {
if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (getWidth <= 0) return;
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
int theByte;
int mask;
int n = getWidth;
int i = startIndex;
int srcX = x, srcY = y;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
theByte = data[index] & 0xFF;
while (n > 0) {
mask = 1 << (7 - (srcX & 0x7));
if ((theByte & mask) == 0) {
pixels[i] = 0;
} else {
pixels[i] = 1;
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
if (n > 0) theByte = data[index] & 0xFF;
srcX = 0;
} else {
if (mask == 1) {
index++;
if (n > 0) theByte = data[index] & 0xFF;
}
}
}
return;
}
if (depth == 2) {
index = (y * bytesPerLine) + (x >> 2);
theByte = data[index] & 0xFF;
int offset;
while (n > 0) {
offset = 3 - (srcX % 4);
mask = 3 << (offset * 2);
pixels[i] = (byte)((theByte & mask) >> (offset * 2));
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
if (n > 0) theByte = data[index] & 0xFF;
srcX = 0;
} else {
if (offset == 0) {
index++;
theByte = data[index] & 0xFF;
}
}
}
return;
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
if ((x & 0x1) == 1) {
theByte = data[index] & 0xFF;
pixels[i] = theByte & 0x0F;
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
while (n > 1) {
theByte = data[index] & 0xFF;
pixels[i] = theByte >> 4;
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
pixels[i] = theByte & 0x0F;
i++;
n--;
srcX++;;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
}
if (n > 0) {
theByte = data[index] & 0xFF;
pixels[i] = theByte >> 4;
}
return;
}
if (depth == 8) {
index = (y * bytesPerLine) + x;
for (int j = 0; j < getWidth; j++) {
pixels[i] = data[index] & 0xFF;
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
return;
}
if (depth == 16) {
index = (y * bytesPerLine) + (x * 2);
for (int j = 0; j < getWidth; j++) {
pixels[i] = ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 2;
}
}
return;
}
if (depth == 24) {
index = (y * bytesPerLine) + (x * 3);
for (int j = 0; j < getWidth; j++) {
pixels[i] = ((data[index] & 0xFF) << 16) | ((data[index+1] & 0xFF) << 8)
| (data[index+2] & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 3;
}
}
return;
}
if (depth == 32) {
index = (y * bytesPerLine) + (x * 4);
i = startIndex;
for (int j = 0; j < getWidth; j++) {
pixels[i] = ((data[index] & 0xFF) << 24) | ((data[index+1] & 0xFF) << 16)
| ((data[index+2] & 0xFF) << 8) | (data[index+3] & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 4;
}
}
return;
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
/**
* Returns an array of <code>RGB</code>s which comprise the
* indexed color table of the receiver, or null if the receiver
* has a direct color model.
*
* @return the RGB values for the image or null if direct color
*
* @see PaletteData#getRGBs
*/
public RGB[] getRGBs() {
return palette.getRGBs();
}
/**
* Returns an <code>ImageData</code> which specifies the
* transparency mask information for the receiver, or null if the
* receiver has no transparency and is not an icon.
*
* @return the transparency mask or null if none exists
*/
public ImageData getTransparencyMask() {
if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
} else {
return colorMaskImage(transparentPixel);
}
}
/**
* Returns the image transparency type.
*
* @return the receiver's transparency type
*/
public int getTransparencyType() {
if (maskData != null) return SWT.TRANSPARENCY_MASK;
if (transparentPixel != -1) return SWT.TRANSPARENCY_PIXEL;
if (alphaData != null) return SWT.TRANSPARENCY_ALPHA;
return SWT.TRANSPARENCY_NONE;
}
/**
* Returns a copy of the receiver which has been stretched or
* shrunk to the specified size. If either the width or height
* is negative, the resulting image will be inverted in the
* associated axis.
*
* @param width the width of the new ImageData
* @param height the height of the new ImageData
* @return a scaled copy of the image
*/
public ImageData scaledTo(int width, int height) {
/* Create a destination image with no data,
* and then scale all of the data. */
ImageData destImage = new ImageData(
width, height, depth, palette,
scanlinePad, null, 0, null,
null, -1, transparentPixel, type,
x, y, disposalMethod, delayTime);
scaleImage(destImage, 0, 0, this.width, this.height, 0, 0, width, height);
return destImage;
}
void scaleImage(ImageData destImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
boolean flipX, flipY;
/* Flip rects if necessary so that src width and height are positive. */
if (srcWidth < 0) {
srcWidth = -srcWidth;
srcX = srcX - srcWidth;
destWidth = -destWidth;
destX = destX - destWidth;
}
if (srcHeight < 0) {
srcHeight = -srcHeight;
srcY = srcY - srcHeight;
destHeight = -destHeight;
destY = destY - destHeight;
}
/* Ensure dest width and height are positive, remembering whether to flip. */
flipX = destWidth < 0;
if (flipX) {
destWidth = -destWidth;
destX = destX - destWidth;
}
flipY = destHeight < 0;
if (flipY) {
destHeight = -destHeight;
destY = destY - destHeight;
}
/* Check source rect bounds. Succeed with 0 if out of bounds, rather
* than failing.
*/
if (srcX < 0 || srcY < 0 || (srcX + srcWidth > width) ||
(srcY + srcHeight > height)) {
return;
}
if (destX < 0 || destY < 0 || (destX + destWidth > destImage.width) ||
(destY + destHeight > destImage.height)) {
return;
}
/* If dest rect is 0, there is nothing to do. */
if (destWidth == 0 || destHeight == 0) {
return;
}
switch (depth) {
case 1:
stretch1(data, bytesPerLine, MSB_FIRST, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, MSB_FIRST, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 2:
stretch2(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
break;
case 4:
stretch4(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
break;
case 8:
stretch8(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
break;
case 16:
stretch16(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 24:
stretch24(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 32:
stretch32(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
break;
default:
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
destImage.maskPad = maskPad;
int destBpl = (destWidth + 7) / 8;
destBpl = (destBpl + (maskPad - 1)) / maskPad * maskPad;
destImage.maskData = new byte[destBpl * destHeight];
int srcBpl = (srcWidth + 7) / 8;
srcBpl = (srcBpl + (maskPad - 1)) / maskPad * maskPad;
stretch1(maskData, srcBpl, MSB_FIRST, srcX, srcY, srcWidth, srcHeight, destImage.maskData, destBpl, MSB_FIRST, destX, destY, destWidth, destHeight, flipX, flipY);
} else if (alpha != -1) {
destImage.alpha = alpha;
} else if (alphaData != null) {
destImage.alphaData = new byte[destImage.width * destImage.height];
stretch8(alphaData, width, srcX, srcY, srcWidth, srcHeight, destImage.alphaData, destImage.width, destX, destY, destWidth, destHeight, null, flipX, flipY);
}
}
/**
* Sets the alpha value at offset <code>x</code> in
* scanline <code>y</code> in the receiver's alpha data.
*
* @param x the x coordinate of the alpha value to set
* @param y the y coordinate of the alpha value to set
* @param alpha the value to set the alpha to
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
*/
public void setAlpha(int x, int y, int alpha) {
if (x > width || y > height || x < 0 || y < 0 || alpha < 0 || alpha > 255)
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (alphaData == null) alphaData = new byte[width * height];
alphaData[y * width + x] = (byte)alpha;
}
/**
* Sets the alpha values starting at offset <code>x</code> in
* scanline <code>y</code> in the receiver's alpha data to the
* values from the array <code>alphas</code> starting at
* <code>startIndex</code>.
*
* @param x the x coordinate of the pixel to being setting the alpha values
* @param y the y coordinate of the pixel to being setting the alpha values
* @param putWidth the width of the alpha values to set
* @param alphas the alpha values to set
* @param startIndex the index at which to begin setting
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
*/
public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) {
if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (putWidth <= 0) return;
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (alphaData == null) alphaData = new byte[width * height];
System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth);
}
/**
* Sets the pixel value at offset <code>x</code> in
* scanline <code>y</code> in the receiver's data.
*
* @param x the x coordinate of the pixel to set
* @param y the y coordinate of the pixel to set
* @param pixelValue the value to set the pixel to
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public void setPixel(int x, int y, int pixelValue) {
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
byte theByte;
int mask;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
theByte = data[index];
mask = 1 << (7 - (x & 0x7));
if ((pixelValue & 0x1) == 1) {
data[index] = (byte)(theByte | mask);
} else {
data[index] = (byte)(theByte & (mask ^ -1));
}
return;
}
if (depth == 2) {
index = (y * bytesPerLine) + (x >> 2);
theByte = data[index];
int offset = 3 - (x % 4);
mask = 0xFF ^ (3 << (offset * 2));
data[index] = (byte)((data[index] & mask) | (pixelValue << (offset * 2)));
return;
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
if ((x & 0x1) == 0) {
data[index] = (byte)((data[index] & 0x0F) | ((pixelValue & 0x0F) << 4));
} else {
data[index] = (byte)((data[index] & 0xF0) | (pixelValue & 0x0F));
}
return;
}
if (depth == 8) {
index = (y * bytesPerLine) + x ;
data[index] = (byte)(pixelValue & 0xFF);
return;
}
if (depth == 16) {
index = (y * bytesPerLine) + (x * 2);
data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
data[index] = (byte)(pixelValue & 0xFF);
return;
}
if (depth == 24) {
index = (y * bytesPerLine) + (x * 3);
data[index] = (byte)((pixelValue >> 16) & 0xFF);
data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
data[index + 2] = (byte)(pixelValue & 0xFF);
return;
}
if (depth == 32) {
index = (y * bytesPerLine) + (x * 4);
data[index] = (byte)((pixelValue >> 24) & 0xFF);
data[index + 1] = (byte)((pixelValue >> 16) & 0xFF);
data[index + 2] = (byte)((pixelValue >> 8) & 0xFF);
data[index + 3] = (byte)(pixelValue & 0xFF);
return;
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
/**
* Sets the pixel values starting at offset <code>x</code> in
* scanline <code>y</code> in the receiver's data to the
* values from the array <code>pixels</code> starting at
* <code>startIndex</code>.
*
* @param x the x position of the pixel to set
* @param y the y position of the pixel to set
* @param putWidth the width of the pixels to set
* @param pixels the pixels to set
* @param startIndex the index at which to begin setting
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8
* (For higher depths, use the int[] version of this method.)</li>
* </ul>
*/
public void setPixels(int x, int y, int putWidth, byte[] pixels, int startIndex) {
if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (putWidth <= 0) return;
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
int theByte;
int mask;
int n = putWidth;
int i = startIndex;
int pixel;
int srcX = x, srcY = y;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
while (n > 0) {
mask = 1 << (7 - (srcX & 0x7));
if ((pixels[i] & 0x1) == 1) {
data[index] = (byte)((data[index] & 0xFF) | mask);
} else {
data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
if (mask == 1) {
index++;
}
}
}
return;
}
if (depth == 2) {
byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
index = (y * bytesPerLine) + (x >> 2);
int offset = 3 - (x % 4);
while (n > 0) {
theByte = pixels[i] & 0x3;
data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
offset = 0;
srcX = 0;
} else {
if (offset == 0) {
index++;
offset = 3;
} else {
offset--;
}
}
}
return;
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
boolean high = (x & 0x1) == 0;
while (n > 0) {
theByte = pixels[i] & 0x0F;
if (high) {
data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
} else {
data[index] = (byte)((data[index] & 0xF0) | theByte);
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
high = true;
srcX = 0;
} else {
if (!high) index++;
high = !high;
}
}
return;
}
if (depth == 8) {
index = (y * bytesPerLine) + x;
for (int j = 0; j < putWidth; j++) {
data[index] = (byte)(pixels[i] & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
return;
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
/**
* Sets the pixel values starting at offset <code>x</code> in
* scanline <code>y</code> in the receiver's data to the
* values from the array <code>pixels</code> starting at
* <code>startIndex</code>.
*
* @param x the x position of the pixel to set
* @param y the y position of the pixel to set
* @param putWidth the width of the pixels to set
* @param pixels the pixels to set
* @param startIndex the index at which to begin setting
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
* <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
* </ul>
*/
public void setPixels(int x, int y, int putWidth, int[] pixels, int startIndex) {
if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (putWidth <= 0) return;
if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
int index;
int theByte;
int mask;
int n = putWidth;
int i = startIndex;
int pixel;
int srcX = x, srcY = y;
if (depth == 1) {
index = (y * bytesPerLine) + (x >> 3);
while (n > 0) {
mask = 1 << (7 - (srcX & 0x7));
if ((pixels[i] & 0x1) == 1) {
data[index] = (byte)((data[index] & 0xFF) | mask);
} else {
data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
if (mask == 1) {
index++;
}
}
}
return;
}
if (depth == 2) {
byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
index = (y * bytesPerLine) + (x >> 2);
int offset = 3 - (x % 4);
while (n > 0) {
theByte = pixels[i] & 0x3;
data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
offset = 3;
srcX = 0;
} else {
if (offset == 0) {
index++;
offset = 3;
} else {
offset--;
}
}
}
return;
}
if (depth == 4) {
index = (y * bytesPerLine) + (x >> 1);
boolean high = (x & 0x1) == 0;
while (n > 0) {
theByte = pixels[i] & 0x0F;
if (high) {
data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
} else {
data[index] = (byte)((data[index] & 0xF0) | theByte);
}
i++;
n--;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
high = true;
srcX = 0;
} else {
if (!high) index++;
high = !high;
}
}
return;
}
if (depth == 8) {
index = (y * bytesPerLine) + x;
for (int j = 0; j < putWidth; j++) {
data[index] = (byte)(pixels[i] & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index++;
}
}
return;
}
if (depth == 16) {
index = (y * bytesPerLine) + (x * 2);
for (int j = 0; j < putWidth; j++) {
pixel = pixels[i];
data[index] = (byte)(pixel & 0xFF);
data[index + 1] = (byte)((pixel >> 8) & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 2;
}
}
return;
}
if (depth == 24) {
index = (y * bytesPerLine) + (x * 3);
for (int j = 0; j < putWidth; j++) {
pixel = pixels[i];
data[index] = (byte)((pixel >> 16) & 0xFF);
data[index + 1] = (byte)((pixel >> 8) & 0xFF);
data[index + 2] = (byte)(pixel & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 3;
}
}
return;
}
if (depth == 32) {
index = (y * bytesPerLine) + (x * 4);
for (int j = 0; j < putWidth; j++) {
pixel = pixels[i];
data[index] = (byte)((pixel >> 24) & 0xFF);
data[index + 1] = (byte)((pixel >> 16) & 0xFF);
data[index + 2] = (byte)((pixel >> 8) & 0xFF);
data[index + 3] = (byte)(pixel & 0xFF);
i++;
srcX++;
if (srcX >= width) {
srcY++;
index = srcY * bytesPerLine;
srcX = 0;
} else {
index += 4;
}
}
return;
}
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
/**
* Returns a palette with 2 colors: black & white.
*/
static PaletteData bwPalette() {
return new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255, 255, 255)});
}
/**
* Blit operations.
*/
static final int BLIT_SRC = 1;
static final int BLIT_ALPHA = 2;
/**
* Byte and bit order constants.
*/
static final int MSB_FIRST = 1;
static final int LSB_FIRST = 2;
/**
* Masks for blitting.
*/
static final byte[] msbMasks1 = {
(byte)0x80, (byte)0x40, (byte)0x20, (byte)0x10,
(byte)0x08, (byte)0x04, (byte)0x02, (byte)0x01
};
static final byte[] lsbMasks1 = {
(byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,
(byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80
};
static final byte[] msbInverseMasks1 = {
(byte)0x7F, (byte)0xBF, (byte)0xDF, (byte)0xEF,
(byte)0xF7, (byte)0xFB, (byte)0xFD, (byte)0xFE
};
static final byte[] lsbInverseMasks1 = {
(byte)0xFE, (byte)0xFD, (byte)0xFB, (byte)0xF7,
(byte)0xEF, (byte)0xDF, (byte)0xBF, (byte)0x7F
};
static final byte[] masks2 = {
(byte)0x03, (byte)0x0C, (byte)0x30, (byte)0xC0
};
static final byte[] inverseMasks2 = {
(byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F
};
/**
* Gets the offset of the most significant bit for
* the given mask.
*/
static int getMSBOffset(int mask) {
for (int i = 31; i >= 0; i--) {
if (((mask >> i) & 0x1) != 0) return i + 1;
}
return 0;
}
/**
* Finds the closest match.
*/
static int closestMatch(int depth, byte red, byte green, byte blue, int redMask, int greenMask, int blueMask, byte[] reds, byte[] greens, byte[] blues) {
if (depth > 8) {
int rshift = 32 - getMSBOffset(redMask);
int gshift = 32 - getMSBOffset(greenMask);
int bshift = 32 - getMSBOffset(blueMask);
return (((red << 24) >>> rshift) & redMask) |
(((green << 24) >>> gshift) & greenMask) |
(((blue << 24) >>> bshift) & blueMask);
}
int r, g, b;
int minDistance = 0x7fffffff;
int nearestPixel = 0;
int n = reds.length;
for (int j = 0; j < n; j++) {
r = (reds[j] & 0xFF) - (red & 0xFF);
g = (greens[j] & 0xFF) - (green & 0xFF);
b = (blues[j] & 0xFF) - (blue & 0xFF);
int distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
return nearestPixel;
}
/**
* Blits a direct palette image into a direct palette image.
*/
static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, int srcRedMask, int srcGreenMask, int srcBlueMask, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, int destRedMask, int destGreenMask, int destBlueMask, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2;
short sxd, sxs, sas;
int sp, dp, sap = 0;
int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
int srcPixel = 0, destPixel = 0;
short so0 = 0, so1 = 1, so2 = 2, so3 = 3;
short do0 = 0, do1 = 1, do2 = 2, do3 = 3;
int srcRedShift, srcGreenShift, srcBlueShift;
int destRedShift, destGreenShift, destBlueShift;
if (op == BLIT_SRC && srcDepth == destDepth &&
srcRedMask == destRedMask &&
srcGreenMask == destGreenMask &&
srcBlueMask == destBlueMask)
{
switch (srcDepth) {
case 16:
stretch16(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 24:
stretch24(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 32:
stretch32(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
break;
}
return;
}
srcRedShift = 32 - getMSBOffset(srcRedMask);
srcGreenShift = 32 - getMSBOffset(srcGreenMask);
srcBlueShift = 32 - getMSBOffset(srcBlueMask);
destRedShift = 32 - getMSBOffset(destRedMask);
destGreenShift = 32 - getMSBOffset(destGreenMask);
destBlueShift = 32 - getMSBOffset(destBlueMask);
if (srcOrder == LSB_FIRST) {
switch (srcDepth) {
case 16: so0 = 1; so1 = 0; break;
case 24: so0 = 2; so1 = 1; so2 = 0; break;
case 32: so0 = 3; so1 = 2; so2 = 1; so3 = 0; break;
}
}
if (destOrder == LSB_FIRST) {
switch (destDepth) {
case 16: do0 = 1; do1 = 0; break;
case 24: do0 = 2; do1 = 1; do2 = 0; break;
case 32: do0 = 3; do1 = 2; do2 = 1; do3 = 0; break;
}
}
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxs2 = dxs << 1;
dxd2 = dxd << 1;
sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs *= srcDepth / 8;
xs1 *= srcDepth / 8;
sxd *= destDepth / 8;
xd1 *= destDepth / 8;
if (srcGlobalAlpha != -1) srcAlphaData = null;
sa = srcGlobalAlpha;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
sp = ys * srcStride + xs1;
dp = yd * destStride + xd1;
if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
for (dx = 0; dx < dxd; dx++) {
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 16:
srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
break;
case 24:
srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
(srcData[sp+so2] & 0xFF);
break;
case 32:
srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
break;
}
dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
if (op != BLIT_SRC) {
switch (destDepth) {
case 16:
destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
break;
case 24:
destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
(destData[dp+do2] & 0xFF);
break;
case 32:
destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
break;
}
dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
destPixel =
(((dr << 24) >> destRedShift) & destRedMask) |
(((dg << 24) >> destGreenShift) & destGreenMask) |
(((db << 24) >> destBlueShift) & destBlueMask);
switch (destDepth) {
case 16:
destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do1] = (byte)(destPixel & 0xFF);
break;
case 24:
destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do2] = (byte)(destPixel & 0xFF);
break;
case 32:
destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do3] = (byte)(destPixel & 0xFF);
break;
}
while (ex >= 0) {
sp += sxs;
ex -= dxd2;
if (srcAlphaData != null) sap += sas;
}
dp += sxd;
ex += dxs2;
}
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 16:
srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
break;
case 24:
srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
(srcData[sp+so2] & 0xFF);
break;
case 32:
srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
break;
}
dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
if (op != BLIT_SRC) {
switch (destDepth) {
case 16:
destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
break;
case 24:
destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
(destData[dp+do2] & 0xFF);
break;
case 32:
destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
break;
}
dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
destPixel =
(((dr << 24) >> destRedShift) & destRedMask) |
(((dg << 24) >> destGreenShift) & destGreenMask) |
(((db << 24) >> destBlueShift) & destBlueMask);
switch (destDepth) {
case 16:
destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do1] = (byte)(destPixel & 0xFF);
break;
case 24:
destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do2] = (byte)(destPixel & 0xFF);
break;
case 32:
destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do3] = (byte)(destPixel & 0xFF);
break;
}
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Blits an index palette image into a direct palette image.
*/
static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] srcReds, byte[] srcGreens, byte[] srcBlues, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, int destRedMask, int destGreenMask, int destBlueMask, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs;
short sxd, sxs, sas;
int sp, dp, sap = 0;
int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
int srcPixel = 0, destPixel = 0;
short do0 = 0, do1 = 1, do2 = 2, do3 = 3;
int destRedShift, destGreenShift, destBlueShift;
int i, offset = 0;
byte[] srcMasks = null;
int srcN = 1 << srcDepth;
int[] mapping = null;
destRedShift = 32 - getMSBOffset(destRedMask);
destGreenShift = 32 - getMSBOffset(destGreenMask);
destBlueShift = 32 - getMSBOffset(destBlueMask);
if (srcReds != null && srcN > srcReds.length) srcN = srcReds.length;
if (op == BLIT_SRC) {
mapping = new int[srcN];
for (i = 0; i < srcN; i++) {
dr = srcReds[i] & 0xFF;
dg = srcGreens[i] & 0xFF;
db = srcBlues[i] & 0xFF;
mapping[i] =
(((dr << 24) >>> destRedShift) & destRedMask) |
(((dg << 24) >>> destGreenShift) & destGreenMask) |
(((db << 24) >>> destBlueShift) & destBlueMask);
}
}
switch (srcDepth) {
case 1: srcMasks = msbMasks1; break;
case 2: srcMasks = masks2; break;
}
if (srcOrder == LSB_FIRST) {
switch (srcDepth) {
case 1: srcMasks = lsbMasks1; break;
}
}
if (destOrder == LSB_FIRST) {
switch (destDepth) {
case 16: do0 = 1; do1 = 0; break;
case 24: do0 = 2; do1 = 1; do2 = 0; break;
case 32: do0 = 3; do1 = 2; do2 = 1; do3 = 0; break;
}
}
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxs2 = dxs << 1;
dxd2 = dxd << 1;
sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxd *= destDepth / 8;
xd1 *= destDepth / 8;
if (srcGlobalAlpha != -1) srcAlphaData = null;
sa = srcGlobalAlpha;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
offset = 3 - (srcX % 4);
ex = dxs2 - dxd;
xs = xs1;
sp = ys * srcStride;
dp = yd * destStride + xd1;
if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
for (dx = 0; dx < dxd; dx++) {
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 1:
srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
break;
case 2:
srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
srcPixel = srcPixel >> 4;
} else {
srcPixel = srcPixel & 0x0F;
}
break;
case 8:
srcPixel = srcData[sp + xs] & 0xFF;
break;
}
if (mapping != null) {
destPixel = mapping[srcPixel];
} else {
dr = sr = srcReds[srcPixel] & 0xFF;
dg = sg = srcGreens[srcPixel] & 0xFF;
db = sb = srcBlues[srcPixel] & 0xFF;
if (op != BLIT_SRC) {
switch (destDepth) {
case 16:
destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
break;
case 24:
destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
(destData[dp+do2] & 0xFF);
break;
case 32:
destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
break;
}
dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
destPixel =
(((dr << 24) >>> destRedShift) & destRedMask) |
(((dg << 24) >>> destGreenShift) & destGreenMask) |
(((db << 24) >>> destBlueShift) & destBlueMask);
}
switch (destDepth) {
case 16:
destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do1] = (byte)(destPixel & 0xFF);
break;
case 24:
destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do2] = (byte)(destPixel & 0xFF);
break;
case 32:
destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do3] = (byte)(destPixel & 0xFF);
break;
}
while (ex >= 0) {
xs += sxs;
ex -= dxd2;
if (srcAlphaData != null) sap += sas;
}
dp += sxd;
ex += dxs2;
if (offset == 0) {
offset = 3;
} else {
offset--;
}
}
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 1:
srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
break;
case 2:
srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
srcPixel = srcPixel >> 4;
} else {
srcPixel = srcPixel & 0x0F;
}
break;
case 8:
srcPixel = srcData[sp + xs] & 0xFF;
break;
}
if (mapping != null) {
destPixel = mapping[srcPixel];
} else {
dr = sr = srcReds[srcPixel] & 0xFF;
dg = sg = srcGreens[srcPixel] & 0xFF;
db = sb = srcBlues[srcPixel] & 0xFF;
if (op != BLIT_SRC) {
switch (destDepth) {
case 16:
destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
break;
case 24:
destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
(destData[dp+do2] & 0xFF);
break;
case 32:
destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
break;
}
dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
destPixel =
(((dr << 24) >>> destRedShift) & destRedMask) |
(((dg << 24) >>> destGreenShift) & destGreenMask) |
(((db << 24) >>> destBlueShift) & destBlueMask);
}
switch (destDepth) {
case 16:
destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do1] = (byte)(destPixel & 0xFF);
break;
case 24:
destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do2] = (byte)(destPixel & 0xFF);
break;
case 32:
destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
destData[dp + do3] = (byte)(destPixel & 0xFF);
break;
}
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Blits an index palette image into an index palette image.
*/
static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] srcReds, byte[] srcGreens, byte[] srcBlues, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, byte[] destReds, byte[] destGreens, byte[] destBlues, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs, sas;
int sp, dp, sap = 0;
int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
int srcPixel = 0, destPixel = 0;
int i, j, offset = 0;
byte[] srcMasks = null, destMasks = null, destInverseMasks = null;
int destN = 1 << destDepth, srcN = 1 << srcDepth;
int r, g, b, nearestPixel = 0, lastPixel = -1;
int distance, minDistance;
int[] mapping = null;
boolean samePalette = srcReds == destReds && srcGreens == destGreens && srcBlues == srcBlues;
boolean sameAsSrc = op == BLIT_SRC && samePalette && srcDepth <= destDepth;
if (srcReds != null && srcN > srcReds.length) srcN = srcReds.length;
if (destReds != null && destN > destReds.length) destN = destReds.length;
if (op == BLIT_SRC && srcReds != null) {
mapping = new int[srcN];
for (i = 0; i < srcN; i++) {
minDistance = 0x7FFFFFFF;
nearestPixel = 0;
for (j = 0; j < destN; j++) {
r = (destReds[j] & 0xFF) - (srcReds[i] & 0xFF);
g = (destGreens[j] & 0xFF) - (srcGreens[i] & 0xFF);
b = (destBlues[j] & 0xFF) - (srcBlues[i] & 0xFF);
distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
mapping[i] = nearestPixel;
}
}
if (op == BLIT_SRC && srcDepth == destDepth && (mapping != null || samePalette))
{
switch (srcDepth) {
case 1:
stretch1(srcData, srcStride, srcOrder, srcX, srcY, srcWidth, srcHeight, destData, destStride, destOrder, destX, destY, destWidth, destHeight, flipX, flipY);
break;
case 2:
stretch2(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
break;
case 4:
stretch4(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
break;
case 8:
stretch8(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
break;
}
return;
}
switch (srcDepth) {
case 1: srcMasks = msbMasks1; break;
case 2: srcMasks = masks2; break;
}
switch (destDepth) {
case 1: destMasks = msbMasks1; destInverseMasks = msbInverseMasks1; break;
case 2: destMasks = masks2; destInverseMasks = inverseMasks2; break;
}
if (srcOrder == LSB_FIRST) {
switch (srcDepth) {
case 1: srcMasks = lsbMasks1; break;
}
}
if (destOrder == LSB_FIRST) {
switch (destDepth) {
case 1: destMasks = lsbMasks1; destInverseMasks = lsbInverseMasks1; break;
}
}
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxs2 = dxs << 1;
dxd2 = dxd << 1;
sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
if (srcGlobalAlpha != -1) srcAlphaData = null;
sa = srcGlobalAlpha;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
offset = 3 - (srcX % 4);
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
if (srcAlphaData != null) sap = ys * srcAlphaStride;
for (dx = 0; dx < dxd; dx++) {
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 1:
srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
break;
case 2:
srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
srcPixel = srcPixel >> 4;
} else {
srcPixel = srcPixel & 0x0F;
}
break;
case 8:
srcPixel = srcData[sp + xs] & 0xFF;
break;
}
if (mapping != null) {
destPixel = mapping[srcPixel];
} else if (sameAsSrc) {
destPixel = srcPixel;
} else {
dr = sr = srcReds[srcPixel] & 0xFF;
dg = sg = srcGreens[srcPixel] & 0xFF;
db = sb = srcBlues[srcPixel] & 0xFF;
if (op != BLIT_SRC) {
switch (destDepth) {
case 1:
destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
break;
case 2:
destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
destPixel = destData[dp + (xd >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
destPixel = destPixel >> 4;
} else {
destPixel = destPixel & 0x0F;
}
break;
case 8:
destPixel = destData[dp + xd] & 0xFF;
break;
}
dr = destReds[destPixel] & 0xFF;
dg = destGreens[destPixel] & 0xFF;
db = destBlues[destPixel] & 0xFF;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
if (lastPixel == -1 || lastPixel != srcPixel) {
minDistance = 0x7FFFFFFF;
nearestPixel = 0;
for (j = 0; j < destN; j++) {
r = (destReds[j] & 0xFF) - dr;
g = (destGreens[j] & 0xFF) - dg;
b = (destBlues[j] & 0xFF) - db;
distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
lastPixel = srcPixel;
}
destPixel = nearestPixel;
}
switch (destDepth) {
case 1:
if ((destPixel & 0x1) == 1) {
destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
} else {
destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
}
break;
case 2:
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
break;
case 4:
if ((xd & 0x1) == 0) {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
} else {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
}
break;
case 8:
destData[dp + xd] = (byte)(destPixel & 0xFF);
break;
}
while (ex >= 0) {
xs += sxs;
ex -= dxd2;
if (srcAlphaData != null) sap += sas;
}
xd += sxd;
ex += dxs2;
if (offset == 0) {
offset = 3;
} else {
offset--;
}
}
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 1:
srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
break;
case 2:
srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
srcPixel = srcPixel >> 4;
} else {
srcPixel = srcPixel & 0x0F;
}
break;
case 8:
srcPixel = srcData[sp + xs] & 0xFF;
break;
}
if (mapping != null) {
destPixel = mapping[srcPixel];
} else if (sameAsSrc) {
destPixel = srcPixel;
} else {
dr = sr = srcReds[srcPixel] & 0xFF;
dg = sg = srcGreens[srcPixel] & 0xFF;
db = sb = srcBlues[srcPixel] & 0xFF;
if (op != BLIT_SRC) {
switch (destDepth) {
case 1:
destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
break;
case 2:
destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
destPixel = destData[dp + (xd >> 1)] & 0xFF;
if ((xs & 0x1) == 0) {
destPixel = destPixel >> 4;
} else {
destPixel = destPixel & 0x0F;
}
break;
case 8:
destPixel = destData[dp + xd] & 0xFF;
break;
}
dr = destReds[destPixel] & 0xFF;
dg = destGreens[destPixel] & 0xFF;
db = destBlues[destPixel] & 0xFF;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
if (lastPixel == -1 || lastPixel != srcPixel) {
minDistance = 0x7FFFFFFF;
nearestPixel = 0;
for (j = 0; j < destN; j++) {
r = (destReds[j] & 0xFF) - dr;
g = (destGreens[j] & 0xFF) - dg;
b = (destBlues[j] & 0xFF) - db;
distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
lastPixel = srcPixel;
}
destPixel = nearestPixel;
}
switch (destDepth) {
case 1:
if ((destPixel & 0x1) == 1) {
destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
} else {
destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
}
break;
case 2:
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
break;
case 4:
if ((xd & 0x1) == 0) {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
} else {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
}
break;
case 8:
destData[dp + xd] = (byte)(destPixel & 0xFF);
break;
}
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Blits a direct palette image into an index palette image.
*/
static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, int srcRedMask, int srcGreenMask, int srcBlueMask, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, byte[] destReds, byte[] destGreens, byte[] destBlues, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xd;
short sxd, sxs, sas;
int sp, dp, sap = 0;
int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
int srcPixel = 0, destPixel = 0;
short so0 = 0, so1 = 1, so2 = 2, so3 = 3;
int srcRedShift, srcGreenShift, srcBlueShift;
int j, offset = 0;
byte[] destMasks = null, destInverseMasks = null;
int destN = 1 << destDepth;
int r, g, b, nearestPixel = 0, lastPixel = -1;
int distance, minDistance;
srcRedShift = 32 - getMSBOffset(srcRedMask);
srcGreenShift = 32 - getMSBOffset(srcGreenMask);
srcBlueShift = 32 - getMSBOffset(srcBlueMask);
if (destReds != null && destN > destReds.length) destN = destReds.length;
switch (destDepth) {
case 1: destMasks = msbMasks1; destInverseMasks = msbInverseMasks1; break;
case 2: destMasks = masks2; destInverseMasks = inverseMasks2; break;
}
if (srcOrder == LSB_FIRST) {
switch (srcDepth) {
case 16: so0 = 1; so1 = 0; break;
case 24: so0 = 2; so1 = 1; so2 = 0; break;
case 32: so0 = 3; so1 = 2; so2 = 1; so3 = 0; break;
}
}
if (destOrder == LSB_FIRST) {
switch (destDepth) {
case 1: destMasks = lsbMasks1; destInverseMasks = lsbInverseMasks1; break;
}
}
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxs2 = dxs << 1;
dxd2 = dxd << 1;
sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs *= srcDepth / 8;
xs1 *= srcDepth / 8;
if (srcGlobalAlpha != -1) srcAlphaData = null;
sa = srcGlobalAlpha;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
offset = 3 - (srcX % 4);
ex = dxs2 - dxd;
xd = xd1;
sp = ys * srcStride + xs1;
dp = yd * destStride;
if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
for (dx = 0; dx < dxd; dx++) {
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 16:
srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
break;
case 24:
srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
(srcData[sp+so2] & 0xFF);
break;
case 32:
srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
break;
}
dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
if (op != BLIT_SRC) {
switch (destDepth) {
case 1:
destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
break;
case 2:
destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
destPixel = destData[dp + (xd >> 1)] & 0xFF;
if ((xd & 0x1) == 0) {
destPixel = destPixel >> 4;
} else {
destPixel = destPixel & 0x0F;
}
break;
case 8:
destPixel = destData[dp + xd] & 0xFF;
break;
}
dr = destReds[destPixel] & 0xFF;
dg = destGreens[destPixel] & 0xFF;
db = destBlues[destPixel] & 0xFF;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
if (lastPixel == -1 || lastPixel != srcPixel) {
minDistance = 0x7FFFFFFF;
nearestPixel = 0;
for (j = 0; j < destN; j++) {
r = (destReds[j] & 0xFF) - dr;
g = (destGreens[j] & 0xFF) - dg;
b = (destBlues[j] & 0xFF) - db;
distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
lastPixel = srcPixel;
}
destPixel = nearestPixel;
switch (destDepth) {
case 1:
if ((destPixel & 0x1) == 1) {
destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
} else {
destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
}
break;
case 2:
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
break;
case 4:
if ((xd & 0x1) == 0) {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
} else {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
}
break;
case 8:
destData[dp + xd] = (byte)(destPixel & 0xFF);
break;
}
while (ex >= 0) {
sp += sxs;
ex -= dxd2;
if (srcAlphaData != null) sap += sas;
}
xd += sxd;
ex += dxs2;
if (offset == 0) {
offset = 3;
} else {
offset--;
}
}
if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
switch (srcDepth) {
case 16:
srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
break;
case 24:
srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
(srcData[sp+so2] & 0xFF);
break;
case 32:
srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
break;
}
dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
if (op != BLIT_SRC) {
switch (destDepth) {
case 1:
destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
break;
case 2:
destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
break;
case 4:
destPixel = destData[dp + (xd >> 1)] & 0xFF;
if ((xd & 0x1) == 0) {
destPixel = destPixel >> 4;
} else {
destPixel = destPixel & 0x0F;
}
break;
case 8:
destPixel = destData[dp + xd] & 0xFF;
break;
}
dr = destReds[destPixel] & 0xFF;
dg = destGreens[destPixel] & 0xFF;
db = destBlues[destPixel] & 0xFF;
switch (op) {
case BLIT_ALPHA:
dr += (sr - dr) * sa / 255;
dg += (sg - dg) * sa / 255;
db += (sb - db) * sa / 255;
break;
}
}
if (lastPixel == -1 || lastPixel != srcPixel) {
minDistance = 0x7FFFFFFF;
nearestPixel = 0;
for (j = 0; j < destN; j++) {
r = (destReds[j] & 0xFF) - dr;
g = (destGreens[j] & 0xFF) - dg;
b = (destBlues[j] & 0xFF) - db;
distance = r*r + g*g + b*b;
if (distance < minDistance) {
nearestPixel = j;
if (distance == 0) break;
minDistance = distance;
}
}
lastPixel = srcPixel;
}
destPixel = nearestPixel;
switch (destDepth) {
case 1:
if ((destPixel & 0x1) == 1) {
destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
} else {
destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
}
break;
case 2:
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
break;
case 4:
if ((xd & 0x1) == 0) {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
} else {
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
}
break;
case 8:
destData[dp + xd] = (byte)(destPixel & 0xFF);
break;
}
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 1-bit image, into the destination, a 1-bit image.
*/
static void stretch1(byte[] srcData, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs;
byte pixel;
int sp, dp;
byte[] masks, inverseMasks;
if (srcOrder == LSB_FIRST) {
masks = lsbMasks1;
} else {
masks = msbMasks1;
}
if (destOrder == LSB_FIRST) {
inverseMasks = lsbInverseMasks1;
} else {
inverseMasks = msbInverseMasks1;
}
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
pixel = (byte)(srcData[sp + (xs >> 3)] & masks[xs & 7]);
for (dx = 0; dx < dxd; dx++) {
if (pixel != 0)
destData[dp + (xd >> 3)] |= masks[xd & 7];
else
destData[dp + (xd >> 3)] &= inverseMasks[xd & 7];
if (ex >= 0) {
do {
xs += sxs;
ex -= dxd2;
} while (ex >= 0);
pixel = (byte)(srcData[sp + (xs >> 3)] & masks[xs & 7]);
}
xd += sxd;
ex += dxs2;
}
if (pixel != 0)
destData[dp + (xd >> 3)] |= masks[xd & 7];
else
destData[dp + (xd >> 3)] &= inverseMasks[xd & 7];
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 16-bit image, into the destination, a 16-bit image.
* The images are assumed to have the same red, green, and blue masks.
*
* Untested - would need an X server with the same red, green and blue
* masks as the file has, namely, 0x7C00, 0x3E0, 0x1F. Most 16-bit X servers
* have masks of 0xF800, 0x7E0, 0x1F.
*/
static void stretch16(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs;
byte pixel0, pixel1;
int sp, dp;
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
pixel0 = srcData[sp + xs];
pixel1 = srcData[sp + xs + 1];
for (dx = 0; dx < dxd; dx++) {
destData[dp + xd] = pixel0;
destData[dp + xd + 1] = pixel1;
if (ex >= 0) {
do {
xs += (sxs << 1);
ex -= dxd2;
} while (ex >= 0);
pixel0 = srcData[sp + xs];
pixel1 = srcData[sp + xs + 1];
}
xd += (sxd << 1);
ex += dxs2;
}
destData[dp + xd] = pixel0;
destData[dp + xd + 1] = pixel1;
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 2-bit image, into the destination, a 2-bit image.
*/
static void stretch2(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs;
byte pixel;
int sp, dp, x;
byte [] masks = { (byte)0x03, (byte)0x0C, (byte)0x30, (byte)0xC0 };
byte [] inverseMasks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
int offset = 3 - (srcX % 4);
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
x = (byte)(((srcData[sp + (xs >> 2)] & masks[offset]) & 0xFF) >> (offset * 2));
pixel = (byte)(mapping == null ? x : mapping[x]);
for (dx = 0; dx < dxd; dx++) {
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & inverseMasks[offset]) | (pixel << (offset * 2)));
if (ex >= 0) {
do {
xs += sxs;
ex -= dxd2;
} while (ex >= 0);
x = (byte)(((srcData[sp + (xs >> 2)] & masks[offset]) & 0xFF) >> (offset * 2));
pixel = (byte)(mapping == null ? x : mapping[x]);
}
xd += sxd;
ex += dxs2;
if (offset == 0) {
offset = 3;
} else {
offset--;
}
}
destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & inverseMasks[offset]) | (pixel << (offset * 2)));
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 24-bit image, into the destination, a 24-bit image.
* The images must have the same red, green, and blue masks.
* The image are assumed to have 24 bits per pixel; many 24-bit images
* use 32 bits per pixel.
*
* Untested. Would require an X server with a depth of 24 which has 24 bits per
* pixel. Most X servers with depth 24 actually have 32 bits per pixel.
*/
static void stretch24(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2;
short sxd, sxs;
byte r, g, b;
int sp, dp;
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 3 : -3);
sxs = (short)((xs2 - xs1) > 0 ? 3 : -3);
xs1 *= 3;
xd1 *= 3;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
sp = ys * srcStride + xs1;
dp = yd * destStride + xd1;
r = srcData[sp];
g = srcData[sp + 1];
b = srcData[sp + 2];
for (dx = 0; dx < dxd; dx++) {
destData[dp] = r;
destData[dp + 1] = g;
destData[dp + 2] = b;
if (ex >= 0) {
while (ex >= 0) {
sp += sxs;
ex -= dxd2;
}
r = srcData[sp];
g = srcData[sp + 1];
b = srcData[sp + 2];
}
dp += sxd;
ex += dxs2;
}
destData[dp] = r;
destData[dp + 1] = g;
destData[dp + 2] = b;
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 32-bit image, into the destination, a 32-bit image.
* The images must have the same red, green, and blue masks.
*/
static void stretch32(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2;
short sxd, sxs;
byte r, g, b, a;
int sp, dp;
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 4 : -4);
sxs = (short)((xs2 - xs1) > 0 ? 4 : -4);
xs1 *= 4;
xd1 *= 4;
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
sp = ys * srcStride + xs1;
dp = yd * destStride + xd1;
r = srcData[sp];
g = srcData[sp + 1];
b = srcData[sp + 2];
a = srcData[sp + 3];
for (dx = 0; dx < dxd; dx++) {
destData[dp] = r;
destData[dp + 1] = g;
destData[dp + 2] = b;
destData[dp + 3] = a;
if (ex >= 0) {
while (ex >= 0) {
sp += sxs;
ex -= dxd2;
}
r = srcData[sp];
g = srcData[sp + 1];
b = srcData[sp + 2];
a = srcData[sp + 3];
}
dp += sxd;
ex += dxs2;
}
destData[dp] = r;
destData[dp + 1] = g;
destData[dp + 2] = b;
destData[dp + 3] = a;
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, a 4-bit image, into the destination, a 4-bit image.
*/
static void stretch4(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs;
byte pixel;
int sp, dp;
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
int x = srcData[sp + (xs >> 1)];
if ((xs & 1) != 0) {
pixel = (byte)((mapping == null) ? (x & 0x0F) : (mapping[x & 0x0F] & 0x0F));
} else {
pixel = (byte)((mapping == null) ? (x >> 4) : (mapping[x >> 4] & 0x0F));
}
for (dx = 0; dx < dxd; dx++) {
if ((xd & 1) != 0)
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | pixel);
else
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | (pixel << 4));
if (ex >= 0) {
do {
xs += sxs;
ex -= dxd2;
} while (ex >= 0);
x = srcData[sp + (xs >> 1)];
if ((xd & 1) != 0) {
pixel = (byte)((mapping == null) ? (x & 0x0F) : (mapping[x & 0x0F] & 0x0F));
} else {
pixel = (byte)((mapping == null) ? ((x >> 4) & 0x0F) : (mapping[x >> 4] & 0x0F));
}
}
xd += sxd;
ex += dxs2;
}
if ((xd & 1) != 0)
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | pixel);
else
destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | (pixel << 4));
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
/**
* Stretches the source, an 8-bit image, into the destination, an 8-bit image.
*/
static void stretch8(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
short syd, sys;
int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
short sxd, sxs;
byte pixel;
int sp, dp, x;
xs1 = srcX; xs2 = srcX + srcWidth - 1;
ys1 = srcY; ys2 = srcY + srcHeight - 1;
if (flipX) {
xd1 = destX + destWidth - 1;
xd2 = destX;
} else {
xd1 = destX;
xd2 = destX + destWidth - 1;
}
if (flipY) {
yd1 = destY + destHeight - 1;
yd2 = destY;
} else {
yd1 = destY;
yd2 = destY + destHeight - 1;
}
/* Y preliminary calculations */
dyd = yd2 - yd1;
if (dyd < 0) dyd = -dyd;
dys = ys2 - ys1;
if (dys < 0) dys = -dys;
dyd2 = dyd << 1;
dys2 = dys << 1;
syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
ey = dys2 - dyd;
ys = ys1;
yd = yd1;
/* X preliminary calculations */
dxd = xd2 - xd1;
if (dxd < 0) dxd = -dxd;
dxs = xs2 - xs1;
if (dxs < 0) dxs = -dxs;
dxd2 = dxd << 1;
dxs2 = dxs << 1;
sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
for (dy = 0; dy <= dyd; dy++) {
/* X stretch starts here */
ex = dxs2 - dxd;
xs = xs1;
xd = xd1;
sp = ys * srcStride;
dp = yd * destStride;
x = srcData[sp + xs] & 0xFF;
pixel = (byte)(mapping == null ? x : mapping[x]);
for (dx = 0; dx < dxd; dx++) {
destData[dp + xd] = pixel;
if (ex >= 0) {
do {
xs += sxs;
ex -= dxd2;
} while (ex >= 0);
x = srcData[sp + xs] & 0xFF;
pixel = (byte)(mapping == null ? x : mapping[x]);
}
xd += sxd;
ex += dxs2;
}
destData[dp + xd] = pixel;
/* X stretch ends here */
if (dy == dyd)
break;
while (ey >= 0) {
ys += sys;
ey -= dyd2;
}
yd += syd;
ey += dys2;
}
}
}