LWUITImplementation.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:82k
- /*
- * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
- package com.sun.lwuit.impl;
- import com.sun.lwuit.*;
- import com.sun.lwuit.animations.Animation;
- import com.sun.lwuit.geom.Dimension;
- import com.sun.lwuit.geom.Rectangle;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.WeakReference;
- import java.util.Enumeration;
- import java.util.Hashtable;
- /**
- * Represents a vendor extension mechanizm for LWUIT, <b>WARNING: this class is for internal
- * use only and is subject to change in future API revisions</b>. To replace the way in which
- * LWUIT performs its task this class can be extended and its functionality replaced or
- * enhanced.
- * <p>It is the responsibility of the implementation class to grab and fire all events to the
- * Display specifically for key, pointer events and screen resolution.
- *
- * @author Shai Almog
- */
- public abstract class LWUITImplementation {
- /**
- * Indicates the range of "hard" RTL bidi characters in unicode
- */
- private static final char RTL_RANGE_BEGIN = 0x590;
- private static final char RTL_RANGE_END = 0x7BF;
- private Hashtable linearGradientCache;
- private Hashtable radialGradientCache;
- private int dragActivationCounter = 0;
- private int dragActivationX = 0;
- private int dragActivationY = 0;
- private int dragStartPercentage = 3;
- private Form currentForm;
- private static Object displayLock;
- private Animation[] paintQueue = new Animation[50];
- private Animation[] paintQueueTemp = new Animation[50];
- private int paintQueueFill = 0;
- private Graphics lwuitGraphics;
- private boolean bidi;
- /**
- * Useful since the content of a single element touch event is often recycled
- * and always arrives on 1 thread. Even on multi-tocuh devices a single coordinate
- * touch event should be very efficient
- */
- private int[] xPointerEvent = new int[1];
- /**
- * Useful since the content of a single element touch event is often recycled
- * and always arrives on 1 thread. Even on multi-tocuh devices a single coordinate
- * touch event should be very efficient
- */
- private int[] yPointerEvent = new int[1];
- private int pointerPressedX;
- private int pointerPressedY;
-
- /**
- * Invoked by the display init method allowing the implementation to "bind"
- *
- * @param m the object passed to the Display init method
- */
- public abstract void init(Object m);
- /**
- * Invoked when a dialog is shown, this method allows a dialog to play a sound
- *
- * @param type the type of the dialog matching the dialog classes defined types
- */
- public void playDialogSound(final int type) {
- }
- /**
- * Vibrates the device for the given length of time
- *
- * @param duration length of time to vibrate
- */
- public void vibrate(int duration) {
- }
- /**
- * Flash the backlight of the device for the given length of time
- *
- * @param duration length of time to flash the backlight
- */
- public void flashBacklight(int duration) {
- }
- /**
- * Returns the width dimention of the display controlled by this implementation
- *
- * @return the width
- */
- public abstract int getDisplayWidth();
- /**
- * Returns the height dimention of the display controlled by this implementation
- *
- * @return the height
- */
- public abstract int getDisplayHeight();
- /**
- * Invoked when an exception occurs on the EDT, allows the implementation to
- * take control of the device to produce testing information.
- *
- * @param err the exception that was caught in the EDT loop
- * @return false by default, true if the exception shouldn't be handled further
- * by the EDT
- */
- public boolean handleEDTException(Throwable err) {
- return false;
- }
- /**
- * Encapsulates the editing code which is specific to the platform, some platforms
- * would allow "in place editing" MIDP does not.
- *
- * @param cmp the {@link TextArea} component
- * @param maxSize the maximum size from the text area
- * @param constraint the constraints of the text area
- * @param text the string to edit
- */
- public abstract void editString(Component cmp, int maxSize, int constraint, String text);
- /**
- * Invoked if LWUIT needs to dispose the native text editing but would like the editor
- * to store its state.
- */
- public void saveTextEditingState() {
- }
- /**
- * Returns true if the implementation still has elements to paint.
- *
- * @return false by default
- */
- public boolean hasPendingPaints() {
- return paintQueueFill != 0;
- }
- /**
- * Returns the video control for the media player
- *
- * @param player the media player
- * @return the video control for the media player
- */
- public Object getVideoControl(Object player) {
- return null;
- }
- /**
- * Return the number of alpha levels supported by the implementation.
- *
- * @return the number of alpha levels supported by the implementation
- */
- public int numAlphaLevels() {
- return 255;
- }
- /**
- * Returns the number of colors applicable on the device, note that the API
- * does not support gray scale devices.
- *
- * @return the number of colors applicable on the device
- */
- public int numColors() {
- return 65536;
- }
- /**
- * Allows for painting an overlay on top of the implementation for notices during
- * testing etc.
- *
- * @param g graphics context on which to draw the overlay
- */
- protected void paintOverlay(Graphics g) {
- }
- /**
- * Invoked by the EDT to paint the dirty regions
- */
- public void paintDirty() {
- int size = 0;
- synchronized (displayLock) {
- size = paintQueueFill;
- Animation[] array = paintQueue;
- paintQueue = paintQueueTemp;
- paintQueueTemp = array;
- paintQueueFill = 0;
- }
- if (size > 0) {
- Graphics wrapper = getLWUITGraphics();
- int topX = getDisplayWidth();
- int topY = getDisplayHeight();
- int bottomX = 0;
- int bottomY = 0;
- for (int iter = 0; iter < size; iter++) {
- Animation ani = paintQueueTemp[iter];
- paintQueueTemp[iter] = null;
- wrapper.translate(-wrapper.getTranslateX(), -wrapper.getTranslateY());
- wrapper.setClip(0, 0, getDisplayWidth(), getDisplayHeight());
- if (ani instanceof Component) {
- Component cmp = (Component) ani;
- Rectangle dirty = cmp.getDirtyRegion();
- if (dirty != null) {
- wrapper.setClip(dirty.getX(), dirty.getY(), dirty.getSize().getWidth(), dirty.getSize().getHeight());
- cmp.setDirtyRegion(null);
- }
- cmp.paintComponent(wrapper);
- int cmpAbsX = cmp.getAbsoluteX() + cmp.getScrollX();
- topX = Math.min(cmpAbsX, topX);
- bottomX = Math.max(cmpAbsX + cmp.getWidth(), bottomX);
- int cmpAbsY = cmp.getAbsoluteY() + cmp.getScrollY();
- topY = Math.min(cmpAbsY, topY);
- bottomY = Math.max(cmpAbsY + cmp.getHeight(), bottomY);
- } else {
- bottomX = getDisplayWidth();
- bottomY = getDisplayHeight();
- topX = 0;
- topY = 0;
- ani.paint(wrapper);
- }
- }
- paintOverlay(wrapper);
- flushGraphics(topX, topY, bottomX - topX, bottomY - topY);
- }
- }
- /**
- * This method is a callback from the edt before the edt enters to an idle
- * state
- * @param enter true before the edt sleeps and false when exits from the
- * idle state
- */
- public void edtIdle(boolean enter){
- }
-
- /**
- * Flush the currently painted drawing onto the screen if using a double buffer
- *
- * @param x position of the dirty region
- * @param y position of the dirty region
- * @param width width of the dirty region
- * @param height height of the dirty region
- */
- public abstract void flushGraphics(int x, int y, int width, int height);
- /**
- * Flush the currently painted drawing onto the screen if using a double buffer
- */
- public abstract void flushGraphics();
- /**
- * Returns a graphics object for use by the painting
- *
- * @return a graphics object, either recycled or new, this object will be
- * used on the EDT
- */
- protected Graphics getLWUITGraphics() {
- return lwuitGraphics;
- }
- /**
- * Installs the LWUIT graphics object into the implementation
- *
- * @param g graphics object for use by the implementation
- */
- public void setLWUITGraphics(Graphics g) {
- lwuitGraphics = g;
- }
- /**
- * Installs the display lock allowing implementors to synchronize against the
- * Display mutex, this method is invoked internally and should not be used.
- *
- * @param lock the mutex from display
- */
- public void setDisplayLock(Object lock) {
- displayLock = lock;
- }
- /**
- * Returns a lock object which can be synchrnoized against, this lock is used
- * by the EDT.
- *
- * @return a lock object
- */
- public Object getDisplayLock() {
- return displayLock;
- }
- /**
- * Invoked to add an element to the paintQueue
- *
- * @param cmp component or animation to push into the paint queue
- */
- public void repaint(Animation cmp) {
- synchronized (displayLock) {
- for (int iter = 0; iter < paintQueueFill; iter++) {
- Animation ani = paintQueue[iter];
- if (ani == cmp) {
- return;
- }
- }
- // overcrowding the queue don't try to grow the array!
- if (paintQueueFill >= paintQueue.length) {
- System.out.println("Warning paint queue size exceeded, please watch the amount of repaint calls");
- return;
- }
- paintQueue[paintQueueFill] = cmp;
- paintQueueFill++;
- displayLock.notify();
- }
- }
- /**
- * Extracts RGB data from the given native image and places it in the given array
- *
- * @param nativeImage native platform image object
- * @param arr int array to store RGB data
- * @param offset position within the array to start
- * @param x x position within the image
- * @param y y position within the image
- * @param width width to extract
- * @param height height to extract
- */
- public abstract void getRGB(Object nativeImage, int[] arr, int offset, int x, int y, int width, int height);
- /**
- * Create a platform native image object from the given RGB data
- *
- * @param rgb ARGB data from which to create a platform image
- * @param width width for the resulting image
- * @param height height for the resulting image
- * @return platform image object
- */
- public abstract Object createImage(int[] rgb, int width, int height);
- /**
- * Creates a native image from a file in the system jar
- *
- * @param path within the jar
- * @return native system image
- * @throws java.io.IOException if thrown by loading
- */
- public abstract Object createImage(String path) throws IOException;
- /**
- * Creates a native image from a given input stream
- *
- * @param i input stream from which to load the image
- * @return native system image
- * @throws java.io.IOException if thrown by loading
- */
- public abstract Object createImage(InputStream i) throws IOException;
- /**
- * Creates a modifable native image that can return a graphics object
- *
- * @param width the width of the mutable image
- * @param height the height of the mutable image
- * @param fillColor the ARGB fill color, alpha may be ignored based on the value of
- * isAlphaMutableImageSupported
- * @return the native image
- */
- public abstract Object createMutableImage(int width, int height, int fillColor);
- /**
- * Indicates whether mutable images respect alpha values when constructed
- *
- * @return true if mutable images can have an alpha value when initially created
- */
- public boolean isAlphaMutableImageSupported() {
- return false;
- }
- /**
- * Create a nativate image from its compressed byte data
- *
- * @param bytes the byte array representing the image data
- * @param offset offset within the byte array
- * @param len the length for the image within the byte array
- * @return a native image
- */
- public abstract Object createImage(byte[] bytes, int offset, int len);
- /**
- * Returns the width of a native image
- *
- * @param i the native image
- * @return the width of the native image
- */
- public abstract int getImageWidth(Object i);
- /**
- * Returns the height of a native image
- *
- * @param i the native image
- * @return the height of the native image
- */
- public abstract int getImageHeight(Object i);
- /**
- * Scales a native image and returns the scaled version
- *
- * @param nativeImage image to scale
- * @param width width of the resulting image
- * @param height height of the resulting image
- * @return scaled image instance
- */
- public abstract Object scale(Object nativeImage, int width, int height);
- private static int round(double d) {
- double f = Math.floor(d);
- double c = Math.ceil(d);
- if (c - d < d - f) {
- return (int) c;
- }
- return (int) f;
- }
- /**
- * Returns an instance of this image rotated by the given number of degrees. By default 90 degree
- * angle divisions are supported, anything else is implementation dependent. This method assumes
- * a square image. Notice that it is inefficient in the current implementation to rotate to
- * non-square angles,
- * <p>E.g. rotating an image to 45, 90 and 135 degrees is inefficient. Use rotatate to 45, 90
- * and then rotate the 45 to another 90 degrees to achieve the same effect with less memory.
- *
- * @param degrees A degree in right angle must be larger than 0 and up to 359 degrees
- * @return new image instance with the closest possible rotation
- */
- public Object rotate(Object image, int degrees) {
- int width = getImageWidth(image);
- int height = getImageHeight(image);
- int[] arr = new int[width * height];
- int[] dest = new int[arr.length];
- getRGB(image, arr, 0, 0, 0, width, height);
- int centerX = width / 2;
- int centerY = height / 2;
- double radians = Math.toRadians(-degrees);
- double cosDeg = Math.cos(radians);
- double sinDeg = Math.sin(radians);
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- int x2 = round(cosDeg * (x - centerX) - sinDeg * (y - centerY) + centerX);
- int y2 = round(sinDeg * (x - centerX) + cosDeg * (y - centerY) + centerY);
- if (!(x2 < 0 || y2 < 0 || x2 >= width || y2 >= height)) {
- int destOffset = x2 + y2 * width;
- if (destOffset >= 0 && destOffset < dest.length) {
- dest[x + y * width] = arr[destOffset];
- }
- }
- }
- }
- return createImage(dest, width, height);
- }
- /**
- * Returns the number of softkeys on the device
- *
- * @return the number of softkey buttons on the device
- */
- public abstract int getSoftkeyCount();
- /**
- * Returns the softkey keycode for the given softkey index
- *
- * @param index the index of the softkey
- * @return the set of keycodes which can indicate the softkey, multiple keycodes
- * might apply to the same functionality
- */
- public abstract int[] getSoftkeyCode(int index);
- /**
- * Returns the keycode for the clear key
- *
- * @return the system key code for this device
- */
- public abstract int getClearKeyCode();
- /**
- * Returns the keycode for the backspace key
- *
- * @return the system key code for this device
- */
- public abstract int getBackspaceKeyCode();
- /**
- * Returns the keycode for the back key
- *
- * @return the system key code for this device
- */
- public abstract int getBackKeyCode();
- /**
- * Returns the display game action for the given keyCode if applicable to match
- * the contrct of LWUIT for the game action behavior
- *
- * @param keyCode the device keycode
- * @return a game action or 0
- */
- public abstract int getGameAction(int keyCode);
- /**
- * Returns a keycode which can be sent to getGameAction
- *
- * @param gameAction the game action
- * @return key code matching the given game action
- */
- public abstract int getKeyCode(int gameAction);
- /**
- * Returns true if the device will send touch events
- *
- * @return true if the device will send touch events
- */
- public abstract boolean isTouchDevice();
- /**
- * This method is used internally to determine the actual current form
- * it doesn't perform the logic of transitions etc. and shouldn't be invoked
- * by developers
- *
- * @param f the current form
- */
- public void setCurrentForm(Form f) {
- currentForm = f;
- }
- /**
- * Callback method allowing the implementation to confirm that it controls the
- * view just before a new form is installed.
- */
- public void confirmControlView() {
- }
- /**
- * Returns the current form, this method is for internal use only and does not
- * take transitions/menus into consideration
- *
- * @return The internal current form
- */
- public Form getCurrentForm() {
- return currentForm;
- }
- /**
- * LWUIT can translate all coordinates and never requires a call to translate
- * this works well for some devices which have hairy issues with translate.
- * However for some platforms where translate can be leveraged with affine transforms
- * this can be a problem. These platforms can choose to translate on their own
- *
- * @return true if the implementation is interested in receiving translate calls
- * and handling them.
- */
- public boolean isTranslationSupported() {
- return false;
- }
- /**
- * 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 graphics the graphics context
- * @param x the x coordinate
- * @param y the y coordinate
- */
- public void translate(Object graphics, int x, int y) {
- }
- /**
- * Returns the current x translate value
- *
- * @param graphics the graphics context
- * @return the current x translate value
- */
- public int getTranslateX(Object graphics) {
- return 0;
- }
- /**
- * Returns the current y translate value
- *
- * @param graphics the graphics context
- * @return the current y translate value
- */
- public int getTranslateY(Object graphics) {
- return 0;
- }
- /**
- * Returns the current color
- *
- * @param graphics the graphics context
- * @return the RGB graphics color
- */
- public abstract int getColor(Object graphics);
- /**
- * Sets the current rgb color while ignoring any potential alpha component within
- * said color value.
- *
- * @param graphics the graphics context
- * @param RGB the RGB value for the color.
- */
- public abstract void setColor(Object graphics, int RGB);
- /**
- * Alpha value from 0-255 can be ignored for some operations
- *
- * @param graphics the graphics context
- * @param alpha the alpha channel
- */
- public abstract void setAlpha(Object graphics, int alpha);
- /**
- * Alpha value from 0-255 can be ignored for some operations
- *
- * @param graphics the graphics context
- * @return the alpha channel
- */
- public abstract int getAlpha(Object graphics);
- /**
- * Returns true if alpha can be applied for all elements globally and efficiently
- * otherwise alpha should be ignored.
- * Notice that fillRect MUST always support alpha regardless of the value of this
- * variable!
- *
- * @return true if alpha support is natively implemented
- */
- public boolean isAlphaGlobal() {
- return false;
- }
- /**
- * Indicates whether the underlying implementation allows for anti-aliasing in regular
- * drawing operations
- *
- * @return false by default
- */
- public boolean isAntiAliasingSupported() {
- return false;
- }
- /**
- * Indicates whether the underlying implementation allows for anti-aliased fonts
- *
- * @return false by default
- */
- public boolean isAntiAliasedTextSupported() {
- return false;
- }
- /**
- * Toggles anti-aliasing mode for regular rendering operations
- *
- * @param graphics the graphics context
- * @param a true to activate Anti-aliasing, false to disable it
- */
- public void setAntiAliased(Object graphics, boolean a) {
- }
- /**
- * Returns anti-aliasing mode for regular rendering operations
- *
- * @param graphics the graphics context
- * @return true if Anti-aliasing is active, false otherwise
- */
- public boolean isAntiAliased(Object graphics) {
- return false;
- }
- /**
- * Toggles anti-aliasing mode for font rendering operations
- *
- * @param graphics the graphics context
- * @param a true to activate Anti-aliasing, false to disable it
- */
- public void setAntiAliasedText(Object graphics, boolean a) {
- }
- /**
- * Returns anti-aliasing mode for font rendering operations
- *
- * @param graphics the graphics context
- * @return true if Anti-aliasing is active, false otherwise
- */
- public boolean isAntiAliasedText(Object graphics) {
- return false;
- }
- /**
- * Installs a native font object
- *
- * @param graphics the graphics context
- * @param font the native font object
- */
- public abstract void setNativeFont(Object graphics, Object font);
- /**
- * Returns the internal clipping rectangle. This method must create a new
- * rectangle object to prevent corruption by modification.
- *
- * @param graphics the graphics context
- * @return the clipping rectangle.
- */
- public Rectangle getClipRect(Object graphics) {
- return new Rectangle(getClipX(graphics), getClipY(graphics), new Dimension(getClipWidth(graphics), getClipHeight(graphics)));
- }
- /**
- * Returns the clipping coordinate
- *
- * @param graphics the graphics context
- * @return the clipping coordinate
- */
- public abstract int getClipX(Object graphics);
- /**
- * Returns the clipping coordinate
- *
- * @param graphics the graphics context
- * @return the clipping coordinate
- */
- public abstract int getClipY(Object graphics);
- /**
- * Returns the clipping coordinate
- *
- * @param graphics the graphics context
- * @return the clipping coordinate
- */
- public abstract int getClipWidth(Object graphics);
- /**
- * Returns the clipping coordinate
- *
- * @param graphics the graphics context
- * @return the clipping coordinate
- */
- public abstract int getClipHeight(Object graphics);
- /**
- * Installs a new clipping rectangle
- *
- * @param graphics the graphics context
- * @param rect rectangle representing the new clipping area
- */
- public void setClipRect(Object graphics, Rectangle rect) {
- Dimension d = rect.getSize();
- setClip(graphics, rect.getX(), rect.getY(), d.getWidth(), d.getHeight());
- }
- /**
- * Installs a new clipping rectangle
- *
- * @param graphics the graphics context
- * @param x coordinate
- * @param y coordinate
- * @param width size
- * @param height size
- * @param rect rectangle representing the new clipping area
- */
- public abstract void setClip(Object graphics, int x, int y, int width, int height);
- /**
- * Changes the current clipping rectangle to subset the current clipping with
- * the given clipping.
- *
- * @param graphics the graphics context
- * @param rect rectangle representing the new clipping area
- */
- public void clipRect(Object graphics, Rectangle rect) {
- Dimension d = rect.getSize();
- clipRect(graphics, rect.getX(), rect.getY(), d.getWidth(), d.getHeight());
- }
- /**
- * Changes the current clipping rectangle to subset the current clipping with
- * the given clipping.
- *
- * @param graphics the graphics context
- * @param x coordinate
- * @param y coordinate
- * @param width size
- * @param height size
- * @param rect rectangle representing the new clipping area
- */
- public abstract void clipRect(Object graphics, int x, int y, int width, int height);
- /**
- * Draws a line between the 2 X/Y coordinates
- *
- * @param graphics the graphics context
- * @param x1 first x position
- * @param y1 first y position
- * @param x2 second x position
- * @param y2 second y position
- */
- public abstract void drawLine(Object graphics, int x1, int y1, int x2, int y2);
- /**
- * Fills the rectangle from the given position according to the width/height
- * minus 1 pixel according to the convention in Java.
- *
- * @param graphics the graphics context
- * @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 abstract void fillRect(Object graphics, int x, int y, int width, int height);
- /**
- * Draws a rectangle in the given coordinates
- *
- * @param graphics the graphics context
- * @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 abstract void drawRect(Object graphics, int x, int y, int width, int height);
- /**
- * Draws a rounded corner rectangle in the given coordinates with the arcWidth/height
- * matching the last two arguments respectively.
- *
- * @param graphics the graphics context
- * @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 abstract void drawRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight);
- /**
- * Fills a rounded rectangle in the same way as drawRoundRect
- *
- * @param graphics the graphics context
- * @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 abstract void fillRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int 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 graphics the graphics context
- * @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 abstract void fillArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle);
- /**
- * Draws a circular or elliptical arc based on the given angles and bounding
- * box
- *
- * @param graphics the graphics context
- * @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 abstract void drawArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle);
- /**
- * 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 graphics the graphics context
- * @param str the string to be drawn.
- * @param x the x coordinate.
- * @param y the y coordinate.
- */
- public abstract void drawString(Object graphics, String str, int x, int y);
- /**
- * Draws the image so its top left coordinate corresponds to x/y
- *
- * @param graphics the graphics context
- * @param img the specified native image to be drawn
- * @param x the x coordinate.
- * @param y the y coordinate.
- */
- public abstract void drawImage(Object graphics, Object img, int x, int y);
- /**
- * Draws a portion of the image
- *
- * @param nativeGraphics the graphics context
- * @param img the specified native image to be drawn
- * @param x the x coordinate.
- * @param y the y coordinate.
- * @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
- */
- public void drawImageArea(Object nativeGraphics, Object img, int x, int y, int imageX, int imageY, int imageWidth, int imageHeight) {
- int clipX = getClipX(nativeGraphics);
- int clipY = getClipY(nativeGraphics);
- int clipWidth = getClipWidth(nativeGraphics);
- int clipHeight = getClipHeight(nativeGraphics);
- clipRect(nativeGraphics, x, y, imageWidth, imageHeight);
- if (getClipWidth(nativeGraphics) > 0 && getClipHeight(nativeGraphics) > 0) {
- drawImage(nativeGraphics, img, x - imageX, y - imageY);
- }
- setClip(nativeGraphics, clipX, clipY, clipWidth, clipHeight);
- }
- /**
- * Draws the image so its top left coordinate corresponds to x/y with a fast
- * native rotation in a square angle which must be one of 0, 90, 180 or 270
- *
- * @param graphics the graphics context
- * @param img the specified native image to be drawn
- * @param x the x coordinate.
- * @param y the y coordinate.
- * @param degrees either 0, 90, 180 or 270 degree rotation for the image drawing
- */
- public void drawImageRotated(Object graphics, Object img, int x, int y, int degrees) {
- }
- /**
- * Indicates whether drawImageRotated is supported by the platform for FAST drawing,
- * if not then its not worth calling the method which will be unimplemented!
- *
- * @return true if drawImageRotated will draw an image
- */
- public boolean isRotationDrawingSupported() {
- return false;
- }
- /**
- * Draws a filled triangle with the given coordinates
- *
- * @param graphics the graphics context
- * @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(Object graphics, int x1, int y1, int x2, int y2, int x3, int y3) {
- fillPolygon(graphics, new int[]{x1, x2, x3}, new int[]{y1, y2, y3}, 3);
- }
- /**
- * 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 graphics the graphics context
- * @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
- */
- public abstract void drawRGB(Object graphics, int[] rgbData, int offset, int x, int y, int w, int h, boolean processAlpha);
- /**
- * Returns the native graphics object on which all rendering operations occur
- *
- * @return a native graphics context
- */
- public abstract Object getNativeGraphics();
- /**
- * Returns the native graphics object on the given native image occur
- *
- * @param image the native image on which the graphics will draw
- * @return a native graphics context
- */
- public abstract Object getNativeGraphics(Object image);
- /**
- * Return the width of the given characters in the given native font instance
- *
- * @param nativeFont the font for which the string width should be calculated
- * @param ch array of characters
- * @param offset characters offsets
- * @param length characters length
- * @return the width of the given characters in this font instance
- */
- public abstract int charsWidth(Object nativeFont, char[] ch, int offset, int length);
- /**
- * Return the width of the given string in this font instance
- *
- * @param nativeFont the font for which the string width should be calculated
- * @param str the given string *
- * @return the width of the given string in this font instance
- */
- public abstract int stringWidth(Object nativeFont, String str);
- /**
- * Return the width of the specific character when rendered alone
- *
- * @param nativeFont the font for which the string width should be calculated
- * @param ch the specific character
- * @return the width of the specific character when rendered alone
- */
- public abstract int charWidth(Object nativeFont, char ch);
- /**
- * Return the total height of the font
- *
- * @param nativeFont the font for which the string width should be calculated
- * @return the total height of the font
- */
- public abstract int getHeight(Object nativeFont);
- /**
- * Return the global default font instance, if font is passed as null
- * this font should be used
- *
- * @return the global default font instance
- */
- public abstract Object getDefaultFont();
- /**
- * Optional operation returning the font face for the font
- *
- * @param nativeFont the font for which the string width should be calculated
- * @return Optional operation returning the font face for system fonts
- */
- public int getFace(Object nativeFont) {
- return 0;
- }
- /**
- * Optional operation returning the font size for system fonts
- *
- * @param nativeFont the font for which the string width should be calculated
- * @return Optional operation returning the font size for system fonts
- */
- public int getSize(Object nativeFont) {
- return 0;
- }
- /**
- * Optional operation returning the font style for system fonts
- *
- * @param nativeFont the font for which the string width should be calculated
- * @return Optional operation returning the font style for system fonts
- */
- public int getStyle(Object nativeFont) {
- return 0;
- }
- /**
- * Creates a new instance of a native font
- *
- * @param face the face of the font, can be one of FACE_SYSTEM,
- * FACE_PROPORTIONAL, FACE_MONOSPACE.
- * @param style the style of the font.
- * The value is an OR'ed combination of STYLE_BOLD, STYLE_ITALIC, and
- * STYLE_UNDERLINED; or the value is zero (STYLE_PLAIN).
- * @param size the size of the font, can be one of SIZE_SMALL,
- * SIZE_MEDIUM, SIZE_LARGE
- * @return a native font object
- */
- public abstract Object createFont(int face, int style, int size);
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param keyCode the key for the event
- */
- protected void keyPressed(final int keyCode) {
- Display.getInstance().keyPressed(keyCode);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param keyCode the key for the event
- */
- protected void keyReleased(final int keyCode) {
- Display.getInstance().keyReleased(keyCode);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerDragged(final int x, final int y) {
- xPointerEvent[0] = x;
- yPointerEvent[0] = y;
- pointerDragged(xPointerEvent, yPointerEvent);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerPressed(final int x, final int y) {
- xPointerEvent[0] = x;
- yPointerEvent[0] = y;
- pointerPressed(xPointerEvent, yPointerEvent);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerReleased(final int x, final int y) {
- xPointerEvent[0] = x;
- yPointerEvent[0] = y;
- pointerReleased(xPointerEvent, yPointerEvent);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerHover(final int[] x, final int[] y) {
- Display.getInstance().pointerHover(x, y);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerHoverReleased(final int[] x, final int[] y) {
- Display.getInstance().pointerHoverReleased(x, y);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerHoverReleased(final int x, final int y) {
- xPointerEvent[0] = x;
- yPointerEvent[0] = y;
- pointerHoverReleased(xPointerEvent, yPointerEvent);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerHover(final int x, final int y) {
- xPointerEvent[0] = x;
- yPointerEvent[0] = y;
- pointerHover(xPointerEvent, yPointerEvent);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerDragged(final int[] x, final int[] y) {
- if (hasDragStarted(x, y)) {
-
- Display.getInstance().pointerDragged(x, y);
- }
- }
- /**
- * This method can be overriden by subclasses to indicate whether a drag
- * event has started or whether the device is just sending out "noise".
- * This method is invoked by pointer dragged to determine whether to propogate
- * the actual pointer drag event to LWUIT.
- *
- * @param x the position of the current drag event
- * @param y the position of the current drag event
- * @return true if the drag should propogate into LWUIT
- */
- protected boolean hasDragStarted(final int[] x, final int[] y) {
- return hasDragStarted(x[0], y[0]);
- }
- /**
- * This method can be overriden by subclasses to indicate whether a drag
- * event has started or whether the device is just sending out "noise".
- * This method is invoked by pointer dragged to determine whether to propogate
- * the actual pointer drag event to LWUIT.
- *
- * @param x the position of the current drag event
- * @param y the position of the current drag event
- * @return true if the drag should propogate into LWUIT
- */
- protected boolean hasDragStarted(final int x, final int y) {
- if (dragActivationCounter == 0) {
- dragActivationX = x;
- dragActivationY = y;
- dragActivationCounter++;
- return false;
- }
- //send the drag events to the form only after latency of 7 drag events,
- //most touch devices are too sensitive and send too many drag events.
- //7 is just a latency const number that is pretty good for most devices
- //this may be tuned for specific devices.
- dragActivationCounter++;
- if (dragActivationCounter > getDragAutoActivationThreshold()) {
- return true;
- }
- // have we passed the motion threshold on the X axis?
- if (((float) getDisplayWidth()) / 100.0f * ((float) getDragStartPercentage()) <=
- Math.abs(dragActivationX - x)) {
- dragActivationCounter = getDragAutoActivationThreshold() + 1;
- return true;
- }
- // have we passed the motion threshold on the Y axis?
- if (((float) getDisplayHeight()) / 100.0f * ((float) getDragStartPercentage()) <=
- Math.abs(dragActivationY - y)) {
- dragActivationCounter = getDragAutoActivationThreshold() + 1;
- return true;
- }
- return false;
- }
- /**
- * This method allows us to manipulate the drag started detection logic.
- * If the pointer was dragged for more than this percentage of the display size it
- * is safe to assume that a drag is in progress.
- *
- * @return motion percentage
- */
- public int getDragStartPercentage() {
- return dragStartPercentage;
- }
- /**
- * This method allows us to manipulate the drag started detection logic.
- * If the pointer was dragged for more than this percentage of the display size it
- * is safe to assume that a drag is in progress.
- *
- * @param dragStartPercentage percentage of the screen required to initiate drag
- */
- public void setDragStartPercentage(int dragStartPercentage) {
- this.dragStartPercentage = dragStartPercentage;
- }
- /**
- * This method allows subclasses to manipulate the drag started detection logic.
- * If more than this number of drag events were delivered it is safe to assume a drag has started
- * This number must be bigger than 0!
- *
- * @return number representing a minimum number of motion events to start a drag operation
- */
- protected int getDragAutoActivationThreshold() {
- return 7;
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerPressed(final int[] x, final int[] y) {
- pointerPressedX = x[0];
- pointerPressedY = y[0];
- Display.getInstance().pointerPressed(x, y);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param x the position of the event
- * @param y the position of the event
- */
- protected void pointerReleased(final int[] x, final int[] y) {
- // this is a special case designed to detect a "flick" event on some Samsung devices
- // that send a pointerPressed/Released with widely differing X/Y values but don't send
- // the pointerDrag events in between
- if(dragActivationCounter == 0 && x[0] != pointerPressedX && y[0] != pointerPressedY) {
- hasDragStarted(pointerPressedX, pointerPressedY);
- if(hasDragStarted(x, y)) {
- pointerDragged(pointerPressedX, pointerPressedY);
- pointerDragged(x, y);
- }
- }
- dragActivationCounter = 0;
- Display.getInstance().pointerReleased(x, y);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param w the size of the screen
- * @param h the size of the screen
- */
- protected void sizeChanged(int w, int h) {
- Display.getInstance().sizeChanged(w, h);
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param w the size of the screen
- * @param h the size of the screen
- */
- protected void hideNotify() {
- Display.getInstance().hideNotify();
- }
- /**
- * Subclasses should invoke this method, it delegates the event to the display and into
- * LWUIT.
- *
- * @param w the size of the screen
- * @param h the size of the screen
- */
- protected void showNotify() {
- Display.getInstance().showNotify();
- }
- private Object findCachedGradient(Hashtable cache, int startColor, int endColor, int x, int y, int width, int height, boolean horizontal, int centerX, int centerY, int size) {
- if(cache != null) {
- Enumeration e = cache.keys();
- while(e.hasMoreElements()) {
- int[] current = (int[])e.nextElement();
- WeakReference currentRef = (WeakReference)cache.get(current);
- Object currentImage = currentRef.get();
- if(currentImage == null) {
- cache.remove(current);
- e = cache.keys();
- continue;
- }
- if(current[0] == startColor &&
- current[1] == endColor &&
- current[2] == x &&
- current[3] == y &&
- current[5] == centerX &&
- current[6] == centerY &&
- current[7] == size &&
- getImageWidth(currentImage) == width &&
- getImageHeight(currentImage) == height) {
- if((horizontal && current[4] == 1) || ((!horizontal) && current[4] == 0)) {
- return currentImage;
- }
- }
- }
- }
- return null;
- }
- private void storeCachedGradient(Object img, Hashtable cache, int startColor, int endColor, int x, int y, boolean horizontal, int centerX, int centerY, int size) {
- int[] key;
- if(horizontal) {
- key = new int[] {startColor, endColor, x, y, 1, centerX, centerY, size};
- } else {
- key = new int[] {startColor, endColor, x, y, 0, centerX, centerY, size};
- }
- cache.put(key, new WeakReference(img));
- }
- /**
- * 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 graphics the graphics context
- * @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(Object graphics, int startColor, int endColor, int x, int y, int width, int height, float relativeX, float relativeY, float relativeSize) {
- int centerX = (int) (width * (1 - relativeX));
- int centerY = (int) (height * (1 - relativeY));
- int x2 = width / 2 - centerX;
- int y2 = height / 2 - centerY;
- int size = (int)(Math.min(width, height) * relativeSize);
- if(cacheRadialGradients()) {
- Object r = findCachedGradient(radialGradientCache, startColor, endColor, x, y, width, height, true, centerX, centerY, size);
- if(r != null) {
- drawImage(graphics, r, x, y);
- } else {
- r = createMutableImage(width, height, 0xffffffff);
- Object imageGraphics = getNativeGraphics(r);
- setColor(imageGraphics, endColor);
- fillRect(imageGraphics, 0, 0, width, height);
- fillRadialGradientImpl(imageGraphics, startColor, endColor, x2, y2, size, size);
- drawImage(graphics, r, x, y);
- if(radialGradientCache == null) {
- radialGradientCache = new Hashtable();
- }
- storeCachedGradient(r, radialGradientCache, startColor, endColor, x, y, true, centerX, centerY, size);
- }
- } else {
- setColor(graphics, endColor);
- fillRect(graphics, x, y, width, height);
- fillRadialGradientImpl(graphics, startColor, endColor, x + x2, y + y2, size, size);
- }
- }
- /**
- * 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 graphics the graphics context
- * @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(Object graphics, int startColor, int endColor, int x, int y, int width, int height) {
- fillRadialGradientImpl(graphics, startColor, endColor, x, y, width, height);
- }
- private void fillRadialGradientImpl(Object graphics, int startColor, int endColor, int x, int y, int width, int height) {
- int sourceR = startColor >> 16 & 0xff;
- int sourceG = startColor >> 8 & 0xff;
- int sourceB = startColor & 0xff;
- int destR = endColor >> 16 & 0xff;
- int destG = endColor >> 8 & 0xff;
- int destB = endColor & 0xff;
- int oldColor = getColor(graphics);
- int originalHeight = height;
- while (width > 0 && height > 0) {
- updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
- destG, destB, originalHeight, height);
- fillArc(graphics, x, y, width, height, 0, 360);
- x++;
- y++;
- width -= 2;
- height -= 2;
- }
- setColor(graphics, oldColor);
- }
- private void updateGradientColor(Object nativeGraphics, int sourceR, int sourceG, int sourceB, int destR,
- int destG, int destB, int distance, int offset) {
- //int a = calculateGraidentChannel(sourceA, destA, distance, offset);
- int r = calculateGraidentChannel(sourceR, destR, distance, offset);
- int g = calculateGraidentChannel(sourceG, destG, distance, offset);
- int b = calculateGraidentChannel(sourceB, destB, distance, offset);
- int color = /*((a << 24) & 0xff000000) |*/ ((r << 16) & 0xff0000) |
- ((g << 8) & 0xff00) | (b & 0xff);
- setColor(nativeGraphics, color);
- }
- /**
- * Converts the color channel value according to the offest within the distance
- */
- private int calculateGraidentChannel(int sourceChannel, int destChannel, int distance, int offset) {
- if (sourceChannel == destChannel) {
- return sourceChannel;
- }
- float ratio = ((float) offset) / ((float) distance);
- int pos = (int) (Math.abs(sourceChannel - destChannel) * ratio);
- if (sourceChannel > destChannel) {
- return sourceChannel - pos;
- } else {
- return sourceChannel + pos;
- }
- }
- /**
- * Draws a linear gradient in the given coordinates with the given colors,
- * doesn't take alpha into consideration when drawing the gradient
- *
- * @param graphics the graphics context
- * @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(Object graphics, int startColor, int endColor, int x, int y, int width, int height, boolean horizontal) {
- if(cacheLinearGradients()) {
- Object r = findCachedGradient(linearGradientCache, startColor, endColor, x, y, width, height, horizontal, 0, 0, 0);
- if(r != null) {
- drawImage(graphics, r, x, y);
- } else {
- r = createMutableImage(width, height, 0xffffffff);
- fillLinearGradientImpl(getNativeGraphics(r), startColor, endColor, 0, 0, width, height, horizontal);
- drawImage(graphics, r, x, y);
- if(linearGradientCache == null) {
- linearGradientCache = new Hashtable();
- }
- storeCachedGradient(r, linearGradientCache, startColor, endColor, x, y, horizontal, 0, 0, 0);
- }
- } else {
- fillLinearGradientImpl(graphics, startColor, endColor, x, y, width, height, horizontal);
- }
- }
- private void fillLinearGradientImpl(Object graphics, int startColor, int endColor, int x, int y, int width, int height, boolean horizontal) {
- int sourceR = startColor >> 16 & 0xff;
- int sourceG = startColor >> 8 & 0xff;
- int sourceB = startColor & 0xff;
- int destR = endColor >> 16 & 0xff;
- int destG = endColor >> 8 & 0xff;
- int destB = endColor & 0xff;
- int oldColor = getColor(graphics);
- if (horizontal) {
- for (int iter = 0; iter < width; iter++) {
- updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
- destG, destB, width, iter);
- drawLine(graphics, x + iter, y, x + iter, y + height);
- }
- } else {
- for (int iter = 0; iter < height; iter++) {
- updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
- destG, destB, height, iter);
- drawLine(graphics, x, y + iter, x + width, y + iter);
- }
- }
- setColor(graphics, oldColor);
- }
- private boolean checkIntersection(Object g, int y0, int x1, int x2, int y1, int y2, int[] intersections, int intersectionsCount) {
- if (y0 > y1 && y0 < y2 || y0 > y2 && y0 < y1) {
- if (y1 == y2) {
- drawLine(g, x1, y0, x2, y0);
- return false;
- }
- intersections[intersectionsCount] = x1 + ((y0 - y1) * (x2 - x1)) / (y2 - y1);
- return true;
- }
- return false;
- }
- private int markIntersectionEdge(Object g, int idx, int[] yPoints, int[] xPoints, int nPoints, int[] intersections, int intersectionsCount) {
- intersections[intersectionsCount] = xPoints[idx];
- if ((yPoints[idx] - yPoints[(idx + 1) % nPoints]) * (yPoints[idx] - yPoints[(idx + nPoints - 1) % nPoints]) > 0) {
- intersections[intersectionsCount + 1] = xPoints[idx];
- return 2;
- }
- //Check for special case horizontal line
- if (yPoints[idx] == yPoints[(idx + 1) % nPoints]) {
- drawLine(g, xPoints[idx], yPoints[idx], xPoints[(idx + 1) % nPoints], yPoints[(idx + 1) % nPoints]);
- if ((yPoints[(idx + 1) % nPoints] - yPoints[(idx + 2) % nPoints]) * (yPoints[idx] - yPoints[(idx + nPoints - 1) % nPoints]) > 0) {
- return 1;
- } else {
- intersections[intersectionsCount + 1] = xPoints[idx];
- return 2;
- }
- }
- return 1;
- }
- /**
- * Fills a closed polygon defined by arrays of x and y coordinates.
- * Each pair of (x, y) coordinates defines a point.
- *
- * @param graphics the graphics context
- * @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(Object graphics, int[] xPoints, int[] yPoints, int nPoints) {
- int[] intersections = new int[nPoints];
- int intersectionsCount = 0;
- int yMax = (int) yPoints[0];
- int yMin = (int) yPoints[0];
- for (int i = 0; i < nPoints; i++) {
- yMax = Math.max(yMax, yPoints[i]);
- yMin = Math.min(yMin, yPoints[i]);
- }
- // Loop through the rows of the image.
- for (int row = yMin; row <= yMax; row++) {
- intersectionsCount = 0;
- for (int i = 1; i < nPoints; i++) {
- if (checkIntersection(graphics, row, xPoints[i - 1], xPoints[i], yPoints[i - 1], yPoints[i], intersections, intersectionsCount)) {
- intersectionsCount++;
- }
- }
- if (checkIntersection(graphics, row, xPoints[nPoints - 1], xPoints[0], yPoints[nPoints - 1], yPoints[0], intersections, intersectionsCount)) {
- intersectionsCount++;
- }
- for (int j = 0; j < nPoints; j++) {
- if (row == yPoints[j]) {
- intersectionsCount += markIntersectionEdge(graphics, j, yPoints, xPoints, nPoints, intersections, intersectionsCount);
- }
- }
- int swap = 0;
- for (int i = 0; i < intersectionsCount; i++) {
- for (int j = i; j < intersectionsCount; j++) {
- if (intersections[j] < intersections[i]) {
- swap = intersections[i];
- intersections[i] = intersections[j];
- intersections[j] = swap;
- }
- }
- }
- for (int i = 1; i < intersectionsCount; i = i + 2) {
- drawLine(graphics, intersections[i - 1], row, intersections[i], row);
- }
- }
- }
- /**
- * Draws a closed polygon defined by arrays of x and y coordinates.
- * Each pair of (x, y) coordinates defines a point.
- *
- * @param graphics the graphics context
- * @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(Object graphics, int[] xPoints, int[] yPoints, int nPoints) {
- for (int i = 1; i < nPoints; i++) {
- drawLine(graphics, xPoints[i - 1], yPoints[i - 1], xPoints[i], yPoints[i]);
- }
- drawLine(graphics, xPoints[nPoints - 1], yPoints[nPoints - 1], xPoints[0], yPoints[0]);
- }
- /**
- * Displays the virtual keyboard on devices that support manually poping up
- * the vitual keyboard
- *
- * @param show toggles the virtual keyboards visibility
- */
- public void setShowVirtualKeyboard(boolean show) {
- }
- /**
- * Indicates if the virtual keyboard is currently showing or not
- *
- * @return true if the virtual keyboard is showing
- */
- public boolean isVirtualKeyboardShowing() {
- return false;
- }
- /**
- * Indicates whether showing a virtual keyboard programmatically is supported
- *
- * @return false by default
- */
- public boolean isVirtualKeyboardShowingSupported() {
- return false;
- }
- /**
- * Returns the type of the input device one of:
- * KEYBOARD_TYPE_UNKNOWN, KEYBOARD_TYPE_NUMERIC, KEYBOARD_TYPE_QWERTY,
- * KEYBOARD_TYPE_VIRTUAL, KEYBOARD_TYPE_HALF_QWERTY
- *
- * @return KEYBOARD_TYPE_UNKNOWN
- */
- public int getKeyboardType() {
- return Display.KEYBOARD_TYPE_UNKNOWN;
- }
- /**
- * Indicates whether the device supports native in place editing in which case
- * lightweight input logic shouldn't be used for input.
- *
- * @return false by default
- */
- public boolean isNativeInputSupported() {
- return false;
- }
- /**
- * Indicates whether the device supports multi-touch events, this is only
- * relevant when touch events are supported
- *
- * @return false by default
- */
- public boolean isMultiTouch() {
- return false;
- }
- /**
- * Indicates whether the device has a double layer screen thus allowing two
- * stages to touch events: click and hover. This is true for devices such
- * as the storm but can also be true for a PC with a mouse pointer floating
- * on top.
- * <p>A click touch screen will also send pointer hover events to the underlying
- * software and will only send the standard pointer events on click.
- *
- * @return false by default
- */
- public boolean isClickTouchScreen() {
- return false;
- }
- /**
- * Returns true if indexed images should be used natively
- *
- * @return true if a native image should be used for indexed images
- */
- public boolean isNativeIndexed() {
- return false;
- }
- /**
- * Creates a native image representing the indexed image
- *
- * @param image the indexed image
- * @return a native version of the indexed image
- */
- public Object createNativeIndexed(IndexedImage image) {
- return null;
- }
- /**
- * Create a video/media component
- *
- * @param player object responsible for playback lifecycle
- * @return the video control
- */
- public Object createVideoComponent(Object player) {
- return null;
- }
- /**
- * Returns the video width
- *
- * @param videoControl the control for the video
- * @return the width
- */
- public int getVideoWidth(Object videoControl) {
- return 0;
- }
- /**
- * Returns the video height
- *
- * @param videoControl the control for the video
- * @return the height
- */
- public int getVideoHeight(Object videoControl) {
- return 0;
- }
- /**
- * Sets the video visibility
- *
- * @param vc video control instance
- * @param visible whether the video is visible
- */
- public void setVideoVisible(Object vc, boolean visible) {
- }
- /**
- * Starts the video
- *
- * @param player the player object
- * @param videoControl the video control
- */
- public void startVideo(Object player, Object videoControl) {
- }
- /**
- * Stop the video
- *
- * @param player the player object
- * @param videoControl the video control
- */
- public void stopVideo(Object player, Object videoControl) {
- }
- /**
- * Set the number of times the media should loop
- *
- * @param player the player object
- * @param count the number of times the media should loop
- */
- public void setVideoLoopCount(Object player, int count) {
- }
- /**
- * Return the duration of the media
- *
- * @param player the player object
- * @return the duration of the media
- */
- public long getMediaTime(Object player) {
- return 0;
- }
- /**
- * "Jump" to a point in time within the media
- *
- * @param player the player object
- * @param now the point in time to "Jump" to
- * @return the media time in microseconds
- */
- public long setMediaTime(Object player, long now) {
- return 0;
- }
- /**
- * Toggles the fullscreen mode
- *
- * @param player the player object
- * @param fullscreen true for fullscreen mode
- */
- public void setVideoFullScreen(Object player, boolean fullscreen) {
- }
- /**
- * Paint the video for the media component
- *
- * @param cmp the media component
- * @param fullScreen indicates whether this is fullscreen or not
- * @param nativeGraphics the native graphics object
- * @param video the native videoo control
- * @param player the native player object
- */
- public void paintVideo(Component cmp, boolean fullScreen, Object nativeGraphics, Object video,
- Object player) {
- }
- /**
- * Returns true if the image was opaque
- *
- * @param lwuitImage the lwuit image
- * @param nativeImage the image object to test
- * @return true if the image is opaque
- */
- public boolean isOpaque(Image lwuitImage, Object nativeImage) {
- int[] rgb = lwuitImage.getRGBCached();
- for (int iter = 0; iter < rgb.length; iter++) {
- if ((rgb[iter] & 0xff000000) != 0xff000000) {
- return false;
- }
- }
- return true;
- }
- /**
- * 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 false;
- }
- /**
- * Resets the affine transform to the default value
- *
- * @param nativeGraphics the native graphics object
- */
- public void resetAffine(Object nativeGraphics) {
- System.out.println("Affine unsupported");
- }
- /**
- * Scales the coordinate system using the affine transform
- *
- * @param nativeGraphics the native graphics object
- * @param scale factor for x
- * @param scale factor for y
- */
- public void scale(Object nativeGraphics, float x, float y) {
- System.out.println("Affine unsupported");
- }
- /**
- * Rotates the coordinate system around a radian angle using the affine transform
- *
- * @param angle the rotation angle in radians
- * @param nativeGraphics the native graphics object
- */
- public void rotate(Object nativeGraphics, float angle) {
- System.out.println("Affine unsupported");
- }
- /**
- * Shear the graphics coordinate system using the affine transform
- *
- * @param shear factor for x
- * @param shear factor for y
- * @param nativeGraphics the native graphics object
- */
- public void shear(Object nativeGraphics, float x, float y) {
- System.out.println("Affine unsupported");
- }
- /**
- * Indicates whether the underlying platform supports creating an SVG Image
- *
- * @return true if the method create SVG image would return a valid image object
- * from an SVG Input stream
- */
- public boolean isSVGSupported() {
- return false;
- }
- /**
- * Creates an SVG Image from the given byte array data and the base URL
- *
- * @param baseURL URL which is used to resolve relative references within the SVG file
- * @param data the conten of the SVG file
- * @return a native image that can be used within the image object
- * @throws IOException if resource lookup fail SVG is unsupported
- */
- public Object createSVGImage(String baseURL, byte[] data) throws IOException {
- throw new IOException("SVG is not supported by this implementation");
- }
- /**
- * Returns a platform specific DOM object that can be manipulated by the user
- * to change the SVG Image
- *
- * @param svgImage the underlying image object
- * @return Platform dependent object, when JSR 226 is supported an SVGSVGElement might
- * be returned.
- */
- public Object getSVGDocument(Object svgImage) {
- throw new RuntimeException("SVG is not supported by this implementation");
- }
- /**
- * Callback to allow images animated by the underlying system to change their state
- * e.g. for SVG or animated gif support. This method returns true if an animation
- * state has changed requiring a repaint.
- *
- * @param nativeImage a native image used within the image object
- * @param lastFrame the time the last frame of animation was shown
- * @return true if a repaint is required since the image state changed, false otherwise
- */
- public boolean animateImage(Object nativeImage, long lastFrame) {
- return false;
- }
- /**
- * Returns a list of the platform names ordered by priority, platform names are
- * used to choose a font based on platform. Since a platform might support several
- * layers for choice in narrowing platform font selection
- *
- * @return the platform names ordered according to priority.
- */
- public String[] getFontPlatformNames() {
- return new String[]{"MIDP", "MIDP2"};
- }
- /**
- * Loads the truetype font from the input stream without closing the stream,
- * this method should return the native font.
- *
- * @param stream from which to load the font
- * @return the native font created from the stream
- * @throws IOException will be thrown in case of an io error
- */
- public Object loadTrueTypeFont(InputStream stream) throws IOException {
- throw new IOException("Unsupported operation");
- }
- /**
- * Returns true if the system supports dynamically loading truetype fonts from
- * a stream.
- *
- * @return true if the system supports dynamically loading truetype fonts from
- * a stream.
- */
- public boolean isTrueTypeSupported() {
- return false;
- }
- /**
- * Loads a native font based on a lookup for a font name and attributes. Font lookup
- * values can be separated by commas and thus allow fallback if the primary font
- * isn't supported by the platform.
- *
- * @param lookup string describing the font
- * @return the native font object
- */
- public Object loadNativeFont(String lookup) {
- return null;
- }
- /**
- * Indicates whether loading a font by a string is supported by the platform
- *
- * @return true if the platform supports font lookup
- */
- public boolean isLookupFontSupported() {
- return false;
- }
- /**
- * Minimizes the current application if minimization is supported by the platform (may fail).
- * Returns false if minimization failed.
- *
- * @return false if minimization failed true if it succeeded or seems to be successful
- */
- public boolean minimizeApplication() {
- return false;
- }
- /**
- * Restore the minimized application if minimization is supported by the platform
- */
- public void restoreMinimizedApplication() {
- }
- /**
- * Indicates whether an application is minimized
- *
- * @return true if the application is minimized
- */
- public boolean isMinimized() {
- return false;
- }
- /**
- * Indicates whether the implementation is interested in caching radial gradients for
- * drawing.
- *
- * @return true to activate radial gradient caching
- */
- protected boolean cacheRadialGradients() {
- return true;
- }
- /**
- * Indicates whether the implementation is interested in caching linear gradients for
- * drawing.
- *
- * @return true to activate linear gradient caching
- */
- protected boolean cacheLinearGradients() {
- return true;
- }
- /**
- * Indicates the default status to apply to the 3rd softbutton variable
- *
- * @return true if the 3rd softbutton should be set as true
- * @see com.sun.lwuit.Display#isThirdSoftButton()
- * @see com.sun.lwuit.Display#setThirdSoftButton()
- */
- public boolean isThirdSoftButton() {
- return getSoftkeyCount() < 2 && isTouchDevice();
- }
- /**
- * Indicates how many drag points are used to calculate dragging speed
- *
- * @return the size of points to calculate the speed
- */
- public int getDragPathLength(){
- return 10;
- }
- /**
- * Indicates what drag points are valid for the drag speed calculation.
- * Points that are older then the current time - the path time are ignored
- *
- * @return the relevance time per point
- */
- public int getDragPathTime(){
- return 200;
- }
- /**
- * This method returns the dragging speed based on the latest dragged
- * events
- * @param points array of locations
- * @param dragPathTime the time difference between each point
- * @param dragPathOffset the offset in the arrays
- * @param dragPathLength
- */
- public float getDragSpeed(float[] points, long[] dragPathTime,
- int dragPathOffset, int dragPathLength){
- long now = System.currentTimeMillis();
- final long tooold = now - getDragPathTime();
- int offset = dragPathOffset - dragPathLength;
- if (offset < 0) {
- offset = getDragPathLength() + offset;
- }
- long old = 0;
- float oldPoint = 0;
- float speed = 0;
- long timediff;
- float diff;
- float velocity;
- float f = dragPathLength;
- while (dragPathLength > 0) {
- if (dragPathTime[offset] > tooold) {
- if (old == 0) {
- old = dragPathTime[offset];
- oldPoint = points[offset];
- }
- timediff = now - old;
- diff = points[offset] - oldPoint;
- if (timediff > 0) {
- velocity = (diff / timediff) * 1.5f;
- speed += velocity;
- }
- }
- dragPathLength--;
- offset++;
- if (offset >= getDragPathLength()) {
- offset = 0;
- }
- }
- f = Math.max(1, f);
- return -speed / f;
- }
- /**
- * Indicates whether LWUIT should consider the bidi RTL algorithm
- * when drawing text or navigating with the text field cursor.
- *
- * @return true if the bidi algorithm should be considered
- */
- public boolean isBidiAlgorithm() {
- return bidi;
- }
- /**
- * Indicates whether LWUIT should consider the bidi RTL algorithm
- * when drawing text or navigating with the text field cursor.
- *
- * @param activate set to true to activate the bidi algorithm, false to
- * disable it
- */
- public void setBidiAlgorithm(boolean activate) {
- bidi = activate;
- }
- /**
- * Converts the given string from logical bidi layout to visual bidi layout so
- * it can be rendered properly on the screen. This method is only necessary
- * for devices/platforms that don't have "built in" bidi support such as
- * Sony Ericsson devices.
- * See <a href="http://www.w3.org/International/articles/inline-bidi-markup/#visual">this</a>
- * for more on visual vs. logical ordering.
- *
- *
- * @param s a "logical" string with RTL characters
- * @return a "visual" renderable string
- */
- public String convertBidiLogicalToVisual(String s) {
- if(bidi) {
- if (s.length() >= 2) {
- char[] c = s.toCharArray();
- swapBidiChars(c, 0, s.length(), -1);
- return new String(c);
- }
- }
- return s;
- }
- /**
- * Returns the index of the given char within the source string, the actual
- * index isn't necessarily the same when bidi is involved
- * See <a href="http://www.w3.org/International/articles/inline-bidi-markup/#visual">this</a>
- * for more on visual vs. logical ordering.
- *
- * @param source the string in which we are looking for the position
- * @param index the "logical" location of the cursor
- * @return the "visual" location of the cursor
- */
- public int getCharLocation(String source, int index) {
- if(bidi) {
- return swapBidiChars(source.toCharArray(), 0, source.length(), index);
- }
- return index;
- }
- /**
- * Returns true if the given character is an RTL character or a space
- * character
- *
- * @param c character to test
- * @return true if bidi is active and this is a
- */
- public boolean isRTLOrWhitespace(char c) {
- if(bidi) {
- return isRTL(c) || c == ' ';
- }
- return false;
- }
- /**
- * Returns true if the given character is an RTL character
- *
- * @param c character to test
- * @return true if the charcter is an RTL character
- */
- public boolean isRTL(char c) {
- return (c >= RTL_RANGE_BEGIN && c <= RTL_RANGE_END);
- }
- private final int swapBidiChars(char[] chars, int ixStart, int len,int index) {
- int destIndex = -1;
- int ixEnd = ixStart + len;
- int ix0, ix1;
- ix0 = ix1 = ixStart;
- boolean doSwap = false;
- for ( int i1 = ixStart; i1 < ixEnd; i1++ ) {
- if ( isRTL(chars[i1]) ) {
- doSwap = true;
- break;
- }
- }
- if ( doSwap ) {
- while ( ix0 < ixEnd ) {
- if ( (ix1 = scanSecond(chars, ix0, ixEnd)) < 0 ) {
- break;
- } else {
- ix0 = ix1;
- ix1 = scanBackFirst(chars, ix0, ixEnd);
- // swap
- for ( int iy0 = ix0, iy1 = ix1-1; iy0 < iy1; iy0++, iy1--) {
- char tmp = chars[iy0];
- chars[iy0] = chars[iy1];
- chars[iy1] = tmp;
- if (index==iy1) {
- //System.out.println("IY: Found char: new index="+iy0);
- destIndex=iy0;
- index=iy0;
- }
- }
- ix0 = ix1;
- }
- }
- }
- if ( doSwap ) {
- // swap the line
- for (ix0 = ixStart, ix1 = ixEnd - 1 ; ix0 <= ix1 ; ix0++, ix1--) {
- char ch0 = chars[ix0];
- char ch1 = chars[ix1];
- chars[ix0] = ch1;
- chars[ix1] = ch0;
- if (index==ix0) {
- destIndex=ix1;
- } else if (index==ix1) {
- destIndex=ix0;
- }
- }
- }
- return destIndex;
- }
- private boolean isRTLBreak(char ch1) {
- return ch1 == ')' || ch1 == ']' || ch1 == '}' || ch1 == '(' || ch1 == '[' || ch1 == '{' ;
- }
- private boolean isLTR(char c) {
- return !isRTL(c) && !isRTLBreak(c);
- }
- private final int scanSecond(char[] chars, int ixStart, int ixEnd) {
- int ixFound = -1;
- for ( int ix = ixStart; ixFound < 0 && ix < ixEnd; ix++ ) {
- if (!isRTL(chars[ix])) {
- ixFound = ix;
- }
- }
- return ixFound;
- }
- private final int scanBackFirst(char[] chars, int ixStart, int ixEnd)
- {
- int ix, ixFound = ixEnd;
- for ( ix = ixStart+1; ix < ixEnd; ix++ ) {
- if ( isRTLBreak(chars[ix])) {
- ixFound = ix;
- break;
- }
- }
- for (ix = ixFound-1; ix >= ixStart; ix-- ) {
- if ( isLTR(chars[ix]) ) {
- ixFound = ix + 1;
- break;
- }
- }
- return ixFound;
- }
- /**
- * This method is essentially equivalent to cls.getResourceAsStream(String)
- * however some platforms might define unique ways in which to load resources
- * within the implementation.
- *
- * @param cls class to load the resource from
- * @param resource relative/absolute URL based on the Java convention
- * @return input stream for the resource or null if not found
- */
- public InputStream getResourceAsStream(Class cls, String resource) {
- return cls.getResourceAsStream(resource);
- }
- }