--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/Graphics.java Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,1447 @@
+/*
+* 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 org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Internal_GfxPackageSupport;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.qt.graphics.GraphicsContext;
+import org.eclipse.swt.internal.qt.graphics.JavaCommandBuffer;
+import org.eclipse.swt.internal.qt.graphics.FontUtils;
+
+import com.nokia.mid.ui.DirectGraphics;
+
+/**
+ * Implementation of LCDUI <code>Graphics</code> class.
+ */
+public class Graphics {
+
+ /**
+ * Constant for horizontal center alignment of the text.
+ */
+ public static final int HCENTER = 1;
+
+ /**
+ * Constant for vertical alignment of the image.
+ */
+ public static final int VCENTER = 2;
+
+ /**
+ * Constant for horizontal left alignment of the text.
+ */
+ public static final int LEFT = 4;
+
+ /**
+ * Constant for horizontal right alignment of the text.
+ */
+ public static final int RIGHT = 8;
+
+ /**
+ * Constant for vertical top alignment of the text.
+ */
+ public static final int TOP = 16;
+
+ /**
+ * Constant for vertical bottom alignment of the text.
+ */
+ public static final int BOTTOM = 32;
+
+ /**
+ * Constant for vertical baseline alignment of the text.
+ */
+ public static final int BASELINE = 64;
+
+ /**
+ * Constant for solid stroke style.
+ */
+ public static final int SOLID = 0;
+
+ /**
+ * Constant for dotted stroke style.
+ */
+ public static final int DOTTED = 1;
+
+ static final int RGB_MASK = 0x00FFFFFF;
+
+ static final int COMPONENT_MASK = 0xFF;
+
+ private DirectGraphics directGraphics;
+
+ // Graphics rectangle (off-screen buffer rectangle).
+ // private Rectangle graphicsClientArea;
+
+ // Graphics context for drawing to off-screen buffer.
+ private GraphicsContext gc;
+
+ // Off-screen buffer.
+ //private org.eclipse.swt.internal.qt.graphics.Image frameBuffer;
+
+ // Current font for rendering texts.
+ private Font currentFont;
+ private int currentColor;
+ private int translateX;
+ private int translateY;
+ private int[] currentClip = new int[4];
+ private int currentStrokeSyle;
+
+ // Image owning the Graphics if the Graphics object belongs to an Image.
+ private Image parentImage;
+
+ // Flag indicating that we are in Canvas.paint() callback,
+ // thus inside UI thread
+ private boolean paintCallBack;
+ private boolean buffered;
+ private JavaCommandBuffer cmdBuffer;
+ private com.nokia.mj.impl.rt.support.Finalizer finalizer;
+ // serialization lock for command buffering and flush
+ private final Object flushLock = new Object();
+ private Canvas canvasParent;
+ private CustomItem customItemParent;
+
+ //Constructor
+ Graphics() {
+ finalizer = ((finalizer != null) ? finalizer
+ : new com.nokia.mj.impl.rt.support.Finalizer() {
+ public void finalizeImpl() {
+ if (finalizer != null) {
+ finalizer = null;
+ if (!ESWTUIThreadRunner.isDisposed()) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ dispose();
+ }
+ });
+
+ }
+ }
+ }
+ });
+ }
+ /**
+ * Set the parent image of this Graphics.
+ *
+ * @param image an image
+ */
+ void eswtSetParentImage(final Image image) {
+ if(buffered) {
+ return;
+ }
+ if (parentImage != image) {
+ parentImage = image;
+
+ if (gc == null) {
+ gc = new GraphicsContext();
+ }
+ else {
+ gc.releaseTarget();
+ }
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ org.eclipse.swt.graphics.Image eswtImage = Image.getESWTImage(image);
+
+ if (eswtImage != null) {
+ gc.bindTarget(Internal_GfxPackageSupport.getImage(eswtImage));
+ Rectangle clipRect = eswtImage.getBounds();
+ setClip(0, 0, clipRect.width, clipRect.height);
+ }
+ reset();
+ }});
+ }
+ }
+
+ /**
+ * Initializes this instance of Graphics to use command buffer.
+ *
+ * Can be called in a non-UI thread. Not thread-safe.
+ *
+ * @param x The x-coordinate of clip
+ * @param y The y-coordinate of clip
+ * @param width The width of clip
+ * @param height The height of clip
+ */
+ void initBuffered(final Canvas parent, final int x, final int y, final int width, final int height) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ cmdBuffer = new JavaCommandBuffer();
+ if (gc == null) {
+ gc = new GraphicsContext();
+ }
+ gc.bindTarget(cmdBuffer);
+ setClip(x, y, width, height);
+ reset();
+ buffered = true;
+ javax.microedition.lcdui.Graphics.this.canvasParent = parent;
+ }});
+ }
+
+ /**
+ * Initializes this instance of Graphics to use command buffer.
+ *
+ * Can be called in a non-UI thread. Not thread-safe.
+ *
+ * @param x The x-coordinate of clip
+ * @param y The y-coordinate of clip
+ * @param width The width of clip
+ * @param height The height of clip
+ */
+ void initBuffered(CustomItem parent, int x, int y, int width, int height) {
+ cmdBuffer = new JavaCommandBuffer();
+ if (gc == null) {
+ gc = new GraphicsContext();
+ }
+ gc.bindTarget(cmdBuffer);
+ setClip(x, y, width, height);
+ reset();
+ buffered = true;
+ this.customItemParent = parent;
+ }
+
+ /**
+ * Resets the command buffer contents.
+ *
+ * This is safe to call only in the UI thread.
+ */
+ void resetCommandBuffer() {
+ gc.releaseTarget();
+ cmdBuffer.reset();
+ gc.bindTarget(cmdBuffer);
+ // write settings which were active before flush
+ // if they are not the same as defaults
+ gc.setFont(Font.getESWTFont(currentFont).handle);
+ gc.setBackgroundColor(currentColor, false);
+ gc.setForegroundColor(currentColor, false);
+ if ((translateX != 0) || (translateY != 0)) {
+ gc.translate(translateX, translateY);
+ }
+
+ // Note that if called in a non-UI thread then the size of the
+ // Canvas or CustomItem can change between getting the height and
+ // getting the width. Those are modified by the UI thread and there
+ // is no synchronization.
+ int w = 0;
+ int h = 0;
+ if(canvasParent != null) {
+ w = canvasParent.getWidth();
+ h = canvasParent.getHeight();
+ } else {
+ w = customItemParent.getContentWidth();
+ h = customItemParent.getContentHeight();
+ }
+
+ if((currentClip[0] != 0) && (currentClip[1] != 0) &&
+ (currentClip[2] != w) && (currentClip[2] != h)) {
+ gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
+ }
+ if (currentStrokeSyle != SOLID) {
+ gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
+ }
+ }
+
+ /**
+ * Returns the current command buffer or null.
+ *
+ * This method is thread-safe.
+ */
+ JavaCommandBuffer getCommandBuffer() {
+ return cmdBuffer;
+ }
+
+ /**
+ * Get the parent image of this Graphics.
+ */
+ Image getParentImage() {
+ return parentImage;
+ }
+
+ /**
+ * Set Graphics context to a target - the GC is coming from paint event.
+ *
+ * @param eswtGC
+ */
+ void eswtSetGC(final GC eswtGC) {
+ if(buffered) {
+ return;
+ }
+ gc = eswtGC.getGCData().internalGc;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ Rectangle clipRect = eswtGC.getClipping();
+ setClip(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
+ reset();
+ }});
+ }
+
+ /**
+ * Disposes Graphics context resources.
+ */
+ void dispose() {
+ if (parentImage != null) {
+ parentImage = null;
+ }
+ if(gc != null) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.dispose();
+ }});
+ gc = null;
+ }
+ if (cmdBuffer != null) {
+ cmdBuffer = null;
+ }
+ }
+
+ /**
+ * Resets Graphics state to initial.
+ */
+ void reset() {
+ setColor(0, 0, 0);
+ setFont(Font.getDefaultFont());
+ setStrokeStyle(Graphics.SOLID);
+ this.translateX = 0;
+ this.translateY = 0;
+ }
+
+ /**
+ * Cleans the Canvas background.
+ */
+ void cleanBackground(Rectangle area) {
+ int savedColor = currentColor;
+ setColor(255, 255, 255);
+ fillRect(area.x, area.y, area.width, area.height);
+ setColor(savedColor);
+ }
+
+ /**
+ * Cleans the Canvas background.
+ */
+ void cleanBackground(int x, int y, int w, int h) {
+ int savedColor = currentColor;
+ setColor(255, 255, 255);
+ fillRect(x, y, w, h);
+ setColor(savedColor);
+ }
+
+ /**
+ * Sets flag indicating that we are in Canvas.paint() callback
+ */
+ void beginPaint() {
+ paintCallBack = true;
+ }
+
+ /**
+ * Sets flag indicating that we are exiting Canvas.paint() callback
+ */
+ void endPaint() {
+ paintCallBack = false;
+ }
+
+ /**
+ * Provides the serialization lock for buffer writing and flushing
+ * @return lock used for synchronizing command buffer access
+ */
+ Object getLock() {
+ return flushLock;
+ }
+
+ /**
+ * Sets coordinate translation. Translations are cumulative.
+ *
+ * @param xDelta x-shift for coordinates.
+ * @param yDelta y-shift for coordinates.
+ */
+ public void translate(int xDelta, int yDelta) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int xDelta_ = xDelta;
+ final int yDelta_ = yDelta;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.translate(xDelta_, yDelta_);
+ }});
+ } else {
+ gc.translate(xDelta, yDelta);
+ }
+ }
+ translateX += xDelta;
+ translateY += yDelta;
+ }
+
+ /**
+ * Returns current X-shift of coordinate translation.
+ *
+ * @return Current X-shift of coordinate translation.
+ */
+ public int getTranslateX() {
+ return translateX;
+ }
+
+ /**
+ * Returns current Y-shift of coordinate translation.
+ *
+ * @return current Y-shift of coordinate translation.
+ */
+ public int getTranslateY() {
+ return translateY;
+ }
+
+ /**
+ * Returns current color in 0x00RRGGBB format.
+ *
+ * @return Current color in 0x00RRGGBB format.
+ */
+ public int getColor() {
+ return currentColor;
+ }
+
+ /**
+ * Returns red component of current color.
+ *
+ * @return Red component of current color in the range of 0-255.
+ */
+ public int getRedComponent() {
+ return currentColor >> 16;
+ }
+
+ /**
+ * Returns green component of current color.
+ *
+ * @return Green component of current color in the range of 0-255.
+ */
+ public int getGreenComponent() {
+ return (currentColor >> 8) & COMPONENT_MASK;
+ }
+
+ /**
+ * Returns blue component of current color.
+ *
+ * @return Blue component of current color in the range of 0-255.
+ */
+ public int getBlueComponent() {
+ return currentColor & COMPONENT_MASK;
+ }
+
+ /**
+ * Returns current grayscale color.
+ *
+ * @return Returns current grayscale color in the range 0-255.
+ */
+ public int getGrayScale() {
+ return (getRedComponent() + getGreenComponent() + getBlueComponent()) / 3;
+ }
+
+ /**
+ * Sets the current color by color components for red, green and blue.
+ *
+ * @param r - red component of the color to be set.
+ * @param g - green component of the color to be set.
+ * @param b - blue component of the color to be set.
+ */
+ public void setColor(int r, int g, int b) {
+ if (r < 0 || r > 255 ||
+ g < 0 || g > 255 ||
+ b < 0 || b > 255 ) {
+ throw new IllegalArgumentException();
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int r_ = r;
+ final int g_ = g;
+ final int b_ = b;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setForegroundColor(r_, g_, b_);
+ gc.setBackgroundColor(r_, g_, b_);
+ }});
+ } else {
+ gc.setForegroundColor(r, g, b);
+ gc.setBackgroundColor(r, g, b);
+ }
+ }
+ currentColor = ((r << 16) | (g << 8) | b) & RGB_MASK;
+ }
+
+ /**
+ * Sets the current color.
+ *
+ * @param RGB - color to be set in the form of 0x00RRGGBB.
+ */
+ public void setColor(int RGB) {
+ int maskedRGB = RGB & RGB_MASK;
+ final int r = maskedRGB >> 16;
+ final int g = (maskedRGB >> 8) & COMPONENT_MASK;
+ final int b = maskedRGB & COMPONENT_MASK;
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setForegroundColor(r, g, b);
+ gc.setBackgroundColor(r, g, b);
+ }});
+ } else {
+ gc.setForegroundColor(r, g, b);
+ gc.setBackgroundColor(r, g, b);
+ }
+ }
+ currentColor = maskedRGB;
+ }
+
+ /**
+ * Sets gray-scale color.
+ *
+ * @param val - gray-scale value to be set in the range of 0-255.
+ */
+ public void setGrayScale(int val) {
+ if ( (val < 0) || (val > 255)) {
+ throw new IllegalArgumentException();
+ }
+ final int col = val & COMPONENT_MASK;
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setForegroundColor(col, col, col);
+ gc.setBackgroundColor(col, col, col);
+ }});
+ } else {
+ gc.setForegroundColor(col, col, col);
+ gc.setBackgroundColor(col, col, col);
+ }
+ }
+ currentColor = ((col << 16) | (col << 8) | col) & RGB_MASK;
+ }
+
+ /**
+ * Returns the current font.
+ *
+ * @return Current font.
+ */
+ public Font getFont() {
+ return currentFont;
+ }
+
+ /**
+ * Sets the font to be used for string rendering.
+ *
+ * @param newFont - the font to be used for string rendering.
+ */
+ public void setFont(Font newFont) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ final Font newFont_ = newFont;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setFont(Font.getESWTFont(newFont_).handle);
+ }});
+ } else {
+ gc.setFont(Font.getESWTFont(newFont).handle);
+ }
+ }
+ currentFont = newFont;
+ }
+
+ /**
+ * Returns left bound of clip rectangle.
+ *
+ * @return Left bound of clip rectangle.
+ */
+ public int getClipX() {
+ return currentClip[0];
+ }
+
+ /**
+ * Returns top bound of clip rectangle.
+ *
+ * @return Top bound of clip rectangle.
+ */
+ public int getClipY() {
+ return currentClip[1];
+ }
+
+ /**
+ * Returns width of clip rectangle.
+ *
+ * @return Width of clip rectangle.
+ */
+ public int getClipWidth() {
+ return currentClip[2];
+ }
+
+ /**
+ * Returns height of clip rectangle.
+ *
+ * @return Height of clip rectangle.
+ */
+ public int getClipHeight() {
+ return currentClip[3];
+ }
+
+ /**
+ * Intersects current clip rectangle with the specified one.
+ *
+ * @param x - left bound of the clip rectangle to intersect with the
+ * current one.
+ * @param y - top bound of the clip rectangle to intersect with the
+ * current one.
+ * @param w - width of the clip rectangle to intersect with the current one.
+ * @param h - height of the clip rectangle to intersect with the current
+ * one.
+ */
+ public void clipRect(int x, int y, int w, int h) {
+ final int cx2 = Math.min( currentClip[0] + currentClip[2], x + w );
+ final int cy2 = Math.min( currentClip[1] + currentClip[3], y + h );
+ // setting of clip to Java Graphics
+ currentClip[0] = Math.max( x, currentClip[0]);
+ currentClip[1] = Math.max( y, currentClip[1]);
+ currentClip[2] = cx2 - currentClip[0];
+ currentClip[3] = cy2 - currentClip[1];
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
+ }});
+ } else {
+ gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
+ }
+ }
+ }
+
+ /**
+ * Sets the clip rectangle.
+ *
+ * @param x - left bound of the new clip rectangle.
+ * @param y - top bound of the new clip rectangle.
+ * @param w - width of the new clip rectangle.
+ * @param h - height of the new clip rectangle.
+ */
+ public void setClip(int x, int y, int w, int h) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setClip(x_, y_, w_, h_, false);
+ }});
+ } else {
+ gc.setClip(x, y, w, h, false);
+ }
+ }
+ currentClip[0] = x;
+ currentClip[1] = y;
+ currentClip[2] = w;
+ currentClip[3] = h;
+ }
+
+ /**
+ * Draws a line with current color and current stroke style.
+ *
+ * @param xStart - X-coordinate of line starting point.
+ * @param yStart - Y-coordinate of line starting point.
+ * @param xEnd - X-coordinate of line end point.
+ * @param yEnd - Y-coordinate of line end point.
+ */
+ public void drawLine(int xStart, int yStart, int xEnd, int yEnd) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int xs_ = xStart;
+ final int ys_ = yStart;
+ final int xe_ = xEnd;
+ final int ye_ = yEnd;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawLine(xs_, ys_, xe_, ye_);
+ }});
+ } else {
+ gc.drawLine(xStart, yStart, xEnd, yEnd);
+ }
+ }
+ }
+
+ /**
+ * Fills a rectangle with current color.
+ *
+ * @param x - x coordinate of top left corner
+ * @param y - y coordinate of top left corner
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ */
+ public void fillRect(int x, int y, int w, int h) {
+ if ((w < 0) || (h < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.fillRect(x_, y_, w_, h_);
+ }});
+ } else {
+ gc.fillRect(x, y, w, h);
+ }
+ }
+ }
+
+ /**
+ * Draws a rectangle with specified color and stroke style.
+ *
+ * @param x - x coordinate of top left corner
+ * @param y - y coordinate of top left corner
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ */
+ public void drawRect(int x, int y, int w, int h) {
+ if ((w < 0) || (h < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawRect(x_, y_, w_, h_);
+ }});
+ } else {
+ gc.drawRect(x, y, w, h);
+ }
+ }
+ }
+
+ /**
+ * Draws a rounded rectangle with specified color and stroke style.
+ *
+ * @param x - x coordinate of top left corner
+ * @param y - y coordinate of top left corner
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @param arcW - arc width for corner rounding.
+ * @param arcH - arc height for corner rounding.
+ */
+ public void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH) {
+ if ((w < 0) || (h < 0) || (arcW < 0) || (arcH < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ final int arcW_ = arcW;
+ final int arcH_ = arcH;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawRoundRect(x_, y_, w_, h_, arcW_, arcH_);
+ }});
+ } else {
+ gc.drawRoundRect(x, y, w, h, arcW, arcH);
+ }
+ }
+ }
+
+ /**
+ * Fills a rounded rectangle with specified color.
+ *
+ * @param x - x coordinate of top left corner
+ * @param y - y coordinate of top left corner
+ * @param w - width of the rectangle
+ * @param h - height of the rectangle
+ * @param arcW - arc width for corner rounding.
+ * @param arcH - arc height for corner rounding.
+ */
+ public void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH) {
+ if ((w < 0) || (h < 0) || (arcW < 0) || (arcH < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ final int arcW_ = arcW;
+ final int arcH_ = arcH;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.fillRoundRect(x_, y_, w_, h_, arcW_, arcH_);
+ }});
+ } else {
+ gc.fillRoundRect(x, y, w, h, arcW, arcH);
+ }
+ }
+ }
+
+ /**
+ * Fills an arc with specified color.
+ *
+ * @param x - X-coordinate of top left corner of the rectangle to contain
+ * the arc.
+ * @param y - Y-coordinate of top left corner of the rectangle to contain
+ * the arc.
+ * @param w - width of the rectangle to contain the arc.
+ * @param h - height of the rectangle to contain the arc.
+ * @param startAngle - starting angle of the arc in degrees.
+ * @param arcAngle - angle to spread the arc in degrees.
+ */
+ public void fillArc(int x, int y, int w, int h, int startAngle, int arcAngle) {
+ if ((w < 0) || (h < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ final int startAngle_ = startAngle;
+ final int arcAngle_ = arcAngle;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.fillArc(x_, y_, w_, h_, startAngle_, arcAngle_);
+ }});
+ } else {
+ gc.fillArc(x, y, w, h, startAngle, arcAngle);
+ }
+ }
+ }
+
+ /**
+ * Draws an arc with specified color and stroke style.
+ *
+ * @param x - X-coordinate of top left corner of the rectangle to contain
+ * the arc.
+ * @param y - Y-coordinate of top left corner of the rectangle to contain
+ * the arc.
+ * @param w - width of the rectangle to contain the arc.
+ * @param h - height of the rectangle to contain the arc.
+ * @param startAngle - starting angle of the arc in degrees.
+ * @param arcAngle - angle to spread the arc in degrees.
+ */
+ public void drawArc(int x, int y, int w, int h, int startAngle, int arcAngle) {
+ if ((w < 0) || (h < 0)) {
+ return;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ final int startAngle_ = startAngle;
+ final int arcAngle_ = arcAngle;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawArc(x_, y_, w_, h_, startAngle_, arcAngle_);
+ }});
+ } else {
+ gc.drawArc(x, y, w, h, startAngle, arcAngle);
+ }
+ }
+ }
+
+ /**
+ * Draws a string with specified color and font.
+ *
+ * @param string - the string to draw.
+ * @param xPos - X-coordinate of the anchor point.
+ * @param yPos - Y-coordinate of the anchor point
+ * @param anch - anchor, specifies the way to locate the text around the anchor
+ * point. May be the combination of Graphics.TOP,
+ * Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
+ * Graphics.RIGHT, Graphics.HCENTER.
+ */
+ public void drawString(String string, int xPos, int yPos, int anch) {
+ if (string == null) {
+ throw new NullPointerException(
+ MsgRepository.GRAPHICS_EXCEPTION_STRING_IS_NULL);
+ }
+
+ if (!checkTextAnchors(anch)) {
+ throw new IllegalArgumentException(
+ MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
+ }
+
+ final int alignments = GraphicsContext.ALIGNMENT_TOP | GraphicsContext.ALIGNMENT_LEFT;
+ final int[] boundingBox = new int[4];
+ final String localStr = string;
+
+ if (paintCallBack) {
+ gc.getTextBoundingBox(boundingBox, string, alignments, 0);
+ }
+ else {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ FontUtils fu = new FontUtils(Font.getESWTFont(currentFont).handle);
+ fu.getBoundingRect(boundingBox, localStr);
+ }
+ });
+ }
+
+ // boundingBox[RECT_X] - top-left x of the text bounding box
+ // boundingBox[RECT_Y] - top-left y of the text bounding box
+ // boundingBox[RECT_WIDTH] - the width of the text bounding box
+ // boundingBox[RECT_HEIGHT] - the height of the text bounding box
+
+ // Arrange vertical alignments
+ int y = yPos;
+ if (isFlag(anch, Graphics.BOTTOM)) {
+ y = yPos - boundingBox[GraphicsContext.RECT_HEIGHT];
+ }
+ if (isFlag(anch, Graphics.BASELINE)) {
+ y = yPos - currentFont.getBaselinePosition();
+ }
+
+ // Arrange horizontal alignments
+ int x = xPos;
+ if (isFlag(anch, Graphics.RIGHT)) {
+ x = xPos - boundingBox[GraphicsContext.RECT_WIDTH];
+ }
+ if (isFlag(anch, Graphics.HCENTER)) {
+ x = xPos - boundingBox[GraphicsContext.RECT_WIDTH] / 2;
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawString(localStr, x_, y_, true);
+ }});
+ } else {
+ gc.drawString(localStr, x, y, true);
+ }
+ }
+ }
+
+ private static boolean isFlag(int anchor, int flag) {
+ return (anchor & flag) != 0;
+ }
+
+ /**
+ * Draws a string with specified color and font.
+ *
+ * @param string - the string to draw.
+ * @param offset - offset of substring in the string.
+ * @param length - length of substring.
+ * @param xPos - X-coordinate of the anchor point.
+ * @param yPos - Y-coordinate of the anchor point
+ * @param anch - anchor, specifies the way to locate the text around the
+ * anchor point. May be the combination of Graphics.TOP,
+ * Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
+ * Graphics.RIGHT, Graphics.HCENTER.
+ */
+ public void drawSubstring(java.lang.String string, int offset, int length,
+ int xPos, int yPos, int anch) {
+ drawString(string.substring(offset, length), xPos, yPos, anch);
+ }
+
+ /**
+ * Draws a character with specified color and font.
+ *
+ * @param c - character to draw.
+ * @param xPos - X-coordinate of the anchor point.
+ * @param yPos - Y-coordinate of the anchor point
+ * @param anch - anchor, specifies the way to locate the text around the
+ * anchor point. May be the combination of Graphics.TOP,
+ * Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
+ * Graphics.RIGHT, Graphics.HCENTER.
+ */
+ public void drawChar(char c, int xPos, int yPos, int anch) {
+ drawString(String.valueOf(c), xPos, yPos, anch);
+ }
+
+ /**
+ * Draws characters from array with specified color and font.
+ *
+ * @param ch -character array to draw.
+ * @param offset - offset of the starting character in the array.
+ * @param length - length of character sequence from the array to draw.
+ * @param xPos - X-coordinate of the anchor point.
+ * @param yPos - Y-coordinate of the anchor point
+ * @param anch - anchor, specifies the way to locate the text around the
+ * anchor point. May be the combination of Graphics.TOP,
+ * Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
+ * Graphics.RIGHT, Graphics.HCENTER.
+ */
+ public void drawChars(char[] ch, int offset, int length,
+ int xPos, int yPos, int anch) {
+ if (ch == null) {
+ throw new NullPointerException(
+ MsgRepository.GRAPHICS_EXCEPTION_ARRAY_IS_NULL);
+ }
+ String str = null;
+ try {
+ str = String.valueOf(ch, offset, length);
+ }
+ catch (Exception e) {
+ throw new ArrayIndexOutOfBoundsException(
+ MsgRepository.GRAPHICS_EXCEPTION_ARRAY_OUT_OF_BOUNDS);
+ }
+
+ drawString(str, xPos, yPos, anch);
+ }
+
+ /**
+ * Checks if anchors combination is valid.
+ */
+ private boolean checkTextAnchors(int anch) {
+ boolean retVal = false;
+
+ int vertMask = Graphics.TOP | Graphics.BASELINE | Graphics.BOTTOM;
+ int horMask = Graphics.LEFT | Graphics.RIGHT | Graphics.HCENTER;
+
+ if (anch == 0) {
+ return true;
+ }
+
+ if ((anch & ~(vertMask | horMask)) != 0) {
+ return false;
+ }
+
+ int vertAchor = anch & vertMask;
+ int horAchor = anch & horMask;
+
+ if ((vertAchor == Graphics.TOP)
+ || (vertAchor == Graphics.BASELINE)
+ || (vertAchor == Graphics.BOTTOM)) {
+ retVal = true;
+ }
+
+ if ((horAchor == Graphics.LEFT)
+ || (vertAchor == Graphics.RIGHT)
+ || (vertAchor == Graphics.HCENTER)) {
+ retVal = true;
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Draw an Image to the graphical context.
+ *
+ * @param image - Image to be drawn.
+ * @param xPos - X-coordinate of the anchor point.
+ * @param yPos - Y-coordinate of the anchor point.
+ * @param anch - anchor value.
+ */
+ public void drawImage(javax.microedition.lcdui.Image image, int xPos,
+ int yPos, int anch) {
+
+ if (image == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_IS_NULL);
+ }
+ if (!checkImageAnchors(anch)) {
+ throw new IllegalArgumentException(
+ MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
+ }
+
+ int y = yPos;
+ if (isFlag(anch, Graphics.VCENTER)) {
+ y = yPos - image.getHeight() / 2;
+ }
+ if (isFlag(anch, Graphics.BOTTOM)) {
+ y = yPos - image.getHeight();
+ }
+
+ int x = xPos;
+ if (isFlag(anch, Graphics.HCENTER)) {
+ x = xPos - image.getWidth() / 2;
+ }
+ if (isFlag(anch, Graphics.RIGHT)) {
+ x = xPos - image.getWidth();
+ }
+
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x_ = x;
+ final int y_ = y;
+ final org.eclipse.swt.internal.qt.graphics.Image image_ =
+ Internal_GfxPackageSupport.getImage(Image.getESWTImage(image));
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawImage(image_, x_, y_);
+ }});
+ } else {
+ gc.drawImage(Internal_GfxPackageSupport.getImage(Image.getESWTImage(image)), x, y);
+ }
+ }
+ }
+
+ /**
+ * Checks if anchors combination is valid.
+ */
+ private boolean checkImageAnchors(int anch) {
+ boolean retVal = false;
+
+ int vertMask = Graphics.TOP | Graphics.VCENTER | Graphics.BOTTOM;
+ int horMask = Graphics.LEFT | Graphics.RIGHT | Graphics.HCENTER;
+
+ if (anch == 0) {
+ return true;
+ }
+
+ if ((anch & ~(vertMask | horMask)) != 0) {
+ return false;
+ }
+
+ int vertAchor = anch & vertMask;
+ int horAchor = anch & horMask;
+
+ if ((vertAchor == Graphics.TOP)
+ || (vertAchor == Graphics.VCENTER)
+ || (vertAchor == Graphics.BOTTOM)) {
+ retVal = true;
+ }
+
+ if ((horAchor == Graphics.LEFT)
+ || (vertAchor == Graphics.RIGHT)
+ || (vertAchor == Graphics.HCENTER)) {
+ retVal = true;
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Sets the stroke style for drawing graphical primitives.
+ *
+ * @param newStyle - new style, valid values are Graphics.SOLID and
+ * Graphics.DOTTED.
+ * @throws IllegalArgumentException if the new style value is invalid.
+ */
+ public void setStrokeStyle(int newStyle) {
+ if (newStyle == currentStrokeSyle) {
+ return;
+ }
+ if (newStyle == SOLID) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setStrokeStyle(GraphicsContext.STROKE_SOLID);
+ }});
+ } else {
+ gc.setStrokeStyle(GraphicsContext.STROKE_SOLID);
+ }
+ }
+ } else {
+ if (newStyle == DOTTED) {
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
+ }});
+ } else {
+ gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
+ }
+ }
+ } else {
+ throw new IllegalArgumentException(
+ MsgRepository.GRAPHICS_EXCEPTION_ILLEGAL_STROKE_STYLE);
+ }
+ }
+ currentStrokeSyle = newStyle;
+ }
+
+ /**
+ * Returns current stroke style.
+ *
+ * @return Current stroke style.
+ */
+ public int getStrokeStyle() {
+ return currentStrokeSyle;
+ }
+
+ /**
+ * Returns the color that will be used if the specified color is requested.
+ *
+ * @param color - color to use in 0x00RRGGBB form.
+ * @return Color that will be actually used in 0x00RRGGBB form.
+ */
+ public int getDisplayColor(int color) {
+ return color & RGB_MASK;
+ }
+
+ /**
+ * Renders 0xAARRGGBB pixels.
+ *
+ * @param rgb - array of ARGB values
+ * @param offset - index of the first value in the array.
+ * @param scanlength - relative distance in the array between. corresponding
+ * pixels of consecutive rows.
+ * @param x - X-coordinate of the top-left corner of the rectangle to be
+ * rendered.
+ * @param y - Y-coordinate of the top-left corner of the rectangle to be
+ * rendered.
+ * @param w - width of the rectangle to be rendered.
+ * @param h - height of the rectangle to be rendered.
+ * @param alpha - true if alpha values should be rendered, false otherwise.
+ */
+ public void drawRGB(int[] rgb,
+ int offset,
+ int scanlength,
+ int x,
+ int y,
+ int w,
+ int h,
+ boolean alpha) {
+
+ if (rgb == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_DATA_IS_NULL);
+ }
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int[] rgb_ = rgb;
+ final int offset_ = offset;
+ final int scanlength_ = scanlength;
+ final int x_ = x;
+ final int y_ = y;
+ final int w_ = w;
+ final int h_ = h;
+ final boolean alpha_ = alpha;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawRGB(rgb_, offset_, scanlength_, x_, y_, w_, h_, alpha_);
+ }});
+ } else {
+ gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha);
+ }
+ }
+ }
+
+ /**
+ * Fills the specified triangle with current color.
+ *
+ * @param xPos1 - X-coordinate of first vertex.
+ * @param yPos1 - Y-coordinate of first vertex.
+ * @param xPos2 - X-coordinate of second vertex.
+ * @param yPos2 - Y-coordinate of second vertex.
+ * @param xPos3 - X-coordinate of third vertex.
+ * @param yPos3 - Y-coordinate of third vertex.
+ */
+ public void fillTriangle(int xPos1,
+ int yPos1,
+ int xPos2,
+ int yPos2,
+ int xPos3,
+ int yPos3) {
+ final int[] points = {xPos1, yPos1, xPos2, yPos2, xPos3, yPos3};
+ synchronized(flushLock) {
+ if(!buffered) {
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.fillPolygon(points);
+ }});
+ } else {
+ gc.fillPolygon(points);
+ }
+ }
+ }
+
+ /**
+ * Copies the specified area.
+ *
+ * @param xFrom - X-coordinate of the top-left corner of the region to copy.
+ * @param yFrom - Y-coordinate of the top-left corner of the region to copy.
+ * @param w - width of the region to copy.
+ * @param h - height of the region to copy.
+ * @param xTo - X-coordinate of the anchor point to copy region to.
+ * @param yTo - Y-coordinate of the anchor point to copy region to.
+ * @param anch - anchor point specification.
+ */
+ public void copyArea(int xFrom,
+ int yFrom,
+ int w,
+ int h,
+ int xTo,
+ int yTo,
+ int anch) {
+
+ if (this.parentImage == null) {
+ // this Graphics belongs to a screen device.
+ throw new IllegalStateException(
+ MsgRepository.GRAPHICS_EXCEPTION_DESTINATION_IS_SCREEN);
+ }
+
+ if (!javax.microedition.lcdui.Image.validateRegion(parentImage
+ .getWidth(), parentImage.getHeight(), xFrom, yFrom, w, h)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_REGION);
+ }
+
+ // Arrange vertical alignments
+ int destY = yTo;
+ if (isFlag(anch, Graphics.BOTTOM)) {
+ destY = yTo - h;
+ }
+ if (isFlag(anch, Graphics.VCENTER)) {
+ destY = yTo - h / 2;
+ }
+
+ // Arrange horizontal alignments
+ int destX = xTo;
+ if (isFlag(anch, Graphics.RIGHT)) {
+ destX = xTo - w;
+ }
+ if (isFlag(anch, Graphics.HCENTER)) {
+ destX = xTo - w / 2;
+ }
+
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int x1 = xFrom;
+ final int y1 = yFrom;
+ final int width = w;
+ final int height = h;
+ final int x2 = destX;
+ final int y2 = destY;
+
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.copyArea(x1, y1, width, height, x2, y2);
+ }});
+ } else {
+ gc.copyArea(xFrom, yFrom, w, h, destX, destY);
+ }
+ }
+ }
+
+ /**
+ * Renders a portion of source image with possible transforms.
+ *
+ * @param srcImage - source Image
+ * @param xSrc - X-coordinate of the top-left corner of the rectangle in
+ * source image.
+ * @param ySrc - Y-coordinate of the top-left corner of the rectangle in
+ * source image.
+ * @param width - width of the rectangle in source image.
+ * @param height - height of the rectangle in source image.
+ * @param transform - transform to apply to the image before rendering.
+ * @param xDst - X-coordinate of the anchor point in destination.
+ * @param yDst - Y-coordinate of the anchor point in destination.
+ * @param anch - anchor point definition.
+ */
+ public void drawRegion(javax.microedition.lcdui.Image srcImage,
+ int xSrc,
+ int ySrc,
+ int width,
+ int height,
+ int transform,
+ int xDst,
+ int yDst,
+ int anch) {
+
+ if (srcImage == null) {
+ throw new NullPointerException(
+ MsgRepository.IMAGE_EXCEPTION_IS_NULL);
+ }
+ if (srcImage == parentImage) {
+ throw new IllegalArgumentException(
+ MsgRepository.GRAPHICS_EXCEPTION_SAME_SOURCE_AND_DESTINATION);
+ }
+ if (!javax.microedition.lcdui.Image.validateTransform(transform)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_TRANSFORM);
+ }
+ if (!checkImageAnchors(anch)) {
+ throw new IllegalArgumentException(
+ MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
+ }
+ if (!javax.microedition.lcdui.Image.validateRegion(srcImage.getWidth(),
+ srcImage.getHeight(), xSrc, ySrc, width, height)) {
+ throw new IllegalArgumentException(
+ MsgRepository.IMAGE_EXCEPTION_INVALID_REGION);
+ }
+
+ // Arrange vertical alignments
+ int y = yDst;
+ if (isFlag(anch, Graphics.VCENTER)) {
+ y = yDst - srcImage.getHeight() / 2;
+ }
+ if (isFlag(anch, Graphics.BOTTOM)) {
+ y = yDst - srcImage.getHeight();
+ }
+
+ // Arrange horizontal alignments
+ int x = xDst;
+ if (isFlag(anch, Graphics.HCENTER)) {
+ x = xDst - srcImage.getWidth() / 2;
+ }
+ if (isFlag(anch, Graphics.RIGHT)) {
+ x = xDst - srcImage.getWidth();
+ }
+
+ final int gcTransform = Image.getCgTransformValue(transform);
+ synchronized(flushLock) {
+ if(!buffered) {
+ final int localXDst = x;
+ final int localYDst = y;
+ final int localW = width;
+ final int localH = height;
+ final int localXSrc = xSrc;
+ final int localYSrc = ySrc;
+ final org.eclipse.swt.internal.qt.graphics.Image localImage =
+ Internal_GfxPackageSupport.getImage(Image.getESWTImage(srcImage));
+ ESWTUIThreadRunner.safeSyncExec(new Runnable() {
+ public void run() {
+ gc.drawImage(localImage, localXDst, localYDst, localW, localH, localXSrc, localYSrc, localW, localH, gcTransform);
+ }});
+ } else {
+ gc.drawImage(Internal_GfxPackageSupport.getImage(Image.getESWTImage(srcImage)),
+ x, y, width, height, xSrc, ySrc, width, height, gcTransform);
+ }
+ }
+ }
+
+ /**
+ * Return DirectGraphics associated with this instance.
+ */
+ DirectGraphics getDirectGraphics() {
+ if (directGraphics == null) {
+ directGraphics = new DirectGraphicsImpl(this);
+ }
+ return directGraphics;
+ }
+
+ /**
+ * Return native graphic context.
+ */
+ GraphicsContext getGc() {
+ return gc;
+ }
+
+}