LWUITImplementation.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:82k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit.impl;
  26. import com.sun.lwuit.*;
  27. import com.sun.lwuit.animations.Animation;
  28. import com.sun.lwuit.geom.Dimension;
  29. import com.sun.lwuit.geom.Rectangle;
  30. import java.io.IOException;
  31. import java.io.InputStream;
  32. import java.lang.ref.WeakReference;
  33. import java.util.Enumeration;
  34. import java.util.Hashtable;
  35. /**
  36.  * Represents a vendor extension mechanizm for LWUIT, <b>WARNING: this class is for internal
  37.  * use only and is subject to change in future API revisions</b>. To replace the way in which
  38.  * LWUIT performs its task this class can be extended and its functionality replaced or
  39.  * enhanced.
  40.  * <p>It is the responsibility of the implementation class to grab and fire all events to the 
  41.  * Display specifically for key, pointer events and screen resolution.
  42.  * 
  43.  * @author Shai Almog
  44.  */
  45. public abstract class LWUITImplementation {
  46.     /**
  47.      * Indicates the range of "hard" RTL bidi characters in unicode
  48.      */
  49.     private static final char RTL_RANGE_BEGIN = 0x590;
  50.     private static final char RTL_RANGE_END = 0x7BF;
  51.     private Hashtable linearGradientCache;
  52.     private Hashtable radialGradientCache;
  53.     private int dragActivationCounter = 0;
  54.     private int dragActivationX = 0;
  55.     private int dragActivationY = 0;
  56.     private int dragStartPercentage = 3;
  57.     private Form currentForm;
  58.     private static Object displayLock;
  59.     private Animation[] paintQueue = new Animation[50];
  60.     private Animation[] paintQueueTemp = new Animation[50];
  61.     private int paintQueueFill = 0;
  62.     private Graphics lwuitGraphics;
  63.     private boolean bidi;
  64.     /**
  65.      * Useful since the content of a single element touch event is often recycled
  66.      * and always arrives on 1 thread. Even on multi-tocuh devices a single coordinate
  67.      * touch event should be very efficient
  68.      */
  69.     private int[] xPointerEvent = new int[1];
  70.     /**
  71.      * Useful since the content of a single element touch event is often recycled
  72.      * and always arrives on 1 thread. Even on multi-tocuh devices a single coordinate
  73.      * touch event should be very efficient
  74.      */
  75.     private int[] yPointerEvent = new int[1];
  76.     private int pointerPressedX;
  77.     private int pointerPressedY;
  78.     
  79.     /**
  80.      * Invoked by the display init method allowing the implementation to "bind"
  81.      * 
  82.      * @param m the object passed to the Display init method
  83.      */
  84.     public abstract void init(Object m);
  85.     /**
  86.      * Invoked when a dialog is shown, this method allows a dialog to play a sound
  87.      * 
  88.      * @param type the type of the dialog matching the dialog classes defined types
  89.      */
  90.     public void playDialogSound(final int type) {
  91.     }
  92.     /**
  93.      * Vibrates the device for the given length of time
  94.      * 
  95.      * @param duration length of time to vibrate
  96.      */
  97.     public void vibrate(int duration) {
  98.     }
  99.     /**
  100.      * Flash the backlight of the device for the given length of time
  101.      * 
  102.      * @param duration length of time to flash the backlight
  103.      */
  104.     public void flashBacklight(int duration) {
  105.     }
  106.     /**
  107.      * Returns the width dimention of the display controlled by this implementation
  108.      * 
  109.      * @return the width
  110.      */
  111.     public abstract int getDisplayWidth();
  112.     /**
  113.      * Returns the height dimention of the display controlled by this implementation
  114.      * 
  115.      * @return the height
  116.      */
  117.     public abstract int getDisplayHeight();
  118.     /**
  119.      * Invoked when an exception occurs on the EDT, allows the implementation to
  120.      * take control of the device to produce testing information.
  121.      * 
  122.      * @param err the exception that was caught in the EDT loop
  123.      * @return false by default, true if the exception shouldn't be handled further 
  124.      * by the EDT
  125.      */
  126.     public boolean handleEDTException(Throwable err) {
  127.         return false;
  128.     }
  129.     /**
  130.      * Encapsulates the editing code which is specific to the platform, some platforms
  131.      * would allow "in place editing" MIDP does not.
  132.      * 
  133.      * @param cmp the {@link TextArea} component
  134.      * @param maxSize the maximum size from the text area
  135.      * @param constraint the constraints of the text area
  136.      * @param text the string to edit
  137.      */
  138.     public abstract void editString(Component cmp, int maxSize, int constraint, String text);
  139.     /**
  140.      * Invoked if LWUIT needs to dispose the native text editing but would like the editor
  141.      * to store its state.
  142.      */
  143.     public void saveTextEditingState() {
  144.     }
  145.     /**
  146.      * Returns true if the implementation still has elements to paint.
  147.      * 
  148.      * @return false by default
  149.      */
  150.     public boolean hasPendingPaints() {
  151.         return paintQueueFill != 0;
  152.     }
  153.     /**
  154.      * Returns the video control for the media player
  155.      *
  156.      * @param player the media player
  157.      * @return the video control for the media player
  158.      */
  159.     public Object getVideoControl(Object player) {
  160.         return null;
  161.     }
  162.     /**
  163.      * Return the number of alpha levels supported by the implementation.
  164.      * 
  165.      * @return the number of alpha levels supported by the implementation
  166.      */
  167.     public int numAlphaLevels() {
  168.         return 255;
  169.     }
  170.     /**
  171.      * Returns the number of colors applicable on the device, note that the API
  172.      * does not support gray scale devices.
  173.      * 
  174.      * @return the number of colors applicable on the device
  175.      */
  176.     public int numColors() {
  177.         return 65536;
  178.     }
  179.     /**
  180.      * Allows for painting an overlay on top of the implementation for notices during
  181.      * testing etc.
  182.      * 
  183.      * @param g graphics context on which to draw the overlay
  184.      */
  185.     protected void paintOverlay(Graphics g) {
  186.     }
  187.     /**
  188.      * Invoked by the EDT to paint the dirty regions
  189.      */
  190.     public void paintDirty() {
  191.         int size = 0;
  192.         synchronized (displayLock) {
  193.             size = paintQueueFill;
  194.             Animation[] array = paintQueue;
  195.             paintQueue = paintQueueTemp;
  196.             paintQueueTemp = array;
  197.             paintQueueFill = 0;
  198.         }
  199.         if (size > 0) {
  200.             Graphics wrapper = getLWUITGraphics();
  201.             int topX = getDisplayWidth();
  202.             int topY = getDisplayHeight();
  203.             int bottomX = 0;
  204.             int bottomY = 0;
  205.             for (int iter = 0; iter < size; iter++) {
  206.                 Animation ani = paintQueueTemp[iter];
  207.                 paintQueueTemp[iter] = null;
  208.                 wrapper.translate(-wrapper.getTranslateX(), -wrapper.getTranslateY());
  209.                 wrapper.setClip(0, 0, getDisplayWidth(), getDisplayHeight());
  210.                 if (ani instanceof Component) {
  211.                     Component cmp = (Component) ani;
  212.                     Rectangle dirty = cmp.getDirtyRegion();
  213.                     if (dirty != null) {
  214.                         wrapper.setClip(dirty.getX(), dirty.getY(), dirty.getSize().getWidth(), dirty.getSize().getHeight());
  215.                         cmp.setDirtyRegion(null);
  216.                     }
  217.                     cmp.paintComponent(wrapper);
  218.                     int cmpAbsX = cmp.getAbsoluteX() + cmp.getScrollX();
  219.                     topX = Math.min(cmpAbsX, topX);
  220.                     bottomX = Math.max(cmpAbsX + cmp.getWidth(), bottomX);
  221.                     int cmpAbsY = cmp.getAbsoluteY() + cmp.getScrollY();
  222.                     topY = Math.min(cmpAbsY, topY);
  223.                     bottomY = Math.max(cmpAbsY + cmp.getHeight(), bottomY);
  224.                 } else {
  225.                     bottomX = getDisplayWidth();
  226.                     bottomY = getDisplayHeight();
  227.                     topX = 0;
  228.                     topY = 0;
  229.                     ani.paint(wrapper);
  230.                 }
  231.             }
  232.             paintOverlay(wrapper);
  233.             flushGraphics(topX, topY, bottomX - topX, bottomY - topY);
  234.         }
  235.     }
  236.     /**
  237.      * This method is a callback from the edt before the edt enters to an idle 
  238.      * state
  239.      * @param enter true before the edt sleeps and false when exits from the
  240.      * idle state
  241.      */
  242.     public void edtIdle(boolean enter){
  243.     }
  244.     
  245.     /**
  246.      * Flush the currently painted drawing onto the screen if using a double buffer
  247.      * 
  248.      * @param x position of the dirty region
  249.      * @param y position of the dirty region
  250.      * @param width width of the dirty region
  251.      * @param height height of the dirty region
  252.      */
  253.     public abstract void flushGraphics(int x, int y, int width, int height);
  254.     /**
  255.      * Flush the currently painted drawing onto the screen if using a double buffer
  256.      */
  257.     public abstract void flushGraphics();
  258.     /**
  259.      * Returns a graphics object for use by the painting
  260.      * 
  261.      * @return a graphics object, either recycled or new, this object will be 
  262.      * used on the EDT
  263.      */
  264.     protected Graphics getLWUITGraphics() {
  265.         return lwuitGraphics;
  266.     }
  267.     /**
  268.      * Installs the LWUIT graphics object into the implementation
  269.      * 
  270.      * @param g graphics object for use by the implementation
  271.      */
  272.     public void setLWUITGraphics(Graphics g) {
  273.         lwuitGraphics = g;
  274.     }
  275.     /**
  276.      * Installs the display lock allowing implementors to synchronize against the 
  277.      * Display mutex, this method is invoked internally and should not be used.
  278.      * 
  279.      * @param lock the mutex from display
  280.      */
  281.     public void setDisplayLock(Object lock) {
  282.         displayLock = lock;
  283.     }
  284.     /**
  285.      * Returns a lock object which can be synchrnoized against, this lock is used
  286.      * by the EDT.
  287.      * 
  288.      * @return a lock object
  289.      */
  290.     public Object getDisplayLock() {
  291.         return displayLock;
  292.     }
  293.     /**
  294.      * Invoked to add an element to the paintQueue
  295.      * 
  296.      * @param cmp component or animation to push into the paint queue
  297.      */
  298.     public void repaint(Animation cmp) {
  299.         synchronized (displayLock) {
  300.             for (int iter = 0; iter < paintQueueFill; iter++) {
  301.                 Animation ani = paintQueue[iter];
  302.                 if (ani == cmp) {
  303.                     return;
  304.                 }
  305.             }
  306.             // overcrowding the queue don't try to grow the array!
  307.             if (paintQueueFill >= paintQueue.length) {
  308.                 System.out.println("Warning paint queue size exceeded, please watch the amount of repaint calls");
  309.                 return;
  310.             }
  311.             paintQueue[paintQueueFill] = cmp;
  312.             paintQueueFill++;
  313.             displayLock.notify();
  314.         }
  315.     }
  316.     /**
  317.      * Extracts RGB data from the given native image and places it in the given array
  318.      * 
  319.      * @param nativeImage native platform image object
  320.      * @param arr int array to store RGB data
  321.      * @param offset position within the array to start
  322.      * @param x x position within the image
  323.      * @param y y position within the image
  324.      * @param width width to extract
  325.      * @param height height to extract
  326.      */
  327.     public abstract void getRGB(Object nativeImage, int[] arr, int offset, int x, int y, int width, int height);
  328.     /**
  329.      * Create a platform native image object from the given RGB data
  330.      * 
  331.      * @param rgb ARGB data from which to create a platform image
  332.      * @param width width for the resulting image
  333.      * @param height height for the resulting image
  334.      * @return platform image object
  335.      */
  336.     public abstract Object createImage(int[] rgb, int width, int height);
  337.     /**
  338.      * Creates a native image from a file in the system jar
  339.      * 
  340.      * @param path within the jar
  341.      * @return native system image
  342.      * @throws java.io.IOException if thrown by loading
  343.      */
  344.     public abstract Object createImage(String path) throws IOException;
  345.     /**
  346.      * Creates a native image from a given input stream
  347.      * 
  348.      * @param i input stream from which to load the image
  349.      * @return native system image
  350.      * @throws java.io.IOException if thrown by loading
  351.      */
  352.     public abstract Object createImage(InputStream i) throws IOException;
  353.     /**
  354.      * Creates a modifable native image that can return a graphics object
  355.      * 
  356.      * @param width the width of the mutable image
  357.      * @param height the height of the mutable image
  358.      * @param fillColor the ARGB fill color, alpha may be ignored based on the value of
  359.      * isAlphaMutableImageSupported
  360.      * @return the native image
  361.      */
  362.     public abstract Object createMutableImage(int width, int height, int fillColor);
  363.     /**
  364.      * Indicates whether mutable images respect alpha values when constructed
  365.      * 
  366.      * @return true if mutable images can have an alpha value when initially created
  367.      */
  368.     public boolean isAlphaMutableImageSupported() {
  369.         return false;
  370.     }
  371.     /**
  372.      * Create a nativate image from its compressed byte data
  373.      * 
  374.      * @param bytes the byte array representing the image data
  375.      * @param offset offset within the byte array
  376.      * @param len the length for the image within the byte array
  377.      * @return a native image
  378.      */
  379.     public abstract Object createImage(byte[] bytes, int offset, int len);
  380.     /**
  381.      * Returns the width of a native image
  382.      * 
  383.      * @param i the native image
  384.      * @return the width of the native image
  385.      */
  386.     public abstract int getImageWidth(Object i);
  387.     /**
  388.      * Returns the height of a native image
  389.      * 
  390.      * @param i the native image
  391.      * @return the height of the native image
  392.      */
  393.     public abstract int getImageHeight(Object i);
  394.     /**
  395.      * Scales a native image and returns the scaled version
  396.      * 
  397.      * @param nativeImage image to scale
  398.      * @param width width of the resulting image
  399.      * @param height height of the resulting image
  400.      * @return scaled image instance
  401.      */
  402.     public abstract Object scale(Object nativeImage, int width, int height);
  403.     private static int round(double d) {
  404.         double f = Math.floor(d);
  405.         double c = Math.ceil(d);
  406.         if (c - d < d - f) {
  407.             return (int) c;
  408.         }
  409.         return (int) f;
  410.     }
  411.     /**
  412.      * Returns an instance of this image rotated by the given number of degrees. By default 90 degree
  413.      * angle divisions are supported, anything else is implementation dependent. This method assumes 
  414.      * a square image. Notice that it is inefficient in the current implementation to rotate to
  415.      * non-square angles, 
  416.      * <p>E.g. rotating an image to 45, 90 and 135 degrees is inefficient. Use rotatate to 45, 90
  417.      * and then rotate the 45 to another 90 degrees to achieve the same effect with less memory.
  418.      * 
  419.      * @param degrees A degree in right angle must be larger than 0 and up to 359 degrees
  420.      * @return new image instance with the closest possible rotation
  421.      */
  422.     public Object rotate(Object image, int degrees) {
  423.         int width = getImageWidth(image);
  424.         int height = getImageHeight(image);
  425.         int[] arr = new int[width * height];
  426.         int[] dest = new int[arr.length];
  427.         getRGB(image, arr, 0, 0, 0, width, height);
  428.         int centerX = width / 2;
  429.         int centerY = height / 2;
  430.         double radians = Math.toRadians(-degrees);
  431.         double cosDeg = Math.cos(radians);
  432.         double sinDeg = Math.sin(radians);
  433.         for (int x = 0; x < width; x++) {
  434.             for (int y = 0; y < height; y++) {
  435.                 int x2 = round(cosDeg * (x - centerX) - sinDeg * (y - centerY) + centerX);
  436.                 int y2 = round(sinDeg * (x - centerX) + cosDeg * (y - centerY) + centerY);
  437.                 if (!(x2 < 0 || y2 < 0 || x2 >= width || y2 >= height)) {
  438.                     int destOffset = x2 + y2 * width;
  439.                     if (destOffset >= 0 && destOffset < dest.length) {
  440.                         dest[x + y * width] = arr[destOffset];
  441.                     }
  442.                 }
  443.             }
  444.         }
  445.         return createImage(dest, width, height);
  446.     }
  447.     /**
  448.      * Returns the number of softkeys on the device
  449.      * 
  450.      * @return the number of softkey buttons on the device
  451.      */
  452.     public abstract int getSoftkeyCount();
  453.     /**
  454.      * Returns the softkey keycode for the given softkey index
  455.      * 
  456.      * @param index the index of the softkey
  457.      * @return the set of keycodes which can indicate the softkey, multiple keycodes
  458.      * might apply to the same functionality
  459.      */
  460.     public abstract int[] getSoftkeyCode(int index);
  461.     /**
  462.      * Returns the keycode for the clear key
  463.      * 
  464.      * @return the system key code for this device
  465.      */
  466.     public abstract int getClearKeyCode();
  467.     /**
  468.      * Returns the keycode for the backspace key
  469.      * 
  470.      * @return the system key code for this device
  471.      */
  472.     public abstract int getBackspaceKeyCode();
  473.     /**
  474.      * Returns the keycode for the back key
  475.      * 
  476.      * @return the system key code for this device
  477.      */
  478.     public abstract int getBackKeyCode();
  479.     /**
  480.      * Returns the display game action for the given keyCode if applicable to match
  481.      * the contrct of LWUIT for the game action behavior
  482.      * 
  483.      * @param keyCode the device keycode
  484.      * @return a game action or 0
  485.      */
  486.     public abstract int getGameAction(int keyCode);
  487.     /**
  488.      * Returns a keycode which can be sent to getGameAction
  489.      * 
  490.      * @param gameAction the game action
  491.      * @return key code matching the given game action
  492.      */
  493.     public abstract int getKeyCode(int gameAction);
  494.     /**
  495.      * Returns true if the device will send touch events
  496.      * 
  497.      * @return true if the device will send touch events
  498.      */
  499.     public abstract boolean isTouchDevice();
  500.     /**
  501.      * This method is used internally to determine the actual current form
  502.      * it doesn't perform the logic of transitions etc. and shouldn't be invoked
  503.      * by developers
  504.      * 
  505.      * @param f the current form
  506.      */
  507.     public void setCurrentForm(Form f) {
  508.         currentForm = f;
  509.     }
  510.     /**
  511.      * Callback method allowing the implementation to confirm that it controls the
  512.      * view just before a new form is installed.
  513.      */
  514.     public void confirmControlView() {
  515.     }
  516.     /**
  517.      * Returns the current form, this method is for internal use only and does not
  518.      * take transitions/menus into consideration
  519.      * 
  520.      * @return The internal current form
  521.      */
  522.     public Form getCurrentForm() {
  523.         return currentForm;
  524.     }
  525.     /**
  526.      * LWUIT can translate all coordinates and never requires a call to translate
  527.      * this works well for some devices which have hairy issues with translate.
  528.      * However for some platforms where translate can be leveraged with affine transforms
  529.      * this can be a problem. These platforms can choose to translate on their own
  530.      * 
  531.      * @return true if the implementation is interested in receiving translate calls
  532.      * and handling them.
  533.      */
  534.     public boolean isTranslationSupported() {
  535.         return false;
  536.     }
  537.     /**
  538.      * Translates the X/Y location for drawing on the underlying surface. Translation
  539.      * is incremental so the new value will be added to the current translation and
  540.      * in order to reset translation we have to invoke 
  541.      * {@code translate(-getTranslateX(), -getTranslateY()) }
  542.      * 
  543.      * @param graphics the graphics context
  544.      * @param x the x coordinate
  545.      * @param y the y coordinate
  546.      */
  547.     public void translate(Object graphics, int x, int y) {
  548.     }
  549.     /**
  550.      * Returns the current x translate value 
  551.      * 
  552.      * @param graphics the graphics context
  553.      * @return the current x translate value 
  554.      */
  555.     public int getTranslateX(Object graphics) {
  556.         return 0;
  557.     }
  558.     /**
  559.      * Returns the current y translate value 
  560.      * 
  561.      * @param graphics the graphics context
  562.      * @return the current y translate value 
  563.      */
  564.     public int getTranslateY(Object graphics) {
  565.         return 0;
  566.     }
  567.     /**
  568.      * Returns the current color
  569.      * 
  570.      * @param graphics the graphics context
  571.      * @return the RGB graphics color 
  572.      */
  573.     public abstract int getColor(Object graphics);
  574.     /**
  575.      * Sets the current rgb color while ignoring any potential alpha component within
  576.      * said color value.
  577.      * 
  578.      * @param graphics the graphics context
  579.      * @param RGB the RGB value for the color.
  580.      */
  581.     public abstract void setColor(Object graphics, int RGB);
  582.     /**
  583.      * Alpha value from 0-255 can be ignored for some operations
  584.      * 
  585.      * @param graphics the graphics context
  586.      * @param alpha the alpha channel
  587.      */
  588.     public abstract void setAlpha(Object graphics, int alpha);
  589.     /**
  590.      * Alpha value from 0-255 can be ignored for some operations
  591.      * 
  592.      * @param graphics the graphics context
  593.      * @return the alpha channel
  594.      */
  595.     public abstract int getAlpha(Object graphics);
  596.     /**
  597.      * Returns true if alpha can be applied for all elements globally and efficiently
  598.      * otherwise alpha should be ignored.
  599.      * Notice that fillRect MUST always support alpha regardless of the value of this
  600.      * variable!
  601.      * 
  602.      * @return true if alpha support is natively implemented
  603.      */
  604.     public boolean isAlphaGlobal() {
  605.         return false;
  606.     }
  607.     /**
  608.      * Indicates whether the underlying implementation allows for anti-aliasing in regular
  609.      * drawing operations
  610.      * 
  611.      * @return false by default
  612.      */
  613.     public boolean isAntiAliasingSupported() {
  614.         return false;
  615.     }
  616.     /**
  617.      * Indicates whether the underlying implementation allows for anti-aliased fonts
  618.      * 
  619.      * @return false by default
  620.      */
  621.     public boolean isAntiAliasedTextSupported() {
  622.         return false;
  623.     }
  624.     /**
  625.      * Toggles anti-aliasing mode for regular rendering operations
  626.      * 
  627.      * @param graphics the graphics context
  628.      * @param a true to activate Anti-aliasing, false to disable it
  629.      */
  630.     public void setAntiAliased(Object graphics, boolean a) {
  631.     }
  632.     /**
  633.      * Returns anti-aliasing mode for regular rendering operations
  634.      * 
  635.      * @param graphics the graphics context
  636.      * @return true if Anti-aliasing is active, false otherwise
  637.      */
  638.     public boolean isAntiAliased(Object graphics) {
  639.         return false;
  640.     }
  641.     /**
  642.      * Toggles anti-aliasing mode for font rendering operations
  643.      * 
  644.      * @param graphics the graphics context
  645.      * @param a true to activate Anti-aliasing, false to disable it
  646.      */
  647.     public void setAntiAliasedText(Object graphics, boolean a) {
  648.     }
  649.     /**
  650.      * Returns anti-aliasing mode for font rendering operations
  651.      * 
  652.      * @param graphics the graphics context
  653.      * @return true if Anti-aliasing is active, false otherwise
  654.      */
  655.     public boolean isAntiAliasedText(Object graphics) {
  656.         return false;
  657.     }
  658.     /**
  659.      * Installs a native font object
  660.      * 
  661.      * @param graphics the graphics context
  662.      * @param font the native font object
  663.      */
  664.     public abstract void setNativeFont(Object graphics, Object font);
  665.     /**
  666.      * Returns the internal clipping rectangle. This method must create a new
  667.      * rectangle object to prevent corruption by modification.
  668.      * 
  669.      * @param graphics the graphics context
  670.      * @return the clipping rectangle.
  671.      */
  672.     public Rectangle getClipRect(Object graphics) {
  673.         return new Rectangle(getClipX(graphics), getClipY(graphics), new Dimension(getClipWidth(graphics), getClipHeight(graphics)));
  674.     }
  675.     /**
  676.      * Returns the clipping coordinate
  677.      * 
  678.      * @param graphics the graphics context
  679.      * @return the clipping coordinate
  680.      */
  681.     public abstract int getClipX(Object graphics);
  682.     /**
  683.      * Returns the clipping coordinate
  684.      * 
  685.      * @param graphics the graphics context
  686.      * @return the clipping coordinate
  687.      */
  688.     public abstract int getClipY(Object graphics);
  689.     /**
  690.      * Returns the clipping coordinate
  691.      * 
  692.      * @param graphics the graphics context
  693.      * @return the clipping coordinate
  694.      */
  695.     public abstract int getClipWidth(Object graphics);
  696.     /**
  697.      * Returns the clipping coordinate
  698.      * 
  699.      * @param graphics the graphics context
  700.      * @return the clipping coordinate
  701.      */
  702.     public abstract int getClipHeight(Object graphics);
  703.     /**
  704.      * Installs a new clipping rectangle
  705.      * 
  706.      * @param graphics the graphics context
  707.      * @param rect rectangle representing the new clipping area
  708.      */
  709.     public void setClipRect(Object graphics, Rectangle rect) {
  710.         Dimension d = rect.getSize();
  711.         setClip(graphics, rect.getX(), rect.getY(), d.getWidth(), d.getHeight());
  712.     }
  713.     /**
  714.      * Installs a new clipping rectangle
  715.      * 
  716.      * @param graphics the graphics context
  717.      * @param x coordinate
  718.      * @param y coordinate
  719.      * @param width size
  720.      * @param height size
  721.      * @param rect rectangle representing the new clipping area
  722.      */
  723.     public abstract void setClip(Object graphics, int x, int y, int width, int height);
  724.     /**
  725.      * Changes the current clipping rectangle to subset the current clipping with
  726.      * the given clipping.
  727.      * 
  728.      * @param graphics the graphics context
  729.      * @param rect rectangle representing the new clipping area
  730.      */
  731.     public void clipRect(Object graphics, Rectangle rect) {
  732.         Dimension d = rect.getSize();
  733.         clipRect(graphics, rect.getX(), rect.getY(), d.getWidth(), d.getHeight());
  734.     }
  735.     /**
  736.      * Changes the current clipping rectangle to subset the current clipping with
  737.      * the given clipping.
  738.      * 
  739.      * @param graphics the graphics context
  740.      * @param x coordinate
  741.      * @param y coordinate
  742.      * @param width size
  743.      * @param height size
  744.      * @param rect rectangle representing the new clipping area
  745.      */
  746.     public abstract void clipRect(Object graphics, int x, int y, int width, int height);
  747.     /**
  748.      * Draws a line between the 2 X/Y coordinates
  749.      * 
  750.      * @param graphics the graphics context
  751.      * @param x1 first x position
  752.      * @param y1 first y position
  753.      * @param x2 second x position
  754.      * @param y2 second y position
  755.      */
  756.     public abstract void drawLine(Object graphics, int x1, int y1, int x2, int y2);
  757.     /**
  758.      * Fills the rectangle from the given position according to the width/height
  759.      * minus 1 pixel according to the convention in Java.
  760.      * 
  761.      * @param graphics the graphics context
  762.      * @param x the x coordinate of the rectangle to be filled.
  763.      * @param y the y coordinate of the rectangle to be filled.
  764.      * @param width the width of the rectangle to be filled.
  765.      * @param height the height of the rectangle to be filled.
  766.      */
  767.     public abstract void fillRect(Object graphics, int x, int y, int width, int height);
  768.     /**
  769.      * Draws a rectangle in the given coordinates
  770.      * 
  771.      * @param graphics the graphics context
  772.      * @param x the x coordinate of the rectangle to be drawn.
  773.      * @param y the y coordinate of the rectangle to be drawn.
  774.      * @param width the width of the rectangle to be drawn.
  775.      * @param height the height of the rectangle to be drawn.
  776.      */
  777.     public abstract void drawRect(Object graphics, int x, int y, int width, int height);
  778.     /**
  779.      * Draws a rounded corner rectangle in the given coordinates with the arcWidth/height
  780.      * matching the last two arguments respectively.
  781.      * 
  782.      * @param graphics the graphics context
  783.      * @param x the x coordinate of the rectangle to be drawn.
  784.      * @param y the y coordinate of the rectangle to be drawn.
  785.      * @param width the width of the rectangle to be drawn.
  786.      * @param height the height of the rectangle to be drawn.
  787.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  788.      * @param arcHeight the vertical diameter of the arc at the four corners.
  789.      */
  790.     public abstract void drawRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight);
  791.     /**
  792.      * Fills a rounded rectangle in the same way as drawRoundRect
  793.      * 
  794.      * @param graphics the graphics context
  795.      * @param x the x coordinate of the rectangle to be filled.
  796.      * @param y the y coordinate of the rectangle to be filled.
  797.      * @param width the width of the rectangle to be filled.
  798.      * @param height the height of the rectangle to be filled.
  799.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  800.      * @param arcHeight the vertical diameter of the arc at the four corners.
  801.      * @see #drawRoundRect
  802.      */
  803.     public abstract void fillRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight);
  804.     /**
  805.      * Fills a circular or elliptical arc based on the given angles and bounding 
  806.      * box. The resulting arc begins at startAngle and extends for arcAngle 
  807.      * degrees.
  808.      * 
  809.      * @param graphics the graphics context
  810.      * @param x the x coordinate of the upper-left corner of the arc to be filled.
  811.      * @param y the y coordinate of the upper-left corner of the arc to be filled.
  812.      * @param width the width of the arc to be filled.
  813.      * @param height the height of the arc to be filled.
  814.      * @param startAngle the beginning angle.
  815.      * @param arcAngle the angular extent of the arc, relative to the start angle.
  816.      */
  817.     public abstract void fillArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle);
  818.     /**
  819.      * Draws a circular or elliptical arc based on the given angles and bounding 
  820.      * box
  821.      * 
  822.      * @param graphics the graphics context
  823.      * @param x the x coordinate of the upper-left corner of the arc to be drawn.
  824.      * @param y the y coordinate of the upper-left corner of the arc to be drawn.
  825.      * @param width the width of the arc to be drawn.
  826.      * @param height the height of the arc to be drawn.
  827.      * @param startAngle the beginning angle.
  828.      * @param arcAngle the angular extent of the arc, relative to the start angle.
  829.      */
  830.     public abstract void drawArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle);
  831.     /**
  832.      * Draw a string using the current font and color in the x,y coordinates. The font is drawn
  833.      * from the top position and not the baseline.
  834.      * 
  835.      * @param graphics the graphics context
  836.      * @param str the string to be drawn.
  837.      * @param x the x coordinate.
  838.      * @param y the y coordinate.
  839.      */
  840.     public abstract void drawString(Object graphics, String str, int x, int y);
  841.     /**
  842.      * Draws the image so its top left coordinate corresponds to x/y
  843.      * 
  844.      * @param graphics the graphics context
  845.      * @param img the specified native image to be drawn
  846.      * @param x the x coordinate.
  847.      * @param y the y coordinate.
  848.      */
  849.     public abstract void drawImage(Object graphics, Object img, int x, int y);
  850.     /**
  851.      * Draws a portion of the image
  852.      *
  853.      * @param nativeGraphics the graphics context
  854.      * @param img the specified native image to be drawn
  855.      * @param x the x coordinate.
  856.      * @param y the y coordinate.
  857.      * @param imageX location within the image to draw
  858.      * @param imageY location within the image to draw
  859.      * @param imageWidth size of the location within the image to draw
  860.      * @param imageHeight size of the location within the image to draw
  861.      */
  862.     public void drawImageArea(Object nativeGraphics, Object img, int x, int y, int imageX, int imageY, int imageWidth, int imageHeight) {
  863.         int clipX = getClipX(nativeGraphics);
  864.         int clipY = getClipY(nativeGraphics);
  865.         int clipWidth = getClipWidth(nativeGraphics);
  866.         int clipHeight = getClipHeight(nativeGraphics);
  867.         clipRect(nativeGraphics, x, y, imageWidth, imageHeight);
  868.         if (getClipWidth(nativeGraphics) > 0 && getClipHeight(nativeGraphics) > 0) {
  869.             drawImage(nativeGraphics, img, x - imageX, y - imageY);
  870.         }
  871.         setClip(nativeGraphics, clipX, clipY, clipWidth, clipHeight);
  872.     }
  873.     /**
  874.      * Draws the image so its top left coordinate corresponds to x/y with a fast
  875.      * native rotation in a square angle which must be one of 0, 90, 180 or 270
  876.      * 
  877.      * @param graphics the graphics context
  878.      * @param img the specified native image to be drawn
  879.      * @param x the x coordinate.
  880.      * @param y the y coordinate.
  881.      * @param degrees either 0, 90, 180 or 270 degree rotation for the image drawing
  882.      */
  883.     public void drawImageRotated(Object graphics, Object img, int x, int y, int degrees) {
  884.     }
  885.     /**
  886.      * Indicates whether drawImageRotated is supported by the platform for FAST drawing,
  887.      * if not then its not worth calling the method which will be unimplemented!
  888.      * 
  889.      * @return true if drawImageRotated will draw an image
  890.      */
  891.     public boolean isRotationDrawingSupported() {
  892.         return false;
  893.     }
  894.     /**
  895.      * Draws a filled triangle with the given coordinates
  896.      * 
  897.      * @param graphics the graphics context
  898.      * @param x1 the x coordinate of the first vertex of the triangle
  899.      * @param y1 the y coordinate of the first vertex of the triangle
  900.      * @param x2 the x coordinate of the second vertex of the triangle
  901.      * @param y2 the y coordinate of the second vertex of the triangle
  902.      * @param x3 the x coordinate of the third vertex of the triangle
  903.      * @param y3 the y coordinate of the third vertex of the triangle
  904.      */
  905.     public void fillTriangle(Object graphics, int x1, int y1, int x2, int y2, int x3, int y3) {
  906.         fillPolygon(graphics, new int[]{x1, x2, x3}, new int[]{y1, y2, y3}, 3);
  907.     }
  908.     /**
  909.      * Draws the RGB values based on the MIDP API of a similar name. Renders a 
  910.      * series of device-independent RGB+transparency values in a specified 
  911.      * region. The values are stored in rgbData in a format with 24 bits of 
  912.      * RGB and an eight-bit alpha value (0xAARRGGBB), with the first value 
  913.      * stored at the specified offset. The scanlength  specifies the relative 
  914.      * offset within the array between the corresponding pixels of consecutive 
  915.      * rows. Any value for scanlength is acceptable (even negative values) 
  916.      * provided that all resulting references are within the bounds of the 
  917.      * rgbData array. The ARGB data is rasterized horizontally from left to 
  918.      * right within each row. The ARGB values are rendered in the region 
  919.      * specified by x, y, width and height, and the operation is subject 
  920.      * to the current clip region and translation for this Graphics object.
  921.      * 
  922.      * @param graphics the graphics context
  923.      * @param rgbData an array of ARGB values in the format 0xAARRGGBB
  924.      * @param offset the array index of the first ARGB value
  925.      * @param x the horizontal location of the region to be rendered
  926.      * @param y the vertical location of the region to be rendered
  927.      * @param w the width of the region to be rendered
  928.      * @param h the height of the region to be rendered
  929.      * @param processAlpha true if rgbData has an alpha channel, false if
  930.      * all pixels are fully opaque
  931.      */
  932.     public abstract void drawRGB(Object graphics, int[] rgbData, int offset, int x, int y, int w, int h, boolean processAlpha);
  933.     /**
  934.      * Returns the native graphics object on which all rendering operations occur
  935.      * 
  936.      * @return a native graphics context
  937.      */
  938.     public abstract Object getNativeGraphics();
  939.     /**
  940.      * Returns the native graphics object on the given native image occur
  941.      * 
  942.      * @param image the native image on which the graphics will draw
  943.      * @return a native graphics context
  944.      */
  945.     public abstract Object getNativeGraphics(Object image);
  946.     /**
  947.      * Return the width of the given characters in the given native font instance
  948.      * 
  949.      * @param nativeFont the font for which the string width should be calculated
  950.      * @param ch array of characters
  951.      * @param offset characters offsets
  952.      * @param length characters length
  953.      * @return the width of the given characters in this font instance
  954.      */
  955.     public abstract int charsWidth(Object nativeFont, char[] ch, int offset, int length);
  956.     /**
  957.      * Return the width of the given string in this font instance
  958.      * 
  959.      * @param nativeFont the font for which the string width should be calculated
  960.      * @param str the given string     * 
  961.      * @return the width of the given string in this font instance
  962.      */
  963.     public abstract int stringWidth(Object nativeFont, String str);
  964.     /**
  965.      * Return the width of the specific character when rendered alone
  966.      * 
  967.      * @param nativeFont the font for which the string width should be calculated
  968.      * @param ch the specific character
  969.      * @return the width of the specific character when rendered alone
  970.      */
  971.     public abstract int charWidth(Object nativeFont, char ch);
  972.     /**
  973.      * Return the total height of the font
  974.      * 
  975.      * @param nativeFont the font for which the string width should be calculated
  976.      * @return the total height of the font
  977.      */
  978.     public abstract int getHeight(Object nativeFont);
  979.     /**
  980.      * Return the global default font instance, if font is passed as null
  981.      * this font should be used
  982.      * 
  983.      * @return the global default font instance
  984.      */
  985.     public abstract Object getDefaultFont();
  986.     /**
  987.      * Optional operation returning the font face for the font 
  988.      * 
  989.      * @param nativeFont the font for which the string width should be calculated
  990.      * @return Optional operation returning the font face for system fonts
  991.      */
  992.     public int getFace(Object nativeFont) {
  993.         return 0;
  994.     }
  995.     /**
  996.      * Optional operation returning the font size for system fonts
  997.      * 
  998.      * @param nativeFont the font for which the string width should be calculated
  999.      * @return Optional operation returning the font size for system fonts
  1000.      */
  1001.     public int getSize(Object nativeFont) {
  1002.         return 0;
  1003.     }
  1004.     /**
  1005.      * Optional operation returning the font style for system fonts
  1006.      * 
  1007.      * @param nativeFont the font for which the string width should be calculated
  1008.      * @return Optional operation returning the font style for system fonts
  1009.      */
  1010.     public int getStyle(Object nativeFont) {
  1011.         return 0;
  1012.     }
  1013.     /**
  1014.      * Creates a new instance of a native font
  1015.      * 
  1016.      * @param face the face of the font, can be one of FACE_SYSTEM, 
  1017.      * FACE_PROPORTIONAL, FACE_MONOSPACE.
  1018.      * @param style the style of the font. 
  1019.      * The value is an OR'ed  combination of STYLE_BOLD, STYLE_ITALIC, and 
  1020.      * STYLE_UNDERLINED; or the value is zero (STYLE_PLAIN).
  1021.      * @param size the size of the font, can be one of SIZE_SMALL, 
  1022.      * SIZE_MEDIUM, SIZE_LARGE
  1023.      * @return a native font object
  1024.      */
  1025.     public abstract Object createFont(int face, int style, int size);
  1026.     /**
  1027.      * Subclasses should invoke this method, it delegates the event to the display and into
  1028.      * LWUIT.
  1029.      * 
  1030.      * @param keyCode the key for the event
  1031.      */
  1032.     protected void keyPressed(final int keyCode) {
  1033.         Display.getInstance().keyPressed(keyCode);
  1034.     }
  1035.     /**
  1036.      * Subclasses should invoke this method, it delegates the event to the display and into
  1037.      * LWUIT.
  1038.      * 
  1039.      * @param keyCode the key for the event
  1040.      */
  1041.     protected void keyReleased(final int keyCode) {
  1042.         Display.getInstance().keyReleased(keyCode);
  1043.     }
  1044.     /**
  1045.      * Subclasses should invoke this method, it delegates the event to the display and into
  1046.      * LWUIT.
  1047.      * 
  1048.      * @param x the position of the event
  1049.      * @param y the position of the event
  1050.      */
  1051.     protected void pointerDragged(final int x, final int y) {
  1052.         xPointerEvent[0] = x;
  1053.         yPointerEvent[0] = y;
  1054.         pointerDragged(xPointerEvent, yPointerEvent);
  1055.     }
  1056.     /**
  1057.      * Subclasses should invoke this method, it delegates the event to the display and into
  1058.      * LWUIT.
  1059.      * 
  1060.      * @param x the position of the event
  1061.      * @param y the position of the event
  1062.      */
  1063.     protected void pointerPressed(final int x, final int y) {
  1064.         xPointerEvent[0] = x;
  1065.         yPointerEvent[0] = y;
  1066.         pointerPressed(xPointerEvent, yPointerEvent);
  1067.     }
  1068.     /**
  1069.      * Subclasses should invoke this method, it delegates the event to the display and into
  1070.      * LWUIT.
  1071.      * 
  1072.      * @param x the position of the event
  1073.      * @param y the position of the event
  1074.      */
  1075.     protected void pointerReleased(final int x, final int y) {
  1076.         xPointerEvent[0] = x;
  1077.         yPointerEvent[0] = y;
  1078.         pointerReleased(xPointerEvent, yPointerEvent);
  1079.     }
  1080.     /**
  1081.      * Subclasses should invoke this method, it delegates the event to the display and into
  1082.      * LWUIT.
  1083.      * 
  1084.      * @param x the position of the event
  1085.      * @param y the position of the event
  1086.      */
  1087.     protected void pointerHover(final int[] x, final int[] y) {
  1088.         Display.getInstance().pointerHover(x, y);
  1089.     }
  1090.     /**
  1091.      * Subclasses should invoke this method, it delegates the event to the display and into
  1092.      * LWUIT.
  1093.      *
  1094.      * @param x the position of the event
  1095.      * @param y the position of the event
  1096.      */
  1097.     protected void pointerHoverReleased(final int[] x, final int[] y) {
  1098.         Display.getInstance().pointerHoverReleased(x, y);
  1099.     }
  1100.     /**
  1101.      * Subclasses should invoke this method, it delegates the event to the display and into
  1102.      * LWUIT.
  1103.      *
  1104.      * @param x the position of the event
  1105.      * @param y the position of the event
  1106.      */
  1107.     protected void pointerHoverReleased(final int x, final int y) {
  1108.         xPointerEvent[0] = x;
  1109.         yPointerEvent[0] = y;
  1110.         pointerHoverReleased(xPointerEvent, yPointerEvent);
  1111.     }
  1112.     /**
  1113.      * Subclasses should invoke this method, it delegates the event to the display and into
  1114.      * LWUIT.
  1115.      * 
  1116.      * @param x the position of the event
  1117.      * @param y the position of the event
  1118.      */
  1119.     protected void pointerHover(final int x, final int y) {
  1120.         xPointerEvent[0] = x;
  1121.         yPointerEvent[0] = y;
  1122.         pointerHover(xPointerEvent, yPointerEvent);
  1123.     }
  1124.     /**
  1125.      * Subclasses should invoke this method, it delegates the event to the display and into
  1126.      * LWUIT.
  1127.      * 
  1128.      * @param x the position of the event
  1129.      * @param y the position of the event
  1130.      */
  1131.     protected void pointerDragged(final int[] x, final int[] y) {
  1132.         if (hasDragStarted(x, y)) {
  1133.             
  1134.             Display.getInstance().pointerDragged(x, y);
  1135.         }
  1136.     }
  1137.     /**
  1138.      * This method can be overriden by subclasses to indicate whether a drag
  1139.      * event has started or whether the device is just sending out "noise".
  1140.      * This method is invoked by pointer dragged to determine whether to propogate
  1141.      * the actual pointer drag event to LWUIT.
  1142.      *
  1143.      * @param x the position of the current drag event
  1144.      * @param y the position of the current drag event
  1145.      * @return true if the drag should propogate into LWUIT
  1146.      */
  1147.     protected boolean hasDragStarted(final int[] x, final int[] y) {
  1148.         return hasDragStarted(x[0], y[0]);
  1149.     }
  1150.     /**
  1151.      * This method can be overriden by subclasses to indicate whether a drag
  1152.      * event has started or whether the device is just sending out "noise".
  1153.      * This method is invoked by pointer dragged to determine whether to propogate
  1154.      * the actual pointer drag event to LWUIT.
  1155.      * 
  1156.      * @param x the position of the current drag event
  1157.      * @param y the position of the current drag event
  1158.      * @return true if the drag should propogate into LWUIT
  1159.      */
  1160.     protected boolean hasDragStarted(final int x, final int y) {
  1161.         if (dragActivationCounter == 0) {
  1162.             dragActivationX = x;
  1163.             dragActivationY = y;
  1164.             dragActivationCounter++;
  1165.             return false;
  1166.         }
  1167.         //send the drag events to the form only after latency of 7 drag events,
  1168.         //most touch devices are too sensitive and send too many drag events.
  1169.         //7 is just a latency const number that is pretty good for most devices
  1170.         //this may be tuned for specific devices.
  1171.         dragActivationCounter++;
  1172.         if (dragActivationCounter > getDragAutoActivationThreshold()) {
  1173.             return true;
  1174.         }
  1175.         // have we passed the motion threshold on the X axis?
  1176.         if (((float) getDisplayWidth()) / 100.0f * ((float) getDragStartPercentage()) <=
  1177.                 Math.abs(dragActivationX - x)) {
  1178.             dragActivationCounter = getDragAutoActivationThreshold() + 1;
  1179.             return true;
  1180.         }
  1181.         // have we passed the motion threshold on the Y axis?
  1182.         if (((float) getDisplayHeight()) / 100.0f * ((float) getDragStartPercentage()) <=
  1183.                 Math.abs(dragActivationY - y)) {
  1184.             dragActivationCounter = getDragAutoActivationThreshold() + 1;
  1185.             return true;
  1186.         }
  1187.         return false;
  1188.     }
  1189.     /**
  1190.      * This method allows us to manipulate the drag started detection logic.
  1191.      * If the pointer was dragged for more than this percentage of the display size it
  1192.      * is safe to assume that a drag is in progress.
  1193.      *
  1194.      * @return motion percentage
  1195.      */
  1196.     public int getDragStartPercentage() {
  1197.         return dragStartPercentage;
  1198.     }
  1199.     /**
  1200.      * This method allows us to manipulate the drag started detection logic.
  1201.      * If the pointer was dragged for more than this percentage of the display size it
  1202.      * is safe to assume that a drag is in progress.
  1203.      *
  1204.      * @param dragStartPercentage percentage of the screen required to initiate drag
  1205.      */
  1206.     public void setDragStartPercentage(int dragStartPercentage) {
  1207.         this.dragStartPercentage = dragStartPercentage;
  1208.     }
  1209.     /**
  1210.      * This method allows subclasses to manipulate the drag started detection logic.
  1211.      * If more than this number of drag events were delivered it is safe to assume a drag has started
  1212.      * This number must be bigger than 0!
  1213.      *
  1214.      * @return number representing a minimum number of motion events to start a drag operation
  1215.      */
  1216.     protected int getDragAutoActivationThreshold() {
  1217.         return 7;
  1218.     }
  1219.     /**
  1220.      * Subclasses should invoke this method, it delegates the event to the display and into
  1221.      * LWUIT.
  1222.      * 
  1223.      * @param x the position of the event
  1224.      * @param y the position of the event
  1225.      */
  1226.     protected void pointerPressed(final int[] x, final int[] y) {
  1227.         pointerPressedX = x[0];
  1228.         pointerPressedY = y[0];
  1229.         Display.getInstance().pointerPressed(x, y);
  1230.     }
  1231.     /**
  1232.      * Subclasses should invoke this method, it delegates the event to the display and into
  1233.      * LWUIT.
  1234.      * 
  1235.      * @param x the position of the event
  1236.      * @param y the position of the event
  1237.      */
  1238.     protected void pointerReleased(final int[] x, final int[] y) {
  1239.         // this is a special case designed to detect a "flick" event on some Samsung devices
  1240.         // that send a pointerPressed/Released with widely differing X/Y values but don't send
  1241.         // the pointerDrag events in between
  1242.         if(dragActivationCounter == 0 && x[0] != pointerPressedX && y[0] != pointerPressedY) {
  1243.             hasDragStarted(pointerPressedX, pointerPressedY);
  1244.             if(hasDragStarted(x, y)) {
  1245.                 pointerDragged(pointerPressedX, pointerPressedY);
  1246.                 pointerDragged(x, y);
  1247.             }
  1248.         }
  1249.         dragActivationCounter = 0;
  1250.         Display.getInstance().pointerReleased(x, y);
  1251.     }
  1252.     /**
  1253.      * Subclasses should invoke this method, it delegates the event to the display and into
  1254.      * LWUIT.
  1255.      * 
  1256.      * @param w the size of the screen
  1257.      * @param h the size of the screen
  1258.      */
  1259.     protected void sizeChanged(int w, int h) {
  1260.         Display.getInstance().sizeChanged(w, h);
  1261.     }
  1262.     /**
  1263.      * Subclasses should invoke this method, it delegates the event to the display and into
  1264.      * LWUIT.
  1265.      * 
  1266.      * @param w the size of the screen
  1267.      * @param h the size of the screen
  1268.      */
  1269.     protected void hideNotify() {
  1270.         Display.getInstance().hideNotify();
  1271.     }
  1272.     /**
  1273.      * Subclasses should invoke this method, it delegates the event to the display and into
  1274.      * LWUIT.
  1275.      * 
  1276.      * @param w the size of the screen
  1277.      * @param h the size of the screen
  1278.      */
  1279.     protected void showNotify() {
  1280.         Display.getInstance().showNotify();
  1281.     }
  1282.     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) {
  1283.         if(cache != null) {
  1284.             Enumeration e = cache.keys();
  1285.             while(e.hasMoreElements()) {
  1286.                 int[] current = (int[])e.nextElement();
  1287.                 WeakReference currentRef = (WeakReference)cache.get(current);
  1288.                 Object currentImage = currentRef.get();
  1289.                 if(currentImage == null) {
  1290.                     cache.remove(current);
  1291.                     e = cache.keys();
  1292.                     continue;
  1293.                 }
  1294.                 if(current[0] == startColor &&
  1295.                         current[1] == endColor &&
  1296.                         current[2] == x &&
  1297.                         current[3] == y &&
  1298.                         current[5] == centerX &&
  1299.                         current[6] == centerY &&
  1300.                         current[7] == size &&
  1301.                         getImageWidth(currentImage) == width &&
  1302.                         getImageHeight(currentImage) == height) {
  1303.                     if((horizontal && current[4] == 1) || ((!horizontal) && current[4] == 0)) {
  1304.                         return currentImage;
  1305.                     }
  1306.                 }
  1307.             }
  1308.         }
  1309.         return null;
  1310.     }
  1311.     private void storeCachedGradient(Object img, Hashtable cache, int startColor, int endColor, int x, int y, boolean horizontal, int centerX, int centerY, int size) {
  1312.         int[] key;
  1313.         if(horizontal) {
  1314.             key = new int[] {startColor, endColor, x, y, 1, centerX, centerY, size};
  1315.         } else {
  1316.             key = new int[] {startColor, endColor, x, y, 0, centerX, centerY, size};
  1317.         }
  1318.         cache.put(key, new WeakReference(img));
  1319.     }
  1320.     /**
  1321.      * Draws a radial gradient in the given coordinates with the given colors,
  1322.      * doesn't take alpha into consideration when drawing the gradient.
  1323.      * Notice that a radial gradient will result in a circular shape, to create
  1324.      * a square use fillRect or draw a larger shape and clip to the appropriate size.
  1325.      *
  1326.      * @param graphics the graphics context
  1327.      * @param startColor the starting RGB color
  1328.      * @param endColor  the ending RGB color
  1329.      * @param x the x coordinate
  1330.      * @param y the y coordinate
  1331.      * @param width the width of the region to be filled
  1332.      * @param height the height of the region to be filled
  1333.      * @param relativeX indicates the relative position of the gradient within the drawing region
  1334.      * @param relativeY indicates the relative position of the gradient within the drawing region
  1335.      * @param relativeSize  indicates the relative size of the gradient within the drawing region
  1336.      */
  1337.     public void fillRectRadialGradient(Object graphics, int startColor, int endColor, int x, int y, int width, int height, float relativeX, float relativeY, float relativeSize) {
  1338.         int centerX = (int) (width * (1 - relativeX));
  1339.         int centerY = (int) (height * (1 - relativeY));
  1340.         int x2 = width / 2 - centerX;
  1341.         int y2 = height / 2 - centerY;
  1342.         int size = (int)(Math.min(width, height) * relativeSize);
  1343.         if(cacheRadialGradients()) {
  1344.             Object r = findCachedGradient(radialGradientCache, startColor, endColor, x, y, width, height, true, centerX, centerY, size);
  1345.             if(r != null) {
  1346.                 drawImage(graphics, r, x, y);
  1347.             } else {
  1348.                 r = createMutableImage(width, height, 0xffffffff);
  1349.                 Object imageGraphics = getNativeGraphics(r);
  1350.                 setColor(imageGraphics, endColor);
  1351.                 fillRect(imageGraphics, 0, 0, width, height);
  1352.                 fillRadialGradientImpl(imageGraphics, startColor, endColor, x2, y2, size, size);
  1353.                 drawImage(graphics, r, x, y);
  1354.                 if(radialGradientCache == null) {
  1355.                     radialGradientCache = new Hashtable();
  1356.                 }
  1357.                 storeCachedGradient(r, radialGradientCache, startColor, endColor, x, y, true, centerX, centerY, size);
  1358.             }
  1359.         } else {
  1360.             setColor(graphics, endColor);
  1361.             fillRect(graphics, x, y, width, height);
  1362.             fillRadialGradientImpl(graphics, startColor, endColor, x + x2, y + y2, size, size);
  1363.         }
  1364.     }
  1365.     /**
  1366.      * Draws a radial gradient in the given coordinates with the given colors,
  1367.      * doesn't take alpha into consideration when drawing the gradient.
  1368.      * Notice that a radial gradient will result in a circular shape, to create
  1369.      * a square use fillRect or draw a larger shape and clip to the appropriate size.
  1370.      *
  1371.      * @param graphics the graphics context
  1372.      * @param startColor the starting RGB color
  1373.      * @param endColor  the ending RGB color
  1374.      * @param x the x coordinate
  1375.      * @param y the y coordinate
  1376.      * @param width the width of the region to be filled
  1377.      * @param height the height of the region to be filled
  1378.      */
  1379.     public void fillRadialGradient(Object graphics, int startColor, int endColor, int x, int y, int width, int height) {
  1380.         fillRadialGradientImpl(graphics, startColor, endColor, x, y, width, height);
  1381.     }
  1382.     private void fillRadialGradientImpl(Object graphics, int startColor, int endColor, int x, int y, int width, int height) {
  1383.         int sourceR = startColor >> 16 & 0xff;
  1384.         int sourceG = startColor >> 8 & 0xff;
  1385.         int sourceB = startColor & 0xff;
  1386.         int destR = endColor >> 16 & 0xff;
  1387.         int destG = endColor >> 8 & 0xff;
  1388.         int destB = endColor & 0xff;
  1389.         int oldColor = getColor(graphics);
  1390.         int originalHeight = height;
  1391.         while (width > 0 && height > 0) {
  1392.             updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
  1393.                     destG, destB, originalHeight, height);
  1394.             fillArc(graphics, x, y, width, height, 0, 360);
  1395.             x++;
  1396.             y++;
  1397.             width -= 2;
  1398.             height -= 2;
  1399.         }
  1400.         setColor(graphics, oldColor);
  1401.     }
  1402.     private void updateGradientColor(Object nativeGraphics, int sourceR, int sourceG, int sourceB, int destR,
  1403.             int destG, int destB, int distance, int offset) {
  1404.         //int a = calculateGraidentChannel(sourceA, destA, distance, offset);
  1405.         int r = calculateGraidentChannel(sourceR, destR, distance, offset);
  1406.         int g = calculateGraidentChannel(sourceG, destG, distance, offset);
  1407.         int b = calculateGraidentChannel(sourceB, destB, distance, offset);
  1408.         int color = /*((a << 24) & 0xff000000) |*/ ((r << 16) & 0xff0000) |
  1409.                 ((g << 8) & 0xff00) | (b & 0xff);
  1410.         setColor(nativeGraphics, color);
  1411.     }
  1412.     /**
  1413.      * Converts the color channel value according to the offest within the distance
  1414.      */
  1415.     private int calculateGraidentChannel(int sourceChannel, int destChannel, int distance, int offset) {
  1416.         if (sourceChannel == destChannel) {
  1417.             return sourceChannel;
  1418.         }
  1419.         float ratio = ((float) offset) / ((float) distance);
  1420.         int pos = (int) (Math.abs(sourceChannel - destChannel) * ratio);
  1421.         if (sourceChannel > destChannel) {
  1422.             return sourceChannel - pos;
  1423.         } else {
  1424.             return sourceChannel + pos;
  1425.         }
  1426.     }
  1427.     /**
  1428.      * Draws a linear gradient in the given coordinates with the given colors, 
  1429.      * doesn't take alpha into consideration when drawing the gradient
  1430.      * 
  1431.      * @param graphics the graphics context
  1432.      * @param startColor the starting RGB color
  1433.      * @param endColor  the ending RGB color
  1434.      * @param x the x coordinate
  1435.      * @param y the y coordinate
  1436.      * @param width the width of the region to be filled
  1437.      * @param height the height of the region to be filled
  1438.      * @param horizontal indicating wheter it is a horizontal fill or vertical
  1439.      */
  1440.     public void fillLinearGradient(Object graphics, int startColor, int endColor, int x, int y, int width, int height, boolean horizontal) {
  1441.         if(cacheLinearGradients()) {
  1442.             Object r = findCachedGradient(linearGradientCache, startColor, endColor, x, y, width, height, horizontal, 0, 0, 0);
  1443.             if(r != null) {
  1444.                 drawImage(graphics, r, x, y);
  1445.             } else {
  1446.                 r = createMutableImage(width, height, 0xffffffff);
  1447.                 fillLinearGradientImpl(getNativeGraphics(r), startColor, endColor, 0, 0, width, height, horizontal);
  1448.                 drawImage(graphics, r, x, y);
  1449.                 if(linearGradientCache == null) {
  1450.                     linearGradientCache = new Hashtable();
  1451.                 }
  1452.                 storeCachedGradient(r, linearGradientCache, startColor, endColor, x, y, horizontal, 0, 0, 0);
  1453.             }
  1454.         } else {
  1455.             fillLinearGradientImpl(graphics, startColor, endColor, x, y, width, height, horizontal);
  1456.         }
  1457.     }
  1458.     private void fillLinearGradientImpl(Object graphics, int startColor, int endColor, int x, int y, int width, int height, boolean horizontal) {
  1459.         int sourceR = startColor >> 16 & 0xff;
  1460.         int sourceG = startColor >> 8 & 0xff;
  1461.         int sourceB = startColor & 0xff;
  1462.         int destR = endColor >> 16 & 0xff;
  1463.         int destG = endColor >> 8 & 0xff;
  1464.         int destB = endColor & 0xff;
  1465.         int oldColor = getColor(graphics);
  1466.         if (horizontal) {
  1467.             for (int iter = 0; iter < width; iter++) {
  1468.                 updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
  1469.                         destG, destB, width, iter);
  1470.                 drawLine(graphics, x + iter, y, x + iter, y + height);
  1471.             }
  1472.         } else {
  1473.             for (int iter = 0; iter < height; iter++) {
  1474.                 updateGradientColor(graphics, sourceR, sourceG, sourceB, destR,
  1475.                         destG, destB, height, iter);
  1476.                 drawLine(graphics, x, y + iter, x + width, y + iter);
  1477.             }
  1478.         }
  1479.         setColor(graphics, oldColor);
  1480.     }
  1481.     private boolean checkIntersection(Object g, int y0, int x1, int x2, int y1, int y2, int[] intersections, int intersectionsCount) {
  1482.         if (y0 > y1 && y0 < y2 || y0 > y2 && y0 < y1) {
  1483.             if (y1 == y2) {
  1484.                 drawLine(g, x1, y0, x2, y0);
  1485.                 return false;
  1486.             }
  1487.             intersections[intersectionsCount] = x1 + ((y0 - y1) * (x2 - x1)) / (y2 - y1);
  1488.             return true;
  1489.         }
  1490.         return false;
  1491.     }
  1492.     private int markIntersectionEdge(Object g, int idx, int[] yPoints, int[] xPoints, int nPoints, int[] intersections, int intersectionsCount) {
  1493.         intersections[intersectionsCount] = xPoints[idx];
  1494.         if ((yPoints[idx] - yPoints[(idx + 1) % nPoints]) * (yPoints[idx] - yPoints[(idx + nPoints - 1) % nPoints]) > 0) {
  1495.             intersections[intersectionsCount + 1] = xPoints[idx];
  1496.             return 2;
  1497.         }
  1498.         //Check for special case horizontal line
  1499.         if (yPoints[idx] == yPoints[(idx + 1) % nPoints]) {
  1500.             drawLine(g, xPoints[idx], yPoints[idx], xPoints[(idx + 1) % nPoints], yPoints[(idx + 1) % nPoints]);
  1501.             if ((yPoints[(idx + 1) % nPoints] - yPoints[(idx + 2) % nPoints]) * (yPoints[idx] - yPoints[(idx + nPoints - 1) % nPoints]) > 0) {
  1502.                 return 1;
  1503.             } else {
  1504.                 intersections[intersectionsCount + 1] = xPoints[idx];
  1505.                 return 2;
  1506.             }
  1507.         }
  1508.         return 1;
  1509.     }
  1510.     /**
  1511.      *  Fills a closed polygon defined by arrays of x and y coordinates. 
  1512.      *  Each pair of (x, y) coordinates defines a point.
  1513.      * 
  1514.      * @param graphics the graphics context
  1515.      *  @param xPoints - a an array of x coordinates.
  1516.      *  @param yPoints - a an array of y coordinates.
  1517.      *  @param nPoints - a the total number of points.
  1518.      */
  1519.     public void fillPolygon(Object graphics, int[] xPoints, int[] yPoints, int nPoints) {
  1520.         int[] intersections = new int[nPoints];
  1521.         int intersectionsCount = 0;
  1522.         int yMax = (int) yPoints[0];
  1523.         int yMin = (int) yPoints[0];
  1524.         for (int i = 0; i < nPoints; i++) {
  1525.             yMax = Math.max(yMax, yPoints[i]);
  1526.             yMin = Math.min(yMin, yPoints[i]);
  1527.         }
  1528.         //  Loop through the rows of the image.
  1529.         for (int row = yMin; row <= yMax; row++) {
  1530.             intersectionsCount = 0;
  1531.             for (int i = 1; i < nPoints; i++) {
  1532.                 if (checkIntersection(graphics, row, xPoints[i - 1], xPoints[i], yPoints[i - 1], yPoints[i], intersections, intersectionsCount)) {
  1533.                     intersectionsCount++;
  1534.                 }
  1535.             }
  1536.             if (checkIntersection(graphics, row, xPoints[nPoints - 1], xPoints[0], yPoints[nPoints - 1], yPoints[0], intersections, intersectionsCount)) {
  1537.                 intersectionsCount++;
  1538.             }
  1539.             for (int j = 0; j < nPoints; j++) {
  1540.                 if (row == yPoints[j]) {
  1541.                     intersectionsCount += markIntersectionEdge(graphics, j, yPoints, xPoints, nPoints, intersections, intersectionsCount);
  1542.                 }
  1543.             }
  1544.             int swap = 0;
  1545.             for (int i = 0; i < intersectionsCount; i++) {
  1546.                 for (int j = i; j < intersectionsCount; j++) {
  1547.                     if (intersections[j] < intersections[i]) {
  1548.                         swap = intersections[i];
  1549.                         intersections[i] = intersections[j];
  1550.                         intersections[j] = swap;
  1551.                     }
  1552.                 }
  1553.             }
  1554.             for (int i = 1; i < intersectionsCount; i = i + 2) {
  1555.                 drawLine(graphics, intersections[i - 1], row, intersections[i], row);
  1556.             }
  1557.         }
  1558.     }
  1559.     /**
  1560.      *  Draws a closed polygon defined by arrays of x and y coordinates. 
  1561.      *  Each pair of (x, y) coordinates defines a point.
  1562.      * 
  1563.      * @param graphics the graphics context
  1564.      *  @param xPoints - a an array of x coordinates.
  1565.      *  @param yPoints - a an array of y coordinates.
  1566.      *  @param nPoints - a the total number of points.
  1567.      */
  1568.     public void drawPolygon(Object graphics, int[] xPoints, int[] yPoints, int nPoints) {
  1569.         for (int i = 1; i < nPoints; i++) {
  1570.             drawLine(graphics, xPoints[i - 1], yPoints[i - 1], xPoints[i], yPoints[i]);
  1571.         }
  1572.         drawLine(graphics, xPoints[nPoints - 1], yPoints[nPoints - 1], xPoints[0], yPoints[0]);
  1573.     }
  1574.     /**
  1575.      * Displays the virtual keyboard on devices that support manually poping up
  1576.      * the vitual keyboard
  1577.      * 
  1578.      * @param show toggles the virtual keyboards visibility
  1579.      */
  1580.     public void setShowVirtualKeyboard(boolean show) {
  1581.     }
  1582.     /**
  1583.      * Indicates if the virtual keyboard is currently showing or not
  1584.      *
  1585.      * @return true if the virtual keyboard is showing
  1586.      */
  1587.     public boolean isVirtualKeyboardShowing() {
  1588.         return false;
  1589.     }
  1590.     /**
  1591.      * Indicates whether showing a virtual keyboard programmatically is supported 
  1592.      * 
  1593.      * @return false by default
  1594.      */
  1595.     public boolean isVirtualKeyboardShowingSupported() {
  1596.         return false;
  1597.     }
  1598.     /**
  1599.      * Returns the type of the input device one of:
  1600.      * KEYBOARD_TYPE_UNKNOWN, KEYBOARD_TYPE_NUMERIC, KEYBOARD_TYPE_QWERTY, 
  1601.      * KEYBOARD_TYPE_VIRTUAL, KEYBOARD_TYPE_HALF_QWERTY
  1602.      * 
  1603.      * @return KEYBOARD_TYPE_UNKNOWN
  1604.      */
  1605.     public int getKeyboardType() {
  1606.         return Display.KEYBOARD_TYPE_UNKNOWN;
  1607.     }
  1608.     /**
  1609.      * Indicates whether the device supports native in place editing in which case
  1610.      * lightweight input logic shouldn't be used for input.
  1611.      * 
  1612.      * @return false by default
  1613.      */
  1614.     public boolean isNativeInputSupported() {
  1615.         return false;
  1616.     }
  1617.     /**
  1618.      * Indicates whether the device supports multi-touch events, this is only
  1619.      * relevant when touch events are supported
  1620.      * 
  1621.      * @return false by default
  1622.      */
  1623.     public boolean isMultiTouch() {
  1624.         return false;
  1625.     }
  1626.     /**
  1627.      * Indicates whether the device has a double layer screen thus allowing two
  1628.      * stages to touch events: click and hover. This is true for devices such 
  1629.      * as the storm but can also be true for a PC with a mouse pointer floating 
  1630.      * on top.
  1631.      * <p>A click touch screen will also send pointer hover events to the underlying
  1632.      * software and will only send the standard pointer events on click.
  1633.      * 
  1634.      * @return false by default
  1635.      */
  1636.     public boolean isClickTouchScreen() {
  1637.         return false;
  1638.     }
  1639.     /**
  1640.      * Returns true if indexed images should be used natively
  1641.      * 
  1642.      * @return true if a native image should be used for indexed images
  1643.      */
  1644.     public boolean isNativeIndexed() {
  1645.         return false;
  1646.     }
  1647.     /**
  1648.      * Creates a native image representing the indexed image
  1649.      * 
  1650.      * @param image the indexed image
  1651.      * @return a native version of the indexed image
  1652.      */
  1653.     public Object createNativeIndexed(IndexedImage image) {
  1654.         return null;
  1655.     }
  1656.     /**
  1657.      * Create a video/media component
  1658.      * 
  1659.      * @param player object responsible for playback lifecycle
  1660.      * @return the video control
  1661.      */
  1662.     public Object createVideoComponent(Object player) {
  1663.         return null;
  1664.     }
  1665.     /**
  1666.      * Returns the video width
  1667.      * 
  1668.      * @param videoControl the control for the video
  1669.      * @return the width
  1670.      */
  1671.     public int getVideoWidth(Object videoControl) {
  1672.         return 0;
  1673.     }
  1674.     /**
  1675.      * Returns the video height
  1676.      * 
  1677.      * @param videoControl the control for the video
  1678.      * @return the height
  1679.      */
  1680.     public int getVideoHeight(Object videoControl) {
  1681.         return 0;
  1682.     }
  1683.     /**
  1684.      * Sets the video visibility
  1685.      * 
  1686.      * @param vc video control instance
  1687.      * @param visible whether the video is visible
  1688.      */
  1689.     public void setVideoVisible(Object vc, boolean visible) {
  1690.     }
  1691.     /**
  1692.      * Starts the video
  1693.      * 
  1694.      * @param player the player object
  1695.      * @param videoControl the video control
  1696.      */
  1697.     public void startVideo(Object player, Object videoControl) {
  1698.     }
  1699.     /**
  1700.      * Stop the video
  1701.      * 
  1702.      * @param player the player object
  1703.      * @param videoControl the video control
  1704.      */
  1705.     public void stopVideo(Object player, Object videoControl) {
  1706.     }
  1707.     /**
  1708.      * Set the number of times the media should loop
  1709.      * 
  1710.      * @param player the player object
  1711.      * @param count the number of times the media should loop
  1712.      */
  1713.     public void setVideoLoopCount(Object player, int count) {
  1714.     }
  1715.     /**
  1716.      * Return the duration of the media
  1717.      * 
  1718.      * @param player the player object
  1719.      * @return the duration of the media
  1720.      */
  1721.     public long getMediaTime(Object player) {
  1722.         return 0;
  1723.     }
  1724.     /**
  1725.      * "Jump" to a point in time within the media
  1726.      * 
  1727.      * @param player the player object
  1728.      * @param now the point in time to "Jump" to
  1729.      * @return the media time in microseconds
  1730.      */
  1731.     public long setMediaTime(Object player, long now) {
  1732.         return 0;
  1733.     }
  1734.     /**
  1735.      * Toggles the fullscreen mode
  1736.      * 
  1737.      * @param player the player object
  1738.      * @param fullscreen true for fullscreen mode
  1739.      */
  1740.     public void setVideoFullScreen(Object player, boolean fullscreen) {
  1741.     }
  1742.     /**
  1743.      * Paint the video for the media component
  1744.      * 
  1745.      * @param cmp the media component
  1746.      * @param fullScreen indicates whether this is fullscreen or not
  1747.      * @param nativeGraphics the native graphics object
  1748.      * @param video the native videoo control
  1749.      * @param player the native player object
  1750.      */
  1751.     public void paintVideo(Component cmp, boolean fullScreen, Object nativeGraphics, Object video,
  1752.             Object player) {
  1753.     }
  1754.     /**
  1755.      * Returns true if the image was opaque
  1756.      * 
  1757.      * @param lwuitImage the lwuit image 
  1758.      * @param nativeImage the image object to test
  1759.      * @return true if the image is opaque
  1760.      */
  1761.     public boolean isOpaque(Image lwuitImage, Object nativeImage) {
  1762.         int[] rgb = lwuitImage.getRGBCached();
  1763.         for (int iter = 0; iter < rgb.length; iter++) {
  1764.             if ((rgb[iter] & 0xff000000) != 0xff000000) {
  1765.                 return false;
  1766.             }
  1767.         }
  1768.         return true;
  1769.     }
  1770.     /**
  1771.      * Indicates whether the underlying implementation can draw using an affine
  1772.      * transform hence methods such as rotate, scale and shear would work
  1773.      *
  1774.      * @return true if an affine transformation matrix is present
  1775.      */
  1776.     public boolean isAffineSupported() {
  1777.         return false;
  1778.     }
  1779.     /**
  1780.      * Resets the affine transform to the default value
  1781.      * 
  1782.      * @param nativeGraphics the native graphics object
  1783.      */
  1784.     public void resetAffine(Object nativeGraphics) {
  1785.         System.out.println("Affine unsupported");
  1786.     }
  1787.     /**
  1788.      * Scales the coordinate system using the affine transform
  1789.      *
  1790.      * @param nativeGraphics the native graphics object
  1791.      * @param scale factor for x
  1792.      * @param scale factor for y
  1793.      */
  1794.     public void scale(Object nativeGraphics, float x, float y) {
  1795.         System.out.println("Affine unsupported");
  1796.     }
  1797.     /**
  1798.      * Rotates the coordinate system around a radian angle using the affine transform
  1799.      *
  1800.      * @param angle the rotation angle in radians
  1801.      * @param nativeGraphics the native graphics object
  1802.      */
  1803.     public void rotate(Object nativeGraphics, float angle) {
  1804.         System.out.println("Affine unsupported");
  1805.     }
  1806.     /**
  1807.      * Shear the graphics coordinate system using the affine transform
  1808.      *
  1809.      * @param shear factor for x
  1810.      * @param shear factor for y
  1811.      * @param nativeGraphics the native graphics object
  1812.      */
  1813.     public void shear(Object nativeGraphics, float x, float y) {
  1814.         System.out.println("Affine unsupported");
  1815.     }
  1816.     /**
  1817.      * Indicates whether the underlying platform supports creating an SVG Image
  1818.      *
  1819.      * @return true if the method create SVG image would return a valid image object
  1820.      * from an SVG Input stream
  1821.      */
  1822.     public boolean isSVGSupported() {
  1823.         return false;
  1824.     }
  1825.     /**
  1826.      * Creates an SVG Image from the given byte array data and the base URL
  1827.      *
  1828.      * @param baseURL URL which is used to resolve relative references within the SVG file
  1829.      * @param data the conten of the SVG file
  1830.      * @return a native image that can be used within the image object
  1831.      * @throws IOException if resource lookup fail SVG is unsupported
  1832.      */
  1833.     public Object createSVGImage(String baseURL, byte[] data) throws IOException {
  1834.         throw new IOException("SVG is not supported by this implementation");
  1835.     }
  1836.     /**
  1837.      * Returns a platform specific DOM object that can be manipulated by the user
  1838.      * to change the SVG Image
  1839.      *
  1840.      * @param svgImage the underlying image object
  1841.      * @return Platform dependent object, when JSR 226 is supported an SVGSVGElement might
  1842.      * be returned.
  1843.      */
  1844.     public Object getSVGDocument(Object svgImage) {
  1845.         throw new RuntimeException("SVG is not supported by this implementation");
  1846.     }
  1847.     /**
  1848.      * Callback to allow images animated by the underlying system to change their state
  1849.      * e.g. for SVG or animated gif support. This method returns true if an animation
  1850.      * state has changed requiring a repaint.
  1851.      *
  1852.      * @param nativeImage a native image used within the image object
  1853.      * @param lastFrame the time the last frame of animation was shown
  1854.      * @return true if a repaint is required since the image state changed, false otherwise
  1855.      */
  1856.     public boolean animateImage(Object nativeImage, long lastFrame) {
  1857.         return false;
  1858.     }
  1859.     /**
  1860.      * Returns a list of the platform names ordered by priority, platform names are
  1861.      * used to choose a font based on platform. Since a platform might support several
  1862.      * layers for choice in narrowing platform font selection
  1863.      *
  1864.      * @return the platform names ordered according to priority.
  1865.      */
  1866.     public String[] getFontPlatformNames() {
  1867.         return new String[]{"MIDP", "MIDP2"};
  1868.     }
  1869.     /**
  1870.      * Loads the truetype font from the input stream without closing the stream,
  1871.      * this method should return the native font.
  1872.      *
  1873.      * @param stream from which to load the font
  1874.      * @return the native font created from the stream
  1875.      * @throws IOException will be thrown in case of an io error
  1876.      */
  1877.     public Object loadTrueTypeFont(InputStream stream) throws IOException {
  1878.         throw new IOException("Unsupported operation");
  1879.     }
  1880.     /**
  1881.      * Returns true if the system supports dynamically loading truetype fonts from
  1882.      * a stream.
  1883.      *
  1884.      * @return true if the system supports dynamically loading truetype fonts from
  1885.      * a stream.
  1886.      */
  1887.     public boolean isTrueTypeSupported() {
  1888.         return false;
  1889.     }
  1890.     /**
  1891.      * Loads a native font based on a lookup for a font name and attributes. Font lookup
  1892.      * values can be separated by commas and thus allow fallback if the primary font
  1893.      * isn't supported by the platform.
  1894.      *
  1895.      * @param lookup string describing the font
  1896.      * @return the native font object
  1897.      */
  1898.     public Object loadNativeFont(String lookup) {
  1899.         return null;
  1900.     }
  1901.     /**
  1902.      * Indicates whether loading a font by a string is supported by the platform
  1903.      *
  1904.      * @return true if the platform supports font lookup
  1905.      */
  1906.     public boolean isLookupFontSupported() {
  1907.         return false;
  1908.     }
  1909.     /**
  1910.      * Minimizes the current application if minimization is supported by the platform (may fail).
  1911.      * Returns false if minimization failed.
  1912.      *
  1913.      * @return false if minimization failed true if it succeeded or seems to be successful
  1914.      */
  1915.     public boolean minimizeApplication() {
  1916.         return false;
  1917.     }
  1918.     /**
  1919.      * Restore the minimized application if minimization is supported by the platform
  1920.      */
  1921.     public void restoreMinimizedApplication() {
  1922.     }
  1923.     /**
  1924.      * Indicates whether an application is minimized
  1925.      *
  1926.      * @return true if the application is minimized
  1927.      */
  1928.     public boolean isMinimized() {
  1929.         return false;
  1930.     }
  1931.     /**
  1932.      * Indicates whether the implementation is interested in caching radial gradients for
  1933.      * drawing.
  1934.      *
  1935.      * @return true to activate radial gradient caching
  1936.      */
  1937.     protected boolean cacheRadialGradients() {
  1938.         return true;
  1939.     }
  1940.     /**
  1941.      * Indicates whether the implementation is interested in caching linear gradients for
  1942.      * drawing.
  1943.      *
  1944.      * @return true to activate linear gradient caching
  1945.      */
  1946.     protected boolean cacheLinearGradients() {
  1947.         return true;
  1948.     }
  1949.     /**
  1950.      * Indicates the default status to apply to the 3rd softbutton variable
  1951.      *
  1952.      * @return true if the 3rd softbutton should be set as true
  1953.      * @see com.sun.lwuit.Display#isThirdSoftButton()
  1954.      * @see com.sun.lwuit.Display#setThirdSoftButton()
  1955.      */
  1956.     public boolean isThirdSoftButton() {
  1957.         return getSoftkeyCount() < 2 && isTouchDevice();
  1958.     }
  1959.     /**
  1960.      * Indicates how many drag points are used to calculate dragging speed
  1961.      * 
  1962.      * @return the size of points to calculate the speed
  1963.      */
  1964.     public int getDragPathLength(){
  1965.         return 10;
  1966.     }
  1967.     /**
  1968.      * Indicates what drag points are valid for the drag speed calculation.
  1969.      * Points that are older then the current time - the path time are ignored
  1970.      * 
  1971.      * @return the relevance time per point
  1972.      */
  1973.     public int getDragPathTime(){
  1974.         return 200;
  1975.     }
  1976.     /**
  1977.      * This method returns the dragging speed based on the latest dragged
  1978.      * events
  1979.      * @param points array of locations
  1980.      * @param dragPathTime the time difference between each point
  1981.      * @param dragPathOffset the offset in the arrays
  1982.      * @param dragPathLength
  1983.      */
  1984.     public float getDragSpeed(float[] points, long[] dragPathTime,
  1985.             int dragPathOffset, int dragPathLength){
  1986.         long now = System.currentTimeMillis();
  1987.         final long tooold = now - getDragPathTime();
  1988.         int offset = dragPathOffset - dragPathLength;
  1989.         if (offset < 0) {
  1990.             offset = getDragPathLength() + offset;
  1991.         }
  1992.         long old = 0;
  1993.         float oldPoint = 0;
  1994.         float speed = 0;
  1995.         long timediff;
  1996.         float diff;
  1997.         float velocity;
  1998.         float f = dragPathLength;
  1999.         while (dragPathLength > 0) {
  2000.             if (dragPathTime[offset] > tooold) {
  2001.                 if (old == 0) {
  2002.                     old = dragPathTime[offset];
  2003.                     oldPoint = points[offset];
  2004.                 }
  2005.                 timediff = now - old;
  2006.                 diff = points[offset] - oldPoint;
  2007.                 if (timediff > 0) {
  2008.                     velocity = (diff / timediff) * 1.5f;
  2009.                     speed += velocity;
  2010.                 }
  2011.             }
  2012.             dragPathLength--;
  2013.             offset++;
  2014.             if (offset >= getDragPathLength()) {
  2015.                 offset = 0;
  2016.             }
  2017.         }
  2018.         f = Math.max(1, f);
  2019.         return -speed / f;
  2020.     }
  2021.     /**
  2022.      * Indicates whether LWUIT should consider the bidi RTL algorithm
  2023.      * when drawing text or navigating with the text field cursor.
  2024.      *
  2025.      * @return true if the bidi algorithm should be considered
  2026.      */
  2027.     public boolean isBidiAlgorithm() {
  2028.         return bidi;
  2029.     }
  2030.     /**
  2031.      * Indicates whether LWUIT should consider the bidi RTL algorithm
  2032.      * when drawing text or navigating with the text field cursor.
  2033.      *
  2034.      * @param activate set to true to activate the bidi algorithm, false to
  2035.      * disable it
  2036.      */
  2037.     public void setBidiAlgorithm(boolean activate) {
  2038.         bidi = activate;
  2039.     }
  2040.     /**
  2041.      * Converts the given string from logical bidi layout to visual bidi layout so
  2042.      * it can be rendered properly on the screen. This method is only necessary
  2043.      * for devices/platforms that don't have "built in" bidi support such as
  2044.      * Sony Ericsson devices.
  2045.      * See <a href="http://www.w3.org/International/articles/inline-bidi-markup/#visual">this</a>
  2046.      * for more on visual vs. logical ordering.
  2047.      *
  2048.      *
  2049.      * @param s a "logical" string with RTL characters
  2050.      * @return a "visual" renderable string
  2051.      */
  2052.     public String convertBidiLogicalToVisual(String s) {
  2053.         if(bidi) {
  2054.             if (s.length() >= 2) {
  2055.                 char[] c = s.toCharArray();
  2056.                 swapBidiChars(c, 0, s.length(), -1);
  2057.                 return new String(c);
  2058.             }
  2059.         }
  2060.         return s;
  2061.     }
  2062.     /**
  2063.      * Returns the index of the given char within the source string, the actual
  2064.      * index isn't necessarily the same when bidi is involved
  2065.      * See <a href="http://www.w3.org/International/articles/inline-bidi-markup/#visual">this</a>
  2066.      * for more on visual vs. logical ordering.
  2067.      * 
  2068.      * @param source the string in which we are looking for the position
  2069.      * @param index the "logical" location of the cursor
  2070.      * @return the "visual" location of the cursor
  2071.      */
  2072. public int getCharLocation(String source, int index) {
  2073.         if(bidi) {
  2074.      return swapBidiChars(source.toCharArray(), 0, source.length(), index);
  2075.         }
  2076.         return index;
  2077.     }
  2078.     /**
  2079.      * Returns true if the given character is an RTL character or a space
  2080.      * character
  2081.      *
  2082.      * @param c character to test
  2083.      * @return true if bidi is active and this is a
  2084.      */
  2085. public boolean isRTLOrWhitespace(char c) {
  2086.         if(bidi) {
  2087.             return isRTL(c) || c == ' ';
  2088.         }
  2089.         return false;
  2090.     }
  2091.     /**
  2092.      * Returns true if the given character is an RTL character
  2093.      *
  2094.      * @param c character to test
  2095.      * @return true if the charcter is an RTL character
  2096.      */
  2097. public boolean isRTL(char c) {
  2098.         return (c >= RTL_RANGE_BEGIN && c <= RTL_RANGE_END);
  2099.     }
  2100. private final int swapBidiChars(char[] chars, int ixStart, int len,int index) {
  2101. int destIndex = -1;
  2102. int ixEnd = ixStart + len;
  2103. int ix0, ix1;
  2104. ix0 = ix1 = ixStart;
  2105. boolean doSwap = false;
  2106.         for ( int i1 = ixStart; i1 < ixEnd; i1++ ) {
  2107.             if ( isRTL(chars[i1]) ) {
  2108.                 doSwap = true;
  2109.                 break;
  2110.             }
  2111.         }
  2112. if ( doSwap ) {
  2113. while ( ix0 < ixEnd ) {
  2114. if ( (ix1 = scanSecond(chars, ix0, ixEnd)) < 0 ) {
  2115. break;
  2116. } else {
  2117. ix0 = ix1;
  2118. ix1 = scanBackFirst(chars, ix0, ixEnd);
  2119. // swap
  2120. for ( int iy0 = ix0, iy1 = ix1-1; iy0 < iy1; iy0++, iy1--) {
  2121. char tmp = chars[iy0];
  2122. chars[iy0] = chars[iy1];
  2123. chars[iy1] = tmp;
  2124. if (index==iy1) {
  2125. //System.out.println("IY: Found char: new index="+iy0);
  2126. destIndex=iy0;
  2127. index=iy0;
  2128. }
  2129. }
  2130. ix0 = ix1;
  2131. }
  2132. }
  2133. }
  2134. if ( doSwap ) {
  2135. // swap the line
  2136. for (ix0 = ixStart, ix1 = ixEnd - 1 ; ix0 <= ix1 ; ix0++, ix1--) {
  2137. char ch0 = chars[ix0];
  2138. char ch1 = chars[ix1];
  2139. chars[ix0] = ch1;
  2140. chars[ix1] = ch0;
  2141. if (index==ix0) {
  2142. destIndex=ix1;
  2143. } else if (index==ix1) {
  2144. destIndex=ix0;
  2145. }
  2146. }
  2147. }
  2148. return destIndex;
  2149. }
  2150.     private boolean isRTLBreak(char ch1) {
  2151.         return ch1 == ')' || ch1 == ']' || ch1 == '}' || ch1 == '(' || ch1 == '[' || ch1 == '{' ;
  2152.     }
  2153.     private boolean isLTR(char c) {
  2154.         return !isRTL(c) && !isRTLBreak(c);
  2155.     }
  2156. private final int scanSecond(char[] chars, int ixStart, int ixEnd) {
  2157. int ixFound = -1;
  2158. for ( int ix = ixStart; ixFound < 0 && ix < ixEnd; ix++ ) {
  2159. if (!isRTL(chars[ix])) {
  2160. ixFound = ix;
  2161. }
  2162. return ixFound;
  2163. }
  2164. private final int scanBackFirst(char[] chars, int ixStart, int ixEnd)
  2165. {
  2166. int ix, ixFound = ixEnd;
  2167. for ( ix = ixStart+1; ix < ixEnd; ix++ ) {
  2168. if ( isRTLBreak(chars[ix])) {
  2169. ixFound = ix;
  2170. break;
  2171. }
  2172. }
  2173. for (ix = ixFound-1; ix >= ixStart; ix-- ) {
  2174. if ( isLTR(chars[ix]) ) {
  2175. ixFound = ix + 1;
  2176. break;
  2177. }
  2178. }
  2179. return ixFound;
  2180. }
  2181.     /**
  2182.      * This method is essentially equivalent to cls.getResourceAsStream(String)
  2183.      * however some platforms might define unique ways in which to load resources
  2184.      * within the implementation.
  2185.      *
  2186.      * @param cls class to load the resource from
  2187.      * @param resource relative/absolute URL based on the Java convention
  2188.      * @return input stream for the resource or null if not found
  2189.      */
  2190.     public InputStream getResourceAsStream(Class cls, String resource) {
  2191.         return cls.getResourceAsStream(resource);
  2192.     }
  2193. }