public Image colImage(int color) { Image img = Image.createImage(Font.getDefaultFont().getHeight(), Font.getDefaultFont().getHeight()); Graphics g = img.getGraphics(); g.setColor(color); g.fillRect(0, 0, img.getWidth(), img.getHeight()); return img; }
public ExtendedTextField() { setFullScreenMode(true); setCommandListener(this); exit = new Command("Exit", Command.EXIT, 1); open = new Command("Open", Command.ITEM, 1); newFile = new Command("New", Command.ITEM, 2); save = new Command("Save", Command.ITEM, 3); saveAs = new Command("Save As", Command.ITEM, 4); eval = new Command("Eval", Command.ITEM, 5); output = new Command("Output", Command.ITEM, 6); cls = new Command("Clear", Command.ITEM, 7); addCommand(exit); addCommand(newFile); addCommand(open); addCommand(save); addCommand(saveAs); addCommand(eval); addCommand(output); addCommand(cls); new Thread(this).start(); // TODO: change font size? inputFont = Font.getDefaultFont(); inputWidth = getWidth(); inputHeight = inputFont.getHeight(); linesOnScreen = getHeight() / inputHeight; addNewLine(0); }
/** * Konstruktor obiektu klasy MainCanvas * * @throws IOException */ public MainCanvas() throws IOException { super(true); soundPlayer = new SoundPlayer(); // uruchomienie watku odpowiedzialnego za odtwarzanie dzwiekow new Thread(soundPlayer).start(); screenWidth = getWidth(); screenHeight = getHeight(); fontHeight = Font.getDefaultFont().getHeight(); mediaLibrarySelectedItemOnScreen = 0; mediaLibraryItemsNumberOnScreen = (screenHeight - 16) / (fontHeight + 5); buttonsLocation = 70; loadResources(); // utworzenie obiektow warstwy tla i tekstur bluetoothPlayer = new BluetoothPlayer(); Thread appThread = new Thread(this); // uruchomienie watku odpowiedzialnego za wyswietlanie grafiki appThread.start(); }
/** * Metoda wyswietlajaca biblioteke muzyczna na wyswietlaczu * * @param g Referencja do obiektu klasy Graphics, ktory pozwala na wyswietlenie tekstu * @param player Referencja do obiektu klasy odtwarzacza muzycznego * @param screenSelectedItemIndex Indeks wybranego elementu na wyswietlaczu * @param screenNumberOfItems Liczba elementow wyswietlonych na wyswietlaczu */ public void showMediaLibrary( Graphics g, BluetoothPlayer player, int screenSelectedItemIndex, int screenNumberOfItems) { int color = g.getColor(); // przechowanie uzywanego koloru int textPos = 0; String text; g.setColor(255, 255, 255); // biala czcionka for (int i = 0; i < screenNumberOfItems; i++) { text = bluetoothPlayer .getMediaLibrary() .getItem( bluetoothPlayer.getMediaLibrary().getMediaLibrarySelectedItem() - screenSelectedItemIndex + i, g); if (text != null) { // jesli zmienil sie wybrany tekst if ((screenSelectedItemIndex == i) && (text.equals(mediaLibraryLastText) == false)) { mediaLibraryLastText = text; mediaLibraryTextPos = 0; mediaLibraryWaitTimeText = SCROLL_TIME_WAIT; } textPos = mediaLibraryTextPos; // if whole text can be displayed at once if (Font.getDefaultFont().stringWidth(text) <= screenWidth - 32) { g.setColor(255, 255, 255); // biala czcionka g.drawString(text, 10, i * (fontHeight + 5) + 8, Graphics.TOP | Graphics.LEFT); } // if text doesn't fit into the screen else { String leftTextTmp = ""; int j = 0; // cut text from the left as long as it doesn't fit to the screen (only for selected item) if (screenSelectedItemIndex == i) while (Font.getDefaultFont().stringWidth(leftTextTmp) < textPos) { leftTextTmp = text.substring(0, ++j); } String textTmp = text.substring(j, text.length()); boolean textRightCut = false; // cut text from the right as long as it doesn't fit to the screen while (Font.getDefaultFont().stringWidth(textTmp) > screenWidth - 24) { textTmp = textTmp.substring(0, textTmp.length() - 1); textRightCut = true; } g.setColor(255, 255, 255); // biala czcionka g.drawString(textTmp, 10, i * (fontHeight + 5) + 8, Graphics.TOP | Graphics.LEFT); g.setColor(BACKGROUND_COLOR); // zamazanie tekstu po bokach g.fillRect(screenWidth - 10, i * (fontHeight + 5) + 8, 5, fontHeight); if (screenSelectedItemIndex == i) { if ((textRightCut == false) && (mediaLibraryWaitTimeText == 0)) // jesli tekst przewinal sie do konca mediaLibraryWaitTimeText = SCROLL_TIME_WAIT; if (mediaLibraryWaitTimeText == 0) mediaLibraryTextPos += 2; // przewiniecie tekstu // if text is going to be displayed statically (without scrolling it) else { mediaLibraryWaitTimeText--; // if wait time has ended, start scrolling from the beginning if ((mediaLibraryWaitTimeText == 0) && (mediaLibraryTextPos != 0)) { mediaLibraryWaitTimeText = SCROLL_TIME_WAIT; mediaLibraryTextPos = 0; } } } } } } g.setColor(255, 255, 255); // obwodka dla podswietlonego elementu if (screenNumberOfItems > 0) g.drawRect( 7, screenSelectedItemIndex * (fontHeight + 5) + 6, screenWidth - 16, fontHeight + 1); g.setColor(color); }
/** * Metoda sluzaca do wypisania tekstu na ekranie w podanej linii * * @param g Referencja do obiektu klasy Graphics, ktory pozwala na wyswietlenie tekstu * @param text Tekst, ktory ma zostac wypisany * @param line Numer linii, w ktorej ma zostac wypisany tekst * @return <code>true</code> jesli wypisanie tekstu powiodlo sie, <code>false</code> w przeciwnym * razie */ public boolean drawText(Graphics g, String text, int line) { int color = g.getColor(); // przechowanie uzywanego koloru int textPos = 0; g.setColor(BACKGROUND_COLOR); // zamazanie starego tekstu g.fillRect(16, 16 + line * (fontHeight + 3), screenWidth - 32, fontHeight); if (line == 0) { // if displayed text had changed if (text.equals(lastText0) == false) { lastText0 = text; textPos0 = 0; waitTimeText0 = SCROLL_TIME_WAIT; } textPos = textPos0; } else if (line == 1) { // if displayed text had changed if (text.equals(lastText1) == false) { lastText1 = text; textPos1 = 0; waitTimeText1 = SCROLL_TIME_WAIT; } textPos = textPos1; } // if whole text can be displayed at once if (Font.getDefaultFont().stringWidth(text) <= screenWidth - 32) { g.setColor(255, 255, 255); // biala czcionka g.drawString(text, 16, 16 + line * (fontHeight + 3), Graphics.TOP | Graphics.LEFT); } // if text doesn't fit into the screen else { String leftTextTmp = ""; int i = 0; // cut text from the left as long as it doesn't fit to the screen while (Font.getDefaultFont().stringWidth(leftTextTmp) < textPos) { leftTextTmp = text.substring(0, ++i); } String textTmp = text.substring(i, text.length()); boolean textRightCut = false; // cut text from the right as long as it doesn't fit to the screen while (Font.getDefaultFont().stringWidth(textTmp) > screenWidth - 32) { textTmp = textTmp.substring(0, textTmp.length() - 1); textRightCut = true; } g.setColor(255, 255, 255); // biala czcionka g.drawString(textTmp, 16, 16 + line * (fontHeight + 3), Graphics.TOP | Graphics.LEFT); g.setColor(BACKGROUND_COLOR); // zamazanie tekstu po bokach g.fillRect(screenWidth - 16, 16 + line * (fontHeight + 3), 11, fontHeight); // g.fillRect(5, 16 + line*(fontHeight + 3), 11, fontHeight); if (line == 0) { if ((textRightCut == false) && (waitTimeText0 == 0)) // jesli tekst przewinal sie do konca waitTimeText0 = SCROLL_TIME_WAIT; if (waitTimeText0 == 0) textPos0 += 2; // przewiniecie tekstu // if text is going to be displayed statically (without scrolling it) else { waitTimeText0--; // if wait time has ended, start scrolling from the beginning if ((waitTimeText0 == 0) && (textPos0 != 0)) { waitTimeText0 = SCROLL_TIME_WAIT; textPos0 = 0; } } } else if (line == 1) { if ((textRightCut == false) && (waitTimeText1 == 0)) // jesli tekst przewinal sie do konca waitTimeText1 = SCROLL_TIME_WAIT; if (waitTimeText1 == 0) textPos1 += 2; // przewiniecie tekstu // if text is going to be displayed statically (without scrolling it) else { waitTimeText1--; // if wait time has ended, start scrolling from the beginning if ((waitTimeText1 == 0) && (textPos1 != 0)) { waitTimeText1 = SCROLL_TIME_WAIT; textPos1 = 0; } } } } g.setColor(color); return true; }
/** * 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 CodenameOneImplementation impl; private Object nativeGraphics; private Object[] nativeGraphicsState; private float scaleX = 1, scaleY = 1; /** * 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.impl; } /** * 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 the underlying native graphics object * * @return the underlying native 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); } /** * Pushes the current clip onto the clip stack. It can later be restored using {@link #popClip}. */ public void pushClip() { impl.pushClip(nativeGraphics); } /** Pops the top clip from the clip stack and sets it as the current clip. */ public void popClip() { impl.popClip(nativeGraphics); } /** * 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 rectangle in the given coordinates with the given thickness * * @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 thickness the thickness in pixels */ public void drawRect(int x, int y, int width, int height, int thickness) { impl.drawRect(nativeGraphics, xTranslate + x, yTranslate + y, width, height, thickness); } /** * 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. Usage: * * <p><script src="https://gist.github.com/codenameone/31a32bdcf014a9e55a95.js"></script> * * @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) { // remove a commonly used trick to create a spacer label from the paint queue if (str.length() == 0 || str == " ") { return; } if (!(current instanceof CustomFont)) { impl.drawString(nativeGraphics, str, x + xTranslate, y + yTranslate); } else { current.drawString(this, 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. * @param textDecoration Text decoration bitmask (See Style's TEXT_DECORATION_* constants) */ public void drawString(String str, int x, int y, int textDecoration) { Object nativeFont = null; if (current != null) { nativeFont = current.getNativeFont(); } impl.drawString( nativeGraphics, nativeFont, str, x + xTranslate, y + yTranslate, textDecoration); } /** * Draws a string using baseline coordinates. * * @param str The string to be drawn. * @param x The x-coordinate of the start of left edge of the text block. * @param y The y-coordinate of the baseline of the text. * @see #drawString(java.lang.String, int, int) */ public void drawStringBaseline(String str, int x, int y) { drawString(str, x, y - current.getAscent()); } /** * Draws a string using baseline coordinates. * * @param str The string to be drawn. * @param x The x-coordinate of the start of left edge of the text block. * @param y The y-coordinate of the baseline of the text. * @param textDecoration Text decoration bitmask (See Style's TEXT_DECORATION_* constants) * @see #drawString(java.lang.String, int, int, int) */ public void drawStringBaseline(String str, int x, int y, int textDecoration) { drawString(str, x, y - current.getAscent(), textDecoration); } /** * 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); } } // -------------------------------------------------------------------------- // START SHAPE DRAWING STUFF // -------------------------------------------------------------------------- /** * Draws a outline shape inside the specified bounding box. The bounding box will resize the shape * to fit in its dimensions. * * <p>This is not supported on all platforms and contexts currently. Use {@link #isShapeSupported} * to check if the current context supports drawing shapes. * * @param shape The shape to be drawn. * @see #setStroke * @see #isShapeSupported */ public void drawShape(Shape shape, Stroke stroke) { if (isShapeSupported()) { if (xTranslate != 0 || yTranslate != 0) { GeneralPath p = new GeneralPath(); Transform t = Transform.makeTranslation(xTranslate, yTranslate, 0); p.append(shape.getPathIterator(t), true); shape = p; } impl.drawShape(nativeGraphics, shape, stroke); } } /** * Fills the given shape using the current alpha and color settings. * * <p>This is not supported on all platforms and contexts currently. Use {@link #isShapeSupported} * to check if the current context supports drawing shapes. * * @param shape The shape to be filled. * @see #isShapeSupported */ public void fillShape(Shape shape) { if (isShapeSupported()) { if (xTranslate != 0 || yTranslate != 0) { GeneralPath p = new GeneralPath(); Transform t = Transform.makeTranslation(xTranslate, yTranslate, 0); p.append(shape.getPathIterator(t), true); shape = p; } impl.fillShape(nativeGraphics, shape); } } /** * Checks to see if {@link com.codename1.ui.geom.Matrix} transforms are supported by this graphics * context. * * @return {@literal true} if this graphics context supports {@link com.codename1.ui.geom.Matrix} * transforms. * <p>Note that this method only confirms that 2D transforms are supported. If you need to * perform 3D transformations, you should use the {@link #isPerspectiveTransformSupported} * method. * @see #setTransform * @see #getTransform * @see #isPerspectiveTransformSupported */ public boolean isTransformSupported() { return impl.isTransformSupported(nativeGraphics); } /** * Checks to see if perspective (3D) {@link com.codename1.ui.geom.Matrix} transforms are supported * by this graphics context. If 3D transforms are supported, you can use a 4x4 transformation * {@link com.codename1.ui.geom.Matrix} via {@link #setTransform} to perform 3D transforms. * * <p>Note: It is possible for 3D transforms to not be supported but Affine (2D) transforms to be * supported. In this case you would be limited to a 3x3 transformation matrix in {@link * #setTransform}. You can check for 2D transformation support using the {@link * #isTransformSupported} method. * * @return {@literal true} if Perspective (3D) transforms are supported. {@literal false} * otherwise. * @see #isTransformSupported * @see #setTransform * @see #getTransform */ public boolean isPerspectiveTransformSupported() { return impl.isPerspectiveTransformSupported(nativeGraphics); } /** * Checks to see if this graphics context supports drawing shapes (i.e. {@link #drawShape} and * {@link #fillShape} methods. If this returns {@literal false}, and you call {@link #drawShape} * or {@link #fillShape}, then nothing will be drawn. * * @return {@literal true} If {@link #drawShape} and {@link #fillShape} are supported. * @see #drawShape * @see #fillShape */ public boolean isShapeSupported() { return impl.isShapeSupported(nativeGraphics); } /** * Sets the transformation {@link com.codename1.ui.geom.Matrix} to apply to drawing in this * graphics context. In order to use this for 2D/Affine transformations you should first check to * make sure that transforms are supported by calling the {@link #isTransformSupported} method. * For 3D/Perspective transformations, you should first check to make sure that 3D/Perspective * transformations are supported by calling the {@link #isPerspectiveTransformSupported}. * * <p>Transformations are applied with {@literal (0,0)} as the origin. So rotations and scales are * anchored at this point on the screen. You can use a different anchor point by either embedding * it in the transformation matrix (i.e. pre-transform the {@link com.codename1.ui.geom.Matrix} to * anchor at a different point) or use the {@link * #setTransform(com.codename1.ui.geom.Matrix,int,int)} variation that allows you to explicitly * set the anchor point. * * @param transform The transformation {@link com.codename1.ui.geom.Matrix} to use for drawing. * 2D/Affine transformations can be achieved using a 3x3 transformation {@link * com.codename1.ui.geom.Matrix}. 3D/Perspective transformations can be achieved using a 4x3 * transformation {@link com.codename1.ui.geom.Matrix}. * @see #isTransformSupported * @see #isPerspectiveTransformSupported * @see #setTransform(com.codename1.ui.geom.Matrix,int,int) */ public void setTransform(Transform transform) { impl.setTransform(nativeGraphics, transform); } /** * Gets the transformation matrix that is currently applied to this graphics context. * * @return The current transformation matrix. * @see #setTransform */ public Transform getTransform() { return impl.getTransform(nativeGraphics); } // -------------------------------------------------------------------------- // END SHAPE DRAWING METHODS // -------------------------------------------------------------------------- /** * 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 square 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) { // people do that a lot sadly... if (startColor == endColor) { setColor(startColor); fillRect(x, y, width, height, (byte) 0xff); return; } 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) { // people do that a lot sadly... if (startColor == endColor) { setColor(startColor); fillRect(x, y, width, height, (byte) 0xff); return; } 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) { impl.fillRect(nativeGraphics, x, y, w, h, alpha); } /** * 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); scaleX = 1; scaleY = 1; } /** * 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); scaleX = x; scaleY = 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); } /** * Rotates the coordinate system around a radian angle using the affine transform * * @param angle the rotation angle in radians * @param pivotX the pivot point * @param pivotY the pivot point */ public void rotate(float angle, int pivotX, int pivotY) { impl.rotate(nativeGraphics, angle, pivotX, pivotY); } /** * 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 * Codename One 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 Codename One'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; } /** * Allows an implementation to optimize image tiling rendering logic * * @param img the image * @param x coordinate to tile the image along * @param y coordinate to tile the image along * @param w coordinate to tile the image along * @param h coordinate to tile the image along */ public void tileImage(Image img, int x, int y, int w, int h) { impl.tileImage(nativeGraphics, img.getImage(), x + xTranslate, y + yTranslate, w, h); } /** * Returns the affine X scale * * @return the current scale */ public float getScaleX() { return scaleX; } /** * Returns the affine Y scale * * @return the current scale */ public float getScaleY() { return scaleY; } }