/* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores * CA 94065 USA or visit www.oracle.com if you need additional information or * have any questions. */ package com.sun.lwuit; import com.sun.lwuit.impl.LWUITImplementation; import com.sun.lwuit.plaf.Style; /** * Abstracts the underlying platform graphics context thus allowing us to achieve * portability between MIDP devices and CDC devices. This abstaction simplifies * and unifies the Graphics implementations of various platforms. * * <p>A graphics instance should never be created by the developer and is always accessed * using either a paint callback or a mutable image. There is no supported way to create this * object directly. */ public final class Graphics { private int xTranslate; private int yTranslate; private int color; private Font current = Font.getDefaultFont(); private LWUITImplementation impl; private Object nativeGraphics; private Object[] nativeGraphicsState; /** * Constructing new graphics with a given javax.microedition.lcdui.Graphics * @param g an implementation dependent native graphics instance */ Graphics(Object nativeGraphics) { setGraphics(nativeGraphics); impl = Display.getInstance().getImplementation(); } /** * Setting graphics with a given javax.microedition.lcdui.Graphics * * @param g a given javax.microedition.lcdui.Graphics */ void setGraphics(Object g) { this.nativeGraphics = g; } /** * Returns javax.microedition.lcdui.Graphics * * @return a javax.microedition.lcdui.Graphics object */ Object getGraphics() { return nativeGraphics; } /** * Translates the X/Y location for drawing on the underlying surface. Translation * is incremental so the new value will be added to the current translation and * in order to reset translation we have to invoke * {@code translate(-getTranslateX(), -getTranslateY()) } * * @param x the x coordinate * @param y the y coordinate */ public void translate(int x, int y) { if(impl.isTranslationSupported()) { impl.translate(nativeGraphics, x, y); } else { xTranslate += x; yTranslate += y; } } /** * Returns the current x translate value * * @return the current x translate value */ public int getTranslateX() { if(impl.isTranslationSupported()) { return impl.getTranslateX(nativeGraphics); } else { return xTranslate; } } /** * Returns the current y translate value * * @return the current y translate value */ public int getTranslateY() { if(impl.isTranslationSupported()) { return impl.getTranslateY(nativeGraphics); } else { return yTranslate; } } /** * Returns the current color * * @return the RGB graphics color */ public int getColor() { return color; } /** * Sets the current rgb color while ignoring any potential alpha component within * said color value. * * @param RGB the RGB value for the color. */ public void setColor(int RGB) { color = 0xffffff & RGB; impl.setColor(nativeGraphics, color); } /** * Returns the font used with the drawString method calls * * @return the font used with the drawString method calls */ public Font getFont() { return current; } /** * Sets the font to use with the drawString method calls * * @param font the font used with the drawString method calls */ public void setFont(Font font) { this.current = font; if(!(font instanceof CustomFont)) { impl.setNativeFont(nativeGraphics, font.getNativeFont()); } } /** * Returns the x clipping position * * @return the x clipping position */ public int getClipX() { return impl.getClipX(nativeGraphics) - xTranslate; } /** * Returns the clip as an x,y,w,h array * @return clip array copy */ public int[] getClip() { return new int[] {getClipX(), getClipY(), getClipWidth(), getClipHeight()}; } /** * Sets the clip from an array containing x, y, width, height value * @param clip 4 element array */ public void setClip(int[] clip) { setClip(clip[0], clip[1], clip[2], clip[3]); } /** * Returns the y clipping position * * @return the y clipping position */ public int getClipY() { return impl.getClipY(nativeGraphics) - yTranslate; } /** * Returns the clip width * * @return the clip width */ public int getClipWidth() { return impl.getClipWidth(nativeGraphics); } /** * Returns the clip height * * @return the clip height */ public int getClipHeight() { return impl.getClipHeight(nativeGraphics); } /** * Clips the given rectangle by intersecting with the current clipping region, this * method can thus only shrink the clipping region and never increase it. * * @param x the x coordinate of the rectangle to intersect the clip with * @param y the y coordinate of the rectangle to intersect the clip with * @param width the width of the rectangle to intersect the clip with * @param height the height of the rectangle to intersect the clip with */ public void clipRect(int x, int y, int width, int height) { impl.clipRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height); } /** * Updates the clipping region to match the given region exactly * * @param x the x coordinate of the new clip rectangle. * @param y the y coordinate of the new clip rectangle. * @param width the width of the new clip rectangle. * @param height the height of the new clip rectangle. */ public void setClip(int x, int y, int width, int height) { impl.setClip(nativeGraphics, xTranslate + x, yTranslate + y, width, height); } /** * Draws a line between the 2 X/Y coordinates * * @param x1 first x position * @param y1 first y position * @param x2 second x position * @param y2 second y position */ public void drawLine(int x1, int y1, int x2, int y2) { impl.drawLine(nativeGraphics, xTranslate + x1, yTranslate + y1, xTranslate + x2, yTranslate + y2); } /** * Fills the rectangle from the given position according to the width/height * minus 1 pixel according to the convention in Java. * * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. * @param height the height of the rectangle to be filled. */ public void fillRect(int x, int y, int width, int height) { impl.fillRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height); } /** * Draws a rectangle in the given coordinates * * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. * @param height the height of the rectangle to be drawn. */ public void drawRect(int x, int y, int width, int height) { impl.drawRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height); } /** * Draws a rounded corner rectangle in the given coordinates with the arcWidth/height * matching the last two arguments respectively. * * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. * @param height the height of the rectangle to be drawn. * @param arcWidth the horizontal diameter of the arc at the four corners. * @param arcHeight the vertical diameter of the arc at the four corners. */ public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { impl.drawRoundRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height, arcWidth, arcHeight); } /** * Makes the current color slightly lighter, this is useful for many visual effects * * @param factor the degree of lightening a color per channel a number from 1 to 255 */ public void lighterColor(int factor) { int color = getColor(); int r = color >> 16 & 0xff; int g = color >> 8 & 0xff; int b = color & 0xff; r = Math.min(0xff, r + factor); g = Math.min(0xff, g + factor); b = Math.min(0xff, b + factor); setColor(((r << 16) & 0xff0000) | ((g << 8) & 0xff00) | (b & 0xff)); } /** * Makes the current color slightly darker, this is useful for many visual effects * * @param factor the degree of lightening a color per channel a number from 1 to 255 */ public void darkerColor(int factor) { int color = getColor(); int r = color >> 16 & 0xff; int g = color >> 8 & 0xff; int b = color & 0xff; r = Math.max(0, r - factor); g = Math.max(0, g - factor); b = Math.max(0, b - factor); setColor(((r << 16) & 0xff0000) | ((g << 8) & 0xff00) | (b & 0xff)); } /** * Fills a rounded rectangle in the same way as drawRoundRect * * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. * @param height the height of the rectangle to be filled. * @param arcWidth the horizontal diameter of the arc at the four corners. * @param arcHeight the vertical diameter of the arc at the four corners. * @see #drawRoundRect */ public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { impl.fillRoundRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height, arcWidth, arcHeight); } /** * Fills a circular or elliptical arc based on the given angles and bounding * box. The resulting arc begins at startAngle and extends for arcAngle * degrees. * * @param x the x coordinate of the upper-left corner of the arc to be filled. * @param y the y coordinate of the upper-left corner of the arc to be filled. * @param width the width of the arc to be filled. * @param height the height of the arc to be filled. * @param startAngle the beginning angle. * @param arcAngle the angular extent of the arc, relative to the start angle. */ public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { impl.fillArc(nativeGraphics, xTranslate + x, yTranslate + y, width, height, startAngle, arcAngle); } /** * Draws a circular or elliptical arc based on the given angles and bounding * box * * @param x the x coordinate of the upper-left corner of the arc to be drawn. * @param y the y coordinate of the upper-left corner of the arc to be drawn. * @param width the width of the arc to be drawn. * @param height the height of the arc to be drawn. * @param startAngle the beginning angle. * @param arcAngle the angular extent of the arc, relative to the start angle. */ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { impl.drawArc(nativeGraphics, xTranslate + x, yTranslate + y, width, height, startAngle, arcAngle); } private void drawStringImpl(String str, int x, int y) { if(!(current instanceof CustomFont)) { impl.drawString(nativeGraphics, str, x + xTranslate, y + yTranslate); } else { char[] data = str.toCharArray(); current.drawChars(this, data, 0, data.length, x, y); } } /** * Draw a string using the current font and color in the x,y coordinates. The font is drawn * from the top position and not the baseline. * * @param str the string to be drawn. * @param x the x coordinate. * @param y the y coordinate. * @param textDecoration Text decoration bitmask (See Style's TEXT_DECORATION_* constants) */ public void drawString(String str, int x, int y,int textDecoration) { // this if has only the minor effect of providing a slighly faster execution path if(textDecoration != 0) { boolean raised = (textDecoration & Style.TEXT_DECORATION_3D)!=0; boolean lowerd = (textDecoration & Style.TEXT_DECORATION_3D_LOWERED)!=0; if (raised || lowerd) { textDecoration = textDecoration & (~Style.TEXT_DECORATION_3D) & (~Style.TEXT_DECORATION_3D_LOWERED); int c = getColor(); int a = getAlpha(); int newColor = 0; int offset = -2; if(lowerd) { offset = 2; newColor = 0xffffff; } setColor(newColor); if(a == 0xff) { setAlpha(140); } drawString(str, x, y + offset, textDecoration); setAlpha(a); setColor(c); drawString(str, x, y, textDecoration); return; } drawStringImpl(str, x, y); if ((textDecoration & Style.TEXT_DECORATION_UNDERLINE)!=0) { drawLine(x, y+current.getHeight()-1, x+current.stringWidth(str), y+current.getHeight()-1); } if ((textDecoration & Style.TEXT_DECORATION_STRIKETHRU)!=0) { drawLine(x, y+current.getHeight()/2, x+current.stringWidth(str), y+current.getHeight()/2); } if ((textDecoration & Style.TEXT_DECORATION_OVERLINE)!=0) { drawLine(x, y, x+current.stringWidth(str), y); } } else { drawStringImpl(str, x, y); } } /** * Draw a string using the current font and color in the x,y coordinates. The font is drawn * from the top position and not the baseline. * * @param str the string to be drawn. * @param x the x coordinate. * @param y the y coordinate. */ public void drawString(String str, int x, int y) { drawString(str, x, y, 0); } /** * Draw the given char using the current font and color in the x,y * coordinates. The font is drawn from the top position and not the * baseline. * * @param character - the character to be drawn * @param x the x coordinate of the baseline of the text * @param y the y coordinate of the baseline of the text */ public void drawChar(char character, int x, int y) { drawString("" + character, x, y); } /** * Draw the given char array using the current font and color in the x,y coordinates. The font is drawn * from the top position and not the baseline. * * @param data the array of characters to be drawn * @param offset the start offset in the data * @param length the number of characters to be drawn * @param x the x coordinate of the baseline of the text * @param y the y coordinate of the baseline of the text */ public void drawChars(char[] data, int offset, int length, int x, int y) { if(!(current instanceof CustomFont)) { drawString(new String(data, offset, length), x, y); } else { CustomFont f = (CustomFont)current; f.drawChars(this, data, offset, length, x, y); } } /** * Draws the image so its top left coordinate corresponds to x/y * * @param img the specified image to be drawn. This method does * nothing if img is null. * @param x the x coordinate. * @param y the y coordinate. */ public void drawImage(Image img, int x, int y) { img.drawImage(this, nativeGraphics, x, y); } /** * Draws the image so its top left coordinate corresponds to x/y and scales it to width/height * * @param img the specified image to be drawn. This method does * nothing if img is null. * @param x the x coordinate. * @param y the y coordinate. * @param w the width to occupy * @param h the height to occupy */ public void drawImage(Image img, int x, int y, int w ,int h) { if(impl.isScaledImageDrawingSupported()) { img.drawImage(this, nativeGraphics, x, y, w, h); } else { drawImage(img.scaled(w, h), x, y); } } void drawImageWH(Object nativeImage, int x, int y, int w ,int h) { impl.drawImage(nativeGraphics, nativeImage, x + xTranslate, y + yTranslate, w, h); } void drawImage(Object img, int x, int y) { impl.drawImage(nativeGraphics, img, x + xTranslate, y + yTranslate); } /** * Draws an image with a MIDP trasnform for fast rotation */ void drawImage(Object img, int x, int y, int transform) { if (transform != 0) { impl.drawImageRotated(nativeGraphics, img, x + xTranslate, y + yTranslate, transform); } else { drawImage(img, x, y); } } /** * Draws a filled triangle with the given coordinates * * @param x1 the x coordinate of the first vertex of the triangle * @param y1 the y coordinate of the first vertex of the triangle * @param x2 the x coordinate of the second vertex of the triangle * @param y2 the y coordinate of the second vertex of the triangle * @param x3 the x coordinate of the third vertex of the triangle * @param y3 the y coordinate of the third vertex of the triangle */ public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3) { impl.fillTriangle(nativeGraphics, xTranslate + x1, yTranslate + y1, xTranslate + x2, yTranslate + y2, xTranslate + x3, yTranslate + y3); } /** * Draws the RGB values based on the MIDP API of a similar name. Renders a * series of device-independent RGB+transparency values in a specified * region. The values are stored in rgbData in a format with 24 bits of * RGB and an eight-bit alpha value (0xAARRGGBB), with the first value * stored at the specified offset. The scanlength specifies the relative * offset within the array between the corresponding pixels of consecutive * rows. Any value for scanlength is acceptable (even negative values) * provided that all resulting references are within the bounds of the * rgbData array. The ARGB data is rasterized horizontally from left to * right within each row. The ARGB values are rendered in the region * specified by x, y, width and height, and the operation is subject * to the current clip region and translation for this Graphics object. * * @param rgbData an array of ARGB values in the format 0xAARRGGBB * @param offset the array index of the first ARGB value * @param x the horizontal location of the region to be rendered * @param y the vertical location of the region to be rendered * @param w the width of the region to be rendered * @param h the height of the region to be rendered * @param processAlpha true if rgbData has an alpha channel, false if * all pixels are fully opaque */ void drawRGB(int[] rgbData, int offset, int x, int y, int w, int h, boolean processAlpha) { impl.drawRGB(nativeGraphics, rgbData, offset, x + xTranslate, y + yTranslate, w, h, processAlpha); } /** * Draws a radial gradient in the given coordinates with the given colors, * doesn't take alpha into consideration when drawing the gradient. * Notice that a radial gradient will result in a circular shape, to create * a square use fillRect or draw a larger shape and clip to the appropriate size. * * @param startColor the starting RGB color * @param endColor the ending RGB color * @param x the x coordinate * @param y the y coordinate * @param width the width of the region to be filled * @param height the height of the region to be filled */ public void fillRadialGradient(int startColor, int endColor, int x, int y, int width, int height) { impl.fillRadialGradient(nativeGraphics, startColor, endColor, x + xTranslate, y + yTranslate, width, height); } /** * Draws a radial gradient in the given coordinates with the given colors, * doesn't take alpha into consideration when drawing the gradient. Notice that this method * differs from fillRadialGradient since it draws a sqare gradient at all times * and can thus be cached * Notice that a radial gradient will result in a circular shape, to create * a square use fillRect or draw a larger shape and clip to the appropriate size. * * @param startColor the starting RGB color * @param endColor the ending RGB color * @param x the x coordinate * @param y the y coordinate * @param width the width of the region to be filled * @param height the height of the region to be filled * @param relativeX indicates the relative position of the gradient within the drawing region * @param relativeY indicates the relative position of the gradient within the drawing region * @param relativeSize indicates the relative size of the gradient within the drawing region */ public void fillRectRadialGradient(int startColor, int endColor, int x, int y, int width, int height, float relativeX, float relativeY, float relativeSize) { impl.fillRectRadialGradient(nativeGraphics, startColor, endColor, x + xTranslate, y + yTranslate, width, height, relativeX, relativeY, relativeSize); } /** * Draws a linear gradient in the given coordinates with the given colors, * doesn't take alpha into consideration when drawing the gradient * * @param startColor the starting RGB color * @param endColor the ending RGB color * @param x the x coordinate * @param y the y coordinate * @param width the width of the region to be filled * @param height the height of the region to be filled * @param horizontal indicating wheter it is a horizontal fill or vertical */ public void fillLinearGradient(int startColor, int endColor, int x, int y, int width, int height, boolean horizontal) { impl.fillLinearGradient(nativeGraphics, startColor, endColor, x + xTranslate, y + yTranslate, width, height, horizontal); } /** * Fills a rectangle with an optionally translucent fill color * * @param x the x coordinate of the rectangle to be filled * @param y the y coordinate of the rectangle to be filled * @param w the width of the rectangle to be filled * @param h the height of the rectangle to be filled * @param alpha the alpha values specify semitransparency */ public void fillRect(int x, int y, int w, int h, byte alpha) { if(alpha != 0) { int oldAlpha = impl.getAlpha(nativeGraphics); impl.setAlpha(nativeGraphics, alpha & 0xff); impl.fillRect(nativeGraphics, x + xTranslate, y + yTranslate, w, h); impl.setAlpha(nativeGraphics, oldAlpha); } } /** * Fills a closed polygon defined by arrays of x and y coordinates. * Each pair of (x, y) coordinates defines a point. * * @param xPoints - a an array of x coordinates. * @param yPoints - a an array of y coordinates. * @param nPoints - a the total number of points. */ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) { int[] cX = xPoints; int[] cY = yPoints; if((!impl.isTranslationSupported()) && (xTranslate != 0 || yTranslate != 0)) { cX = new int[nPoints]; cY = new int[nPoints]; System.arraycopy(xPoints, 0, cX, 0, nPoints); System.arraycopy(yPoints, 0, cY, 0, nPoints); for(int iter = 0 ; iter < nPoints ; iter++) { cX[iter] += xTranslate; cY[iter] += yTranslate; } } impl.fillPolygon(nativeGraphics, cX, cY, nPoints); } /** * Draws a region of an image in the given x/y coordinate * * @param img the image to draw * @param x x location for the image * @param y y location for the image * @param imageX location within the image to draw * @param imageY location within the image to draw * @param imageWidth size of the location within the image to draw * @param imageHeight size of the location within the image to draw */ void drawImageArea(Image img, int x, int y, int imageX, int imageY, int imageWidth, int imageHeight) { img.drawImageArea(this, nativeGraphics, x, y, imageX, imageY, imageWidth, imageHeight); } /** * Draws a closed polygon defined by arrays of x and y coordinates. * Each pair of (x, y) coordinates defines a point. * * @param xPoints - a an array of x coordinates. * @param yPoints - a an array of y coordinates. * @param nPoints - a the total number of points. */ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { int[] cX = xPoints; int[] cY = yPoints; if((!impl.isTranslationSupported()) && (xTranslate != 0 || yTranslate != 0)) { cX = new int[nPoints]; cY = new int[nPoints]; System.arraycopy(xPoints, 0, cX, 0, nPoints); System.arraycopy(yPoints, 0, cY, 0, nPoints); for(int iter = 0 ; iter < nPoints ; iter++) { cX[iter] += xTranslate; cY[iter] += yTranslate; } } impl.drawPolygon(nativeGraphics, cX, cY, nPoints); } /** * Indicates whether invoking set/getAlpha would have an effect on all further * rendering from this graphics object. * * @return false if setAlpha has no effect true if it applies to everything some effect */ public boolean isAlphaSupported() { return impl.isAlphaGlobal(); } /** * Sets alpha as a value between 0-255 (0 - 0xff) where 255 is completely opaque * and 0 is completely transparent * * @param a the alpha value */ public void setAlpha(int a) { impl.setAlpha(nativeGraphics, a); } /** * Returnes the alpha as a value between 0-255 (0 - 0xff) where 255 is completely opaque * and 0 is completely transparent * * @return the alpha value */ public int getAlpha() { return impl.getAlpha(nativeGraphics); } /** * Returns true if anti-aliasing for standard rendering operations is supported, * notice that text anti-aliasing is a separate attribute. * * @return true if anti aliasing is supported */ public boolean isAntiAliasingSupported() { return impl.isAntiAliasingSupported(); } /** * Returns true if anti-aliasing for text is supported, * notice that text anti-aliasing is a separate attribute from standard anti-alisaing. * * @return true if text anti aliasing is supported */ public boolean isAntiAliasedTextSupported() { return impl.isAntiAliasedTextSupported(); } /** * Returns true if anti-aliasing for standard rendering operations is turned on. * * @return true if anti aliasing is active */ public boolean isAntiAliased() { return impl.isAntiAliased(nativeGraphics); } /** * Set whether anti-aliasing for standard rendering operations is turned on. * * @param a true if anti aliasing is active */ public void setAntiAliased(boolean a) { impl.setAntiAliased(nativeGraphics, a); } /** * Set whether anti-aliasing for text is active, * notice that text anti-aliasing is a separate attribute from standard anti-alisaing. * * @param a true if text anti aliasing is supported */ public void setAntiAliasedText(boolean a) { impl.setAntiAliasedText(nativeGraphics, a); } /** * Indicates whether anti-aliasing for text is active, * notice that text anti-aliasing is a separate attribute from standard anti-alisaing. * * @return true if text anti aliasing is supported */ public boolean isAntiAliasedText() { return impl.isAntiAliasedText(nativeGraphics); } /** * Indicates whether the underlying implementation can draw using an affine * transform hence methods such as rotate, scale and shear would work * * @return true if an affine transformation matrix is present */ public boolean isAffineSupported() { return impl.isAffineSupported(); } /** * Resets the affine transform to the default value */ public void resetAffine() { impl.resetAffine(nativeGraphics); } /** * Scales the coordinate system using the affine transform * * @param x scale factor for x * @param y scale factor for y */ public void scale(float x, float y) { impl.scale(nativeGraphics, x, y); } /** * Rotates the coordinate system around a radian angle using the affine transform * * @param angle the rotation angle in radians */ public void rotate(float angle) { impl.rotate(nativeGraphics, angle); } /** * Shear the graphics coordinate system using the affine transform * * @param x shear factor for x * @param y shear factor for y */ public void shear(float x, float y) { impl.shear(nativeGraphics, x, y); } /** * Starts accessing the native graphics in the underlying OS, when accessing * the native graphics LWUIT shouldn't be used! The native graphics is unclipped * and untranslated by default and its the responsibility of the caller to clip/translate * appropriately. * <p>When finished with the native graphics it is essential to <b>invoke endNativeGraphicsAccess</b> * * @return an instance of the underlying native graphics object */ public Object beginNativeGraphicsAccess() { if(nativeGraphicsState != null) { throw new IllegalStateException("beginNativeGraphicsAccess invoked twice in a row"); } Boolean a = Boolean.FALSE, b = Boolean.FALSE; if(isAntiAliasedText()) { b = Boolean.TRUE; } if(isAntiAliased()) { a = Boolean.TRUE; } nativeGraphicsState = new Object[] { new Integer(getTranslateX()), new Integer(getTranslateY()), new Integer(getColor()), new Integer(getAlpha()), new Integer(getClipX()), new Integer(getClipY()), new Integer(getClipWidth()), new Integer(getClipHeight()), a, b }; translate(-getTranslateX(), -getTranslateY()); setAlpha(255); setClip(0, 0, Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight()); return nativeGraphics; } /** * Invoke this to restore LWUIT's graphics settings into the native graphics */ public void endNativeGraphicsAccess() { translate(((Integer)nativeGraphicsState[0]).intValue(), ((Integer)nativeGraphicsState[1]).intValue()); setColor(((Integer)nativeGraphicsState[2]).intValue()); setAlpha(((Integer)nativeGraphicsState[3]).intValue()); setClip(((Integer)nativeGraphicsState[4]).intValue(), ((Integer)nativeGraphicsState[5]).intValue(), ((Integer)nativeGraphicsState[6]).intValue(), ((Integer)nativeGraphicsState[7]).intValue()); setAntiAliased(((Boolean)nativeGraphicsState[8]).booleanValue()); setAntiAliasedText(((Boolean)nativeGraphicsState[9]).booleanValue()); nativeGraphicsState = null; } }