--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/Image.java Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,716 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+package javax.microedition.lcdui;
+
+import java.io.*;
+
+import javax.microedition.lcdui.game.Sprite;
+
+import org.eclipse.swt.graphics.Internal_GfxPackageSupport;
+
+/**
+ * Class containing graphical data of image.<br>
+ * <br>
+ * Image path handling is not implemented correctly, for example "standard"
+ * LCDUI accepts path "/TestMIDlets/images/100x100.png" but corresponding path
+ * with this image-class must be "/100x100.png".
+ */
+public class Image {
+
+ private static Image createImageReturnValue;
+
+ private org.eclipse.swt.graphics.Image eswtImage;
+ private int eswtImageWidth;
+ private int eswtImageHeight;
+
+ private Graphics imageGraphics;
+ private boolean mutable;
+
+ private com.nokia.mj.impl.rt.support.Finalizer finalizer;
+
+ /**
+ * Constructor.
+ */
+ Image(org.eclipse.swt.graphics.Image eswtImage, boolean isMutable) {
+ this.eswtImage = eswtImage;
+ this.mutable = isMutable;
+ eswtImageWidth = eswtImage.getBounds().width;
+ eswtImageHeight = eswtImage.getBounds().height;
+ finalizer = ((finalizer != null) ? finalizer
+ : new com.nokia.mj.impl.rt.support.Finalizer() {
+ public void finalizeImpl() {
+ if (finalizer != null) {
+ finalizer = null;
+ if (!ESWTUIThreadRunner.isDisposed()) {
+ dispose();
+ }
+ }
+ }
+ });
+ ESWTUIThreadRunner.update(getClass().getName(), 1);
+ }
+
+ /**
+ * Called by finalizer when Image is ready to free its resources.
+ */
+ void dispose() {
+ ESWTUIThreadRunner.update(getClass().getName(), -1);
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ if (eswtImage != null) {
+ eswtImage.dispose();
+ eswtImage = null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Return eSWT Image object.
+ */
+ org.eclipse.swt.graphics.Image getESWTImage() {
+ return eswtImage;
+ }
+
+ /**
+ * Return eSWT Image object.
+ *
+ * @param img Image
+ * @return eSWT Image
+ */
+ static org.eclipse.swt.graphics.Image getESWTImage(Image img) {
+ if (img != null) {
+ return img.eswtImage;
+ }
+ return null;
+ }
+
+ /**
+ * Creates new mutable image where every pixel is white.
+ *
+ * @param w The width of the image to be created.
+ * @param h The height of the image to be created.
+ * @return Image created.
+ * @throws IllegalArgumentException if width or height are zero or less.
+ */
+ public static Image createImage(int w, int h) {
+ if (w <= 0 || h <= 0) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_DIMENSIONS);
+ }
+
+ final int width = w;
+ final int height = h;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.graphics.Image eswtImg =
+ eswtCreateImage(width, height);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, true);
+ }
+ else {
+ createImageReturnValue = null;
+ throw new OutOfMemoryError();
+ }
+ }
+ });
+ return createImageReturnValue;
+ }
+
+ /**
+ * Creates an immutable image with the specified size from the existing
+ * image source.
+ *
+ * @param srcImage the source of image.
+ * @param width the width of the new image.
+ * @param height the height of the new image.
+ * @return the resized Image.
+ * @throws NullPointerException if aImage is null.
+ */
+ static Image createImage(Image srcImage, int width, int height) {
+ if (srcImage == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_IS_NULL);
+ }
+ final Image finalImage = srcImage;
+ final int finalWidth = width;
+ final int finalHeight = height;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.graphics.Image eswtImg =
+ eswtCreateImage(finalImage.eswtImage, finalWidth, finalHeight);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, false);
+ }
+ else {
+ createImageReturnValue = null;
+ throw new OutOfMemoryError();
+ }
+ }
+ });
+ return createImageReturnValue;
+ }
+
+ /**
+ * Creates immutable image from existing image source.
+ *
+ * @param srcImage The source of image.
+ * @return Image created.
+ * @throws NullPointerException if source image is null.
+ */
+ public static Image createImage(Image srcImage) {
+ if (srcImage == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_IS_NULL);
+ }
+
+ if (!srcImage.isMutable()) {
+ return srcImage;
+ }
+
+ final Image finalImage = srcImage;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.graphics.Image eswtImg =
+ eswtCreateImage(finalImage.eswtImage);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, false);
+ }
+ else {
+ createImageReturnValue = null;
+ throw new OutOfMemoryError();
+ }
+ }
+ });
+ return createImageReturnValue;
+ }
+
+ /**
+ * Creates an immutable image from named resource.
+ *
+ * @param name The name of the resource.
+ * @return Image created.
+ * @throws NullPointerException if name is null.
+ * @throws IOException If resource doesn't exist, data cannot be loaded or
+ * data is invalid.
+ */
+ public static Image createImage(String name) throws IOException {
+ if (name == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_FILE_NAME_IS_NULL);
+ }
+
+ String fileName = name;
+ if (!fileName.startsWith("/")) {
+ fileName = "/" + fileName;
+ }
+
+ InputStream stream = Image.class.getResourceAsStream(fileName);
+ if (stream == null) {
+ throw new IOException(MsgRepository.IMAGE_EXCEPTION_IO_ERROR);
+ }
+ Image image = createImage(stream);
+ try {
+ stream.close();
+ }
+ catch (IOException e) {
+ // ignore
+ }
+ return image;
+ }
+
+ /**
+ * Creates immutable image from stream. Thread's execution is blocked until
+ * this method is finished.
+ *
+ * @param stream The stream.
+ * @return Image created.
+ * @throws NullPointerException if stream is null.
+ * @throws java.io.IOException If I/O error occurs or data from stream is
+ * invalid.
+ */
+ public static Image createImage(InputStream stream) throws java.io.IOException {
+ if (stream == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_FILE_STREAM_IS_NULL);
+ }
+ final InputStream finalStream = stream;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.graphics.Image eswtImg = eswtCreateImage(finalStream);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, false);
+ }
+ else {
+ createImageReturnValue = null;
+ }
+ }
+ });
+ if (createImageReturnValue == null) {
+ throw new IOException(MsgRepository.IMAGE_EXCEPTION_IO_ERROR);
+ }
+ return createImageReturnValue;
+ }
+
+ /**
+ * Creates new immutable image from image data provided.
+ *
+ * @param imgData Image data.
+ * @param imgOffset Start offset in image data.
+ * @param imgLength Length of data used.
+ * @return Image created.
+ * @throws ArrayIndexOutOfBoundsException if imgOffset and imgLength
+ * specifies invalid range.
+ * @throws NullPointerException if imgData is null.
+ * @throws IllegalArgumentException if imgData content is invalid.
+ */
+ public static Image createImage(byte[] imgData, int imgOffset, int imgLength) {
+ if (imgData == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_DATA_IS_NULL);
+ }
+ if (imgOffset + imgLength > imgData.length) {
+ throw new ArrayIndexOutOfBoundsException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_BOUNDS);
+ }
+ if (imgOffset < 0 || imgLength < 0) {
+ throw new ArrayIndexOutOfBoundsException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_BOUNDS);
+ }
+
+ InputStream inputStream = new ByteArrayInputStream(imgData, imgOffset, imgLength);
+ try {
+ createImageReturnValue = createImage(inputStream);
+ }
+ catch (IOException e) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_DATA);
+ }
+ finally {
+ try {
+ inputStream.close();
+ }
+ catch (IOException e) {
+ // ignore
+ }
+ }
+ return createImageReturnValue;
+ }
+
+ /**
+ * Creates an immutable image from specified region of existing source image
+ * with specified transform.
+ *
+ * @param srcImage Source image.
+ * @param x Region's x.
+ * @param y Region's y.
+ * @param w Regions width.
+ * @param h Regions height.
+ * @param transform Transform, one of the transforms specified in
+ * Sprite-class.
+ * @return Image created.
+ * @throws NullPointerException if img is null.
+ * @throws IllegalArgumentException if Region specified exceeds the source
+ * image or if w or h is zero or less or if transform is not one
+ * defined in Sprite-class.
+ */
+ public static Image createImage(Image srcImage,
+ int x,
+ int y,
+ int w,
+ int h,
+ int transform) {
+ if (srcImage == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_IS_NULL);
+ }
+ if (w <= 0 || h <= 0) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_DIMENSIONS);
+ }
+ if (!validateTransform(transform)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_TRANSFORM);
+ }
+ if (!validateRegion(srcImage.getWidth(), srcImage.getHeight(), x, y, w, h)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_REGION);
+ }
+
+ final Image fImage = srcImage;
+ final int fx = x;
+ final int fy = y;
+ final int fw = w;
+ final int fh = h;
+ final int fTransform = transform;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.internal.qt.graphics.Image srcCgImage =
+ Internal_GfxPackageSupport.getImage(fImage.getESWTImage());
+
+ org.eclipse.swt.internal.qt.graphics.Image cgImage =
+ new org.eclipse.swt.internal.qt.graphics.Image(
+ srcCgImage, fx, fy, fw, fh);
+
+ cgImage.transform(getCgTransformValue(fTransform));
+
+ org.eclipse.swt.graphics.Image eswtImg =
+ Internal_GfxPackageSupport.new_Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(),
+ cgImage);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, false);
+ }
+ else {
+ createImageReturnValue = null;
+ throw new OutOfMemoryError();
+ }
+ }
+ });
+ return createImageReturnValue;
+ }
+
+ /**
+ * Validates that a specified region is fully located within the image
+ * bounds. Method is package-private, used by Graphics.drawRegion as well.
+ */
+ static boolean validateRegion(int srcWidth, int srcHeight, int x, int y,
+ int w, int h) {
+ return x >= 0 && y >= 0 && w <= srcWidth && h <= srcHeight;
+ }
+
+ /**
+ * Validates if transform has a valid value. Method is package-private, used
+ * by Graphics.drawRegion as well.
+ */
+ static boolean validateTransform(int transform) {
+ return transform == Sprite.TRANS_NONE
+ || transform == Sprite.TRANS_MIRROR
+ || transform == Sprite.TRANS_MIRROR_ROT90
+ || transform == Sprite.TRANS_MIRROR_ROT180
+ || transform == Sprite.TRANS_MIRROR_ROT270
+ || transform == Sprite.TRANS_ROT90
+ || transform == Sprite.TRANS_ROT180
+ || transform == Sprite.TRANS_ROT270;
+ }
+
+ /**
+ * Maps LCDUI transform constants to Common Graphics. Method is package-private, used
+ * by Graphics.drawRegion as well.
+ */
+ static int getCgTransformValue(int transform) {
+ int retVal = org.eclipse.swt.internal.qt.graphics.Image.TRANS_NONE;
+ switch (transform) {
+ case Sprite.TRANS_NONE:
+ retVal = org.eclipse.swt.internal.qt.graphics.Image.TRANS_NONE;
+ break;
+ case Sprite.TRANS_ROT90:
+ retVal = org.eclipse.swt.internal.qt.graphics.Image.TRANS_ROT90;
+ break;
+ case Sprite.TRANS_ROT180:
+ retVal =
+ org.eclipse.swt.internal.qt.graphics.Image.TRANS_ROT180;
+ break;
+ case Sprite.TRANS_ROT270:
+ retVal =
+ org.eclipse.swt.internal.qt.graphics.Image.TRANS_ROT270;
+ break;
+ case Sprite.TRANS_MIRROR:
+ retVal =
+ org.eclipse.swt.internal.qt.graphics.Image.TRANS_MIRROR;
+ break;
+ case Sprite.TRANS_MIRROR_ROT90:
+ retVal = org.eclipse.swt.internal.qt.graphics.
+ Image.TRANS_MIRROR_ROT90;
+ break;
+ case Sprite.TRANS_MIRROR_ROT180:
+ retVal = org.eclipse.swt.internal.qt.graphics.
+ Image.TRANS_MIRROR_ROT180;
+ break;
+ case Sprite.TRANS_MIRROR_ROT270:
+ retVal = org.eclipse.swt.internal.qt.graphics.
+ Image.TRANS_MIRROR_ROT270;
+ break;
+ default:
+ break;
+ }
+ return retVal;
+ }
+
+ /**
+ * Creates eSWT image as a copy of existing image.
+ *
+ * @param image - image to be copied.
+ * @return new eSWT image.
+ */
+ private static org.eclipse.swt.graphics.Image eswtCreateImage(
+ org.eclipse.swt.graphics.Image srcImage) {
+ org.eclipse.swt.graphics.Image ret = null;
+ try {
+ org.eclipse.swt.internal.qt.graphics.Image cgImage =
+ Internal_GfxPackageSupport.getImage(srcImage);
+
+ org.eclipse.swt.internal.qt.graphics.Image cgImage2 =
+ new org.eclipse.swt.internal.qt.graphics.Image(cgImage);
+
+ ret = Internal_GfxPackageSupport.new_Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(), cgImage2);
+ }
+ catch (IllegalArgumentException ex) {
+ // Device is null or there's no current device.
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTException ex) {
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTError err) {
+ ret = null;
+ }
+ return ret;
+ }
+
+ /**
+ * Creates eSWT image of the specified size from the given image.
+ */
+ static org.eclipse.swt.graphics.Image eswtCreateImage(
+ org.eclipse.swt.graphics.Image image, int newWidth, int newHeight) {
+ org.eclipse.swt.graphics.Image ret = null;
+ try {
+ ret = new org.eclipse.swt.graphics.Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(),
+ image.getImageData().scaledTo(newWidth, newHeight));
+ }
+ catch (IllegalArgumentException ex) {
+ // Device is null or there's no current device.
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTException ex) {
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTError err) {
+ ret = null;
+ }
+ return ret;
+ }
+
+ /**
+ * Creates eSWT image of the specified size.
+ */
+ static org.eclipse.swt.graphics.Image eswtCreateImage(int width, int height) {
+ org.eclipse.swt.graphics.Image ret = null;
+ try {
+ ret = new org.eclipse.swt.graphics.Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(), width, height);
+ }
+ catch (IllegalArgumentException ex) {
+ // Device is null or there's no current device.
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTException ex) {
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTError err) {
+ ret = null;
+ }
+ return ret;
+ }
+
+ /**
+ * Creates and eSWT image out of the InputStream.
+ */
+ static org.eclipse.swt.graphics.Image eswtCreateImage(InputStream inputStream) {
+ org.eclipse.swt.graphics.Image ret = null;
+ try {
+ ret = new org.eclipse.swt.graphics.Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(), inputStream);
+ }
+ catch (IllegalArgumentException ex) {
+ // Device is null or there's no current device.
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTException ex) {
+ ret = null;
+ }
+ catch (org.eclipse.swt.SWTError err) {
+ ret = null;
+ }
+ return ret;
+ }
+
+ /**
+ * Creates new image from specified RGB array data.
+ *
+ * @param rgbData Pixel data.
+ * @param width Width of the image to be created.
+ * @param height Height of the image to be created.
+ * @param processAlpha true if there's alpha channel in image data.
+ * Otherwise method assumes that all pixels are fully opaque.
+ * @return Image created.
+ * @throws NullPointerException if rgb is null.
+ * @throws IllegalArgumentException if w or h is zero or less.
+ * @throws ArrayIndexOutOfBoundsException if the w and h parameters doesn't
+ * match the length of the data array provided.
+ */
+ public static Image createRGBImage(int[] rgbData,
+ int width,
+ int height,
+ boolean processAlpha) {
+
+ if (rgbData == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_DATA_IS_NULL);
+ }
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_DIMENSIONS);
+ }
+ if (width * height > rgbData.length) {
+ throw new ArrayIndexOutOfBoundsException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_BOUNDS);
+ }
+
+ final int[] rgb = rgbData;
+ final int w = width;
+ final int h = height;
+ final boolean alpha = processAlpha;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.internal.qt.graphics.Image cgImage =
+ new org.eclipse.swt.internal.qt.graphics.Image(rgb, w, h, alpha);
+
+ org.eclipse.swt.graphics.Image eswtImg =
+ Internal_GfxPackageSupport.new_Image(
+ ESWTUIThreadRunner.getInstance().getDisplay(), cgImage);
+
+ if (eswtImg != null) {
+ createImageReturnValue = new Image(eswtImg, false);
+ }
+ else {
+ createImageReturnValue = null;
+ throw new OutOfMemoryError();
+ }
+ }
+ });
+ return createImageReturnValue;
+ }
+
+ /**
+ * Returns ARGB data of image region to an int[] array.
+ *
+ * @param rgbData - array to be filled with ARGB data.
+ * @param offset - first index in the array to store the data.
+ * @param length - relative distance in the array between corresponding
+ * pixels of consecutive rows.
+ * @param xPos - x-coordinate of the top-left corner of the region.
+ * @param yPos - y-coordinate of the top-left corner of the region.
+ * @param width - width of the region.
+ * @param height - height of the region.
+ */
+ public void getRGB(int[] rgbData,
+ int offset,
+ int length,
+ int xPos,
+ int yPos,
+ int width,
+ int height) {
+
+ if (rgbData == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_DATA_IS_NULL);
+ }
+ if (!validateRegion(this.getWidth(), this.getHeight(),
+ xPos, yPos, width, height)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_BOUNDS);
+ }
+ if (Math.abs(length) < width) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_SCANLENGTH);
+ }
+
+ final int[] localRgbData = rgbData;
+ final int localOffset = offset;
+ final int localLength = length;
+ final int localX = xPos;
+ final int localY = yPos;
+ final int localW = width;
+ final int localH = height;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.internal.qt.graphics.Image cgImage = Internal_GfxPackageSupport.getImage(eswtImage);
+ cgImage.getRGB(localRgbData, localOffset, localLength,
+ localX, localY, localW, localH);
+ }
+ });
+ }
+
+ /**
+ * Creates a new Graphics-objects that is able to draw to this image.
+ *
+ * @return New Graphics-object.
+ * @throws IllegalStateException if image is immutable.
+ */
+ public Graphics getGraphics() {
+ if (mutable) {
+ if (imageGraphics == null) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ // instantiate the Graphics object
+ imageGraphics = new Graphics();
+ // bind the GC to the Image target
+ imageGraphics.eswtSetParentImage(Image.this);
+ }
+ });
+ }
+ return imageGraphics;
+ }
+ throw new IllegalStateException(MsgRepository.IMAGE_EXCEPTION_IMMUTABLE);
+ }
+
+ /**
+ * Gets width of the image.
+ *
+ * @return Image width.
+ */
+ public int getWidth() {
+ return eswtImageWidth;
+ }
+
+ /**
+ * Gets height of the image.
+ *
+ * @return Image height.
+ */
+ public int getHeight() {
+ return eswtImageHeight;
+ }
+
+ /**
+ * Check is it possible to modify this image.
+ *
+ * @return true, if image is mutable.
+ */
+ public boolean isMutable() {
+ return mutable;
+ }
+
+}