javauis/lcdui_qt/src/javax/microedition/lcdui/Graphics.java
changeset 21 2a9601315dfc
child 23 98ccebc37403
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 package javax.microedition.lcdui;
       
    18 
       
    19 import org.eclipse.swt.graphics.GC;
       
    20 import org.eclipse.swt.graphics.Internal_GfxPackageSupport;
       
    21 import org.eclipse.swt.graphics.Rectangle;
       
    22 import org.eclipse.swt.internal.qt.graphics.GraphicsContext;
       
    23 import org.eclipse.swt.internal.qt.graphics.JavaCommandBuffer;
       
    24 import org.eclipse.swt.internal.qt.graphics.FontUtils;
       
    25 
       
    26 import com.nokia.mid.ui.DirectGraphics;
       
    27 
       
    28 /**
       
    29  * Implementation of LCDUI <code>Graphics</code> class.
       
    30  */
       
    31 public class Graphics {
       
    32 
       
    33     /**
       
    34      * Constant for horizontal center alignment of the text.
       
    35      */
       
    36     public static final int HCENTER = 1;
       
    37 
       
    38     /**
       
    39      * Constant for vertical alignment of the image.
       
    40      */
       
    41     public static final int VCENTER = 2;
       
    42 
       
    43     /**
       
    44      * Constant for horizontal left alignment of the text.
       
    45      */
       
    46     public static final int LEFT = 4;
       
    47 
       
    48     /**
       
    49      * Constant for horizontal right alignment of the text.
       
    50      */
       
    51     public static final int RIGHT = 8;
       
    52 
       
    53     /**
       
    54      * Constant for vertical top alignment of the text.
       
    55      */
       
    56     public static final int TOP = 16;
       
    57 
       
    58     /**
       
    59      * Constant for vertical bottom alignment of the text.
       
    60      */
       
    61     public static final int BOTTOM = 32;
       
    62 
       
    63     /**
       
    64      * Constant for vertical baseline alignment of the text.
       
    65      */
       
    66     public static final int BASELINE = 64;
       
    67 
       
    68     /**
       
    69      * Constant for solid stroke style.
       
    70      */
       
    71     public static final int SOLID = 0;
       
    72 
       
    73     /**
       
    74      * Constant for dotted stroke style.
       
    75      */
       
    76     public static final int DOTTED = 1;
       
    77 
       
    78     static final int RGB_MASK = 0x00FFFFFF;
       
    79 
       
    80     static final int COMPONENT_MASK = 0xFF;
       
    81 
       
    82     private DirectGraphics directGraphics;
       
    83 
       
    84     // Graphics rectangle (off-screen buffer rectangle).
       
    85     // private Rectangle graphicsClientArea;
       
    86 
       
    87     // Graphics context for drawing to off-screen buffer.
       
    88     private GraphicsContext gc;
       
    89 
       
    90     // Off-screen buffer.
       
    91     //private org.eclipse.swt.internal.qt.graphics.Image frameBuffer;
       
    92 
       
    93     // Current font for rendering texts.
       
    94     private Font currentFont;
       
    95     private int currentColor;
       
    96     private int translateX;
       
    97     private int translateY;
       
    98     private int[] currentClip = new int[4];
       
    99     private int currentStrokeSyle;
       
   100 
       
   101     // Image owning the Graphics if the Graphics object belongs to an Image.
       
   102     private Image parentImage;
       
   103 
       
   104     // Flag indicating that we are in Canvas.paint() callback,
       
   105     // thus inside UI thread
       
   106     private boolean paintCallBack;
       
   107     private boolean buffered;
       
   108     private JavaCommandBuffer cmdBuffer;
       
   109     private com.nokia.mj.impl.rt.support.Finalizer finalizer;
       
   110     // serialization lock for command buffering and flush
       
   111     private final Object flushLock = new Object();
       
   112     private Canvas canvasParent;
       
   113     private CustomItem customItemParent;
       
   114     
       
   115     //Constructor
       
   116     Graphics() {
       
   117        finalizer = ((finalizer != null) ? finalizer
       
   118                 : new com.nokia.mj.impl.rt.support.Finalizer() {
       
   119                     public void finalizeImpl() {
       
   120                         if (finalizer != null) {
       
   121                             finalizer = null;
       
   122                             if (!ESWTUIThreadRunner.isDisposed()) {
       
   123                                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   124                                    public void run() {
       
   125                                       dispose();
       
   126                                    }
       
   127                                 });
       
   128                                
       
   129                             }
       
   130                         }
       
   131                     }
       
   132                 });
       
   133     }
       
   134     /**
       
   135      * Set the parent image of this Graphics.
       
   136      *
       
   137      * @param image an image
       
   138      */
       
   139     void eswtSetParentImage(final Image image) {
       
   140         if(buffered) {
       
   141             return;
       
   142         }
       
   143         if (parentImage != image) {
       
   144             parentImage = image;
       
   145 
       
   146             if (gc == null) {
       
   147                 gc = new GraphicsContext();
       
   148             }
       
   149             else {
       
   150                 gc.releaseTarget();
       
   151             }
       
   152             ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   153                 public void run() {
       
   154                     org.eclipse.swt.graphics.Image eswtImage = Image.getESWTImage(image);
       
   155                         
       
   156                     if (eswtImage != null) {
       
   157                         gc.bindTarget(Internal_GfxPackageSupport.getImage(eswtImage));
       
   158                         Rectangle clipRect = eswtImage.getBounds();
       
   159                         setClip(0, 0, clipRect.width, clipRect.height);
       
   160                     }
       
   161                     reset();
       
   162                 }});
       
   163         }
       
   164     }
       
   165 
       
   166     /**
       
   167      * Initializes this instance of Graphics to use command buffer.
       
   168      * 
       
   169      * Can be called in a non-UI thread. Not thread-safe. 
       
   170      * 
       
   171      * @param x The x-coordinate of clip
       
   172      * @param y The y-coordinate of clip
       
   173      * @param width The width of clip
       
   174      * @param height The height of clip
       
   175      */
       
   176     void initBuffered(final Canvas parent, final int x, final int y, final int width, final int height) {
       
   177       ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   178           public void run() {
       
   179               cmdBuffer = new JavaCommandBuffer();
       
   180               if (gc == null) {
       
   181                   gc = new GraphicsContext();
       
   182               }
       
   183               gc.bindTarget(cmdBuffer);
       
   184               setClip(x, y, width, height);
       
   185               reset();
       
   186               buffered = true;
       
   187               javax.microedition.lcdui.Graphics.this.canvasParent = parent;
       
   188           }});
       
   189     }
       
   190     
       
   191     /**
       
   192      * Initializes this instance of Graphics to use command buffer.
       
   193      * 
       
   194      * Can be called in a non-UI thread. Not thread-safe. 
       
   195      * 
       
   196      * @param x The x-coordinate of clip
       
   197      * @param y The y-coordinate of clip
       
   198      * @param width The width of clip
       
   199      * @param height The height of clip
       
   200      */
       
   201     void initBuffered(CustomItem parent, int x, int y, int width, int height) {
       
   202         cmdBuffer = new JavaCommandBuffer();
       
   203         if (gc == null) {
       
   204             gc = new GraphicsContext();
       
   205         }
       
   206         gc.bindTarget(cmdBuffer);
       
   207         setClip(x, y, width, height);
       
   208         reset();
       
   209         buffered = true;
       
   210         this.customItemParent = parent;
       
   211     }
       
   212 
       
   213 	/**
       
   214 	 * Resets the command buffer contents.
       
   215 	 * 
       
   216 	 * This is safe to call only in the UI thread. 
       
   217 	 */
       
   218     void resetCommandBuffer() {
       
   219         gc.releaseTarget();
       
   220         cmdBuffer.reset();
       
   221         gc.bindTarget(cmdBuffer);
       
   222         // write settings which were active before flush 
       
   223         // if they are not the same as defaults
       
   224         gc.setFont(Font.getESWTFont(currentFont).handle);
       
   225         gc.setBackgroundColor(currentColor, false);
       
   226         gc.setForegroundColor(currentColor, false);
       
   227         if ((translateX != 0) || (translateY != 0)) { 
       
   228             gc.translate(translateX, translateY);
       
   229         }
       
   230         
       
   231         // Note that if called in a non-UI thread then the size of the
       
   232         // Canvas or CustomItem can change between getting the height and
       
   233         // getting the width. Those are modified by the UI thread and there
       
   234         // is no synchronization. 
       
   235         int w = 0;
       
   236         int h = 0;
       
   237         if(canvasParent != null) {
       
   238             w = canvasParent.getWidth();
       
   239             h = canvasParent.getHeight();
       
   240         } else {
       
   241             w = customItemParent.getContentWidth();
       
   242             h = customItemParent.getContentHeight();
       
   243         }
       
   244         
       
   245         if((currentClip[0] != 0) && (currentClip[1] != 0) && 
       
   246            (currentClip[2] != w) && (currentClip[2] != h)) {
       
   247             gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
       
   248         }
       
   249         if (currentStrokeSyle != SOLID) {
       
   250             gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
       
   251         }
       
   252     }
       
   253     
       
   254     /**
       
   255      * Returns the current command buffer or null. 
       
   256      * 
       
   257      * This method is thread-safe. 
       
   258      */
       
   259     JavaCommandBuffer getCommandBuffer() {
       
   260         return cmdBuffer;
       
   261     }
       
   262     
       
   263     /**
       
   264      * Get the parent image of this Graphics.
       
   265      */
       
   266     Image getParentImage() {
       
   267         return parentImage;
       
   268     }
       
   269 
       
   270     /**
       
   271      * Set Graphics context to a target - the GC is coming from paint event.
       
   272      *
       
   273      * @param eswtGC
       
   274      */
       
   275     void eswtSetGC(final GC eswtGC) {
       
   276        if(buffered) {
       
   277             return;
       
   278         }
       
   279         gc = eswtGC.getGCData().internalGc;
       
   280         ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   281             public void run() {
       
   282                 Rectangle clipRect = eswtGC.getClipping();
       
   283                 setClip(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
       
   284                 reset();
       
   285             }});
       
   286     }
       
   287 
       
   288     /**
       
   289      * Disposes Graphics context resources.
       
   290      */
       
   291     void dispose() {
       
   292         if (parentImage != null) {
       
   293             parentImage = null;
       
   294         }
       
   295         if(gc != null) {
       
   296             ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   297                 public void run() {
       
   298                     gc.dispose();
       
   299                 }});
       
   300           gc = null;
       
   301         }
       
   302         if (cmdBuffer != null) {
       
   303           cmdBuffer = null;
       
   304         }
       
   305     }
       
   306 
       
   307     /**
       
   308      * Resets Graphics state to initial.
       
   309      */
       
   310     void reset() {
       
   311         setColor(0, 0, 0);
       
   312         setFont(Font.getDefaultFont());
       
   313         setStrokeStyle(Graphics.SOLID);
       
   314         this.translateX = 0;
       
   315         this.translateY = 0;
       
   316     }
       
   317 
       
   318     /**
       
   319      * Cleans the Canvas background.
       
   320      */
       
   321     void cleanBackground(Rectangle area) {
       
   322         int savedColor = currentColor;
       
   323         setColor(255, 255, 255);
       
   324         fillRect(area.x, area.y, area.width, area.height);
       
   325         setColor(savedColor);
       
   326     }
       
   327 
       
   328     /**
       
   329      * Cleans the Canvas background.
       
   330      */
       
   331     void cleanBackground(int x, int y, int w, int h) {
       
   332         int savedColor = currentColor;
       
   333         setColor(255, 255, 255);
       
   334         fillRect(x, y, w, h);
       
   335         setColor(savedColor);
       
   336     }
       
   337 
       
   338     /**
       
   339      * Sets flag indicating that we are in Canvas.paint() callback
       
   340      */
       
   341     void beginPaint() {
       
   342         paintCallBack = true;
       
   343     }
       
   344 
       
   345     /**
       
   346      * Sets flag indicating that we are exiting Canvas.paint() callback
       
   347      */
       
   348     void endPaint() {
       
   349         paintCallBack = false;
       
   350     }
       
   351 
       
   352     /**
       
   353      * Provides the serialization lock for buffer writing and flushing
       
   354      * @return lock used for synchronizing command buffer access
       
   355      */
       
   356     Object getLock() {
       
   357         return flushLock;
       
   358     }
       
   359     
       
   360     /**
       
   361      * Sets coordinate translation. Translations are cumulative.
       
   362      *
       
   363      * @param xDelta x-shift for coordinates.
       
   364      * @param yDelta y-shift for coordinates.
       
   365      */
       
   366     public void translate(int xDelta, int yDelta) {
       
   367         synchronized(flushLock) {
       
   368             if(!buffered) { 
       
   369                 final int xDelta_ = xDelta;
       
   370                 final int yDelta_ = yDelta;
       
   371                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   372                     public void run() {
       
   373                         gc.translate(xDelta_, yDelta_);
       
   374                     }});
       
   375             } else {
       
   376                 gc.translate(xDelta, yDelta);
       
   377             }
       
   378         }
       
   379         translateX += xDelta;
       
   380         translateY += yDelta;
       
   381     }
       
   382 
       
   383     /**
       
   384      * Returns current X-shift of coordinate translation.
       
   385      *
       
   386      * @return Current X-shift of coordinate translation.
       
   387      */
       
   388     public int getTranslateX() {
       
   389         return translateX;
       
   390     }
       
   391 
       
   392     /**
       
   393      * Returns current Y-shift of coordinate translation.
       
   394      *
       
   395      * @return current Y-shift of coordinate translation.
       
   396      */
       
   397     public int getTranslateY() {
       
   398         return translateY;
       
   399     }
       
   400 
       
   401     /**
       
   402      * Returns current color in 0x00RRGGBB format.
       
   403      *
       
   404      * @return Current color in 0x00RRGGBB format.
       
   405      */
       
   406     public int getColor() {
       
   407         return currentColor;
       
   408     }
       
   409 
       
   410     /**
       
   411      * Returns red component of current color.
       
   412      *
       
   413      * @return Red component of current color in the range of 0-255.
       
   414      */
       
   415     public int getRedComponent() {
       
   416         return currentColor >> 16;
       
   417     }
       
   418 
       
   419     /**
       
   420      * Returns green component of current color.
       
   421      *
       
   422      * @return Green component of current color in the range of 0-255.
       
   423      */
       
   424     public int getGreenComponent() {
       
   425         return (currentColor >> 8) & COMPONENT_MASK;
       
   426     }
       
   427 
       
   428     /**
       
   429      * Returns blue component of current color.
       
   430      *
       
   431      * @return Blue component of current color in the range of 0-255.
       
   432      */
       
   433     public int getBlueComponent() {
       
   434         return currentColor & COMPONENT_MASK;
       
   435     }
       
   436 
       
   437     /**
       
   438      * Returns current grayscale color.
       
   439      *
       
   440      * @return Returns current grayscale color in the range 0-255.
       
   441      */
       
   442     public int getGrayScale() {
       
   443         return (getRedComponent() + getGreenComponent() + getBlueComponent()) / 3;
       
   444     }
       
   445 
       
   446     /**
       
   447      * Sets the current color by color components for red, green and blue.
       
   448      *
       
   449      * @param r - red component of the color to be set.
       
   450      * @param g - green component of the color to be set.
       
   451      * @param b - blue component of the color to be set.
       
   452      */
       
   453     public void setColor(int r, int g, int b) {
       
   454         if (r < 0 || r > 255 ||
       
   455             g < 0 || g > 255 ||
       
   456             b < 0 || b > 255 ) {
       
   457                 throw new IllegalArgumentException();
       
   458         }
       
   459         synchronized(flushLock) {
       
   460             if(!buffered) { 
       
   461                 final int r_ = r;
       
   462                 final int g_ = g;
       
   463                 final int b_ = b;
       
   464                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   465                     public void run() {
       
   466                         gc.setForegroundColor(r_, g_, b_);
       
   467                         gc.setBackgroundColor(r_, g_, b_);
       
   468                     }});
       
   469             } else {
       
   470                 gc.setForegroundColor(r, g, b);
       
   471                 gc.setBackgroundColor(r, g, b);
       
   472             }
       
   473         }
       
   474         currentColor = ((r << 16) | (g << 8) | b) & RGB_MASK;
       
   475     }
       
   476 
       
   477     /**
       
   478      * Sets the current color.
       
   479      *
       
   480      * @param RGB - color to be set in the form of 0x00RRGGBB.
       
   481      */
       
   482     public void setColor(int RGB) {
       
   483         int maskedRGB = RGB & RGB_MASK;
       
   484         final int r = maskedRGB >> 16;
       
   485         final int g = (maskedRGB >> 8) & COMPONENT_MASK;
       
   486         final int b = maskedRGB & COMPONENT_MASK;
       
   487         synchronized(flushLock) {
       
   488             if(!buffered) { 
       
   489                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   490                     public void run() {
       
   491                         gc.setForegroundColor(r, g, b);
       
   492                         gc.setBackgroundColor(r, g, b);
       
   493                     }});
       
   494             } else {
       
   495                 gc.setForegroundColor(r, g, b);
       
   496                 gc.setBackgroundColor(r, g, b);
       
   497             }
       
   498         }
       
   499         currentColor = maskedRGB;
       
   500     }
       
   501 
       
   502     /**
       
   503      * Sets gray-scale color.
       
   504      *
       
   505      * @param val - gray-scale value to be set in the range of 0-255.
       
   506      */
       
   507     public void setGrayScale(int val) {
       
   508         if ( (val < 0) || (val > 255)) {
       
   509         throw new IllegalArgumentException();
       
   510         }
       
   511         final int col = val & COMPONENT_MASK;
       
   512         synchronized(flushLock) {
       
   513             if(!buffered) { 
       
   514                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   515                     public void run() {
       
   516                         gc.setForegroundColor(col, col, col);
       
   517                         gc.setBackgroundColor(col, col, col);
       
   518                     }});
       
   519             } else {
       
   520                 gc.setForegroundColor(col, col, col);
       
   521                 gc.setBackgroundColor(col, col, col);
       
   522             }
       
   523         }
       
   524         currentColor = ((col << 16) | (col << 8) | col) & RGB_MASK;
       
   525     }
       
   526 
       
   527     /**
       
   528      * Returns the current font.
       
   529      *
       
   530      * @return Current font.
       
   531      */
       
   532     public Font getFont() {
       
   533         return currentFont;
       
   534     }
       
   535 
       
   536     /**
       
   537      * Sets the font to be used for string rendering.
       
   538      *
       
   539      * @param newFont - the font to be used for string rendering.
       
   540      */
       
   541     public void setFont(Font newFont) {
       
   542         synchronized(flushLock) {
       
   543             if(!buffered) { 
       
   544                 final Font newFont_ = newFont;
       
   545                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   546                     public void run() {
       
   547                         gc.setFont(Font.getESWTFont(newFont_).handle);
       
   548                     }});
       
   549             } else {
       
   550                 gc.setFont(Font.getESWTFont(newFont).handle);
       
   551             }
       
   552         }
       
   553         currentFont = newFont;
       
   554     }
       
   555 
       
   556     /**
       
   557      * Returns left bound of clip rectangle.
       
   558      *
       
   559      * @return Left bound of clip rectangle.
       
   560      */
       
   561     public int getClipX() {
       
   562         return currentClip[0];
       
   563     }
       
   564 
       
   565     /**
       
   566      * Returns top bound of clip rectangle.
       
   567      *
       
   568      * @return Top bound of clip rectangle.
       
   569      */
       
   570     public int getClipY() {
       
   571         return currentClip[1];
       
   572     }
       
   573 
       
   574     /**
       
   575      * Returns width of clip rectangle.
       
   576      *
       
   577      * @return Width of clip rectangle.
       
   578      */
       
   579     public int getClipWidth() {
       
   580         return currentClip[2];
       
   581     }
       
   582 
       
   583     /**
       
   584      * Returns height of clip rectangle.
       
   585      *
       
   586      * @return Height of clip rectangle.
       
   587      */
       
   588     public int getClipHeight() {
       
   589         return currentClip[3];
       
   590     }
       
   591 
       
   592     /**
       
   593      * Intersects current clip rectangle with the specified one.
       
   594      *
       
   595      * @param x - left bound of the clip rectangle to intersect with the
       
   596      *            current one.
       
   597      * @param y - top bound of the clip rectangle to intersect with the
       
   598      *            current one.
       
   599      * @param w - width of the clip rectangle to intersect with the current one.
       
   600      * @param h - height of the clip rectangle to intersect with the current
       
   601      *            one.
       
   602      */
       
   603     public void clipRect(int x, int y, int w, int h) {
       
   604         final int cx2 = Math.min( currentClip[0] + currentClip[2], x + w );
       
   605         final int cy2 = Math.min( currentClip[1] + currentClip[3], y + h );
       
   606         // setting of clip to Java Graphics
       
   607         currentClip[0] = Math.max( x, currentClip[0]);
       
   608         currentClip[1] = Math.max( y, currentClip[1]);
       
   609         currentClip[2] = cx2 - currentClip[0];
       
   610         currentClip[3] = cy2 - currentClip[1];
       
   611         synchronized(flushLock) {
       
   612             if(!buffered) { 
       
   613                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   614                     public void run() {
       
   615                         gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
       
   616                     }});
       
   617             } else {
       
   618                 gc.setClip(currentClip[0], currentClip[1], currentClip[2], currentClip[3], false);
       
   619             }
       
   620         }
       
   621     }
       
   622 
       
   623     /**
       
   624      * Sets the clip rectangle.
       
   625      *
       
   626      * @param x - left bound of the new clip rectangle.
       
   627      * @param y - top bound of the new clip rectangle.
       
   628      * @param w - width of the new clip rectangle.
       
   629      * @param h - height of the new clip rectangle.
       
   630      */
       
   631     public void setClip(int x, int y, int w, int h) {
       
   632         synchronized(flushLock) {
       
   633             if(!buffered) { 
       
   634                 final int x_ = x;
       
   635                 final int y_ = y;
       
   636                 final int w_ = w;
       
   637                 final int h_ = h;
       
   638         
       
   639                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   640                     public void run() {
       
   641                         gc.setClip(x_, y_, w_, h_, false);
       
   642                     }});
       
   643             } else {
       
   644                 gc.setClip(x, y, w, h, false);
       
   645             }
       
   646         }
       
   647         currentClip[0] = x;
       
   648         currentClip[1] = y;
       
   649         currentClip[2] = w;
       
   650         currentClip[3] = h;
       
   651     }
       
   652 
       
   653     /**
       
   654      * Draws a line with current color and current stroke style.
       
   655      *
       
   656      * @param xStart - X-coordinate of line starting point.
       
   657      * @param yStart - Y-coordinate of line starting point.
       
   658      * @param xEnd - X-coordinate of line end point.
       
   659      * @param yEnd - Y-coordinate of line end point.
       
   660      */
       
   661     public void drawLine(int xStart, int yStart, int xEnd, int yEnd) {
       
   662         synchronized(flushLock) {
       
   663             if(!buffered) { 
       
   664                 final int xs_ = xStart;
       
   665                 final int ys_ = yStart;
       
   666                 final int xe_ = xEnd;
       
   667                 final int ye_ = yEnd;
       
   668         
       
   669                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   670                     public void run() {
       
   671                         gc.drawLine(xs_, ys_, xe_, ye_);
       
   672                     }});
       
   673             } else {
       
   674                 gc.drawLine(xStart, yStart, xEnd, yEnd);
       
   675             }
       
   676         }
       
   677     }
       
   678 
       
   679     /**
       
   680      * Fills a rectangle with current color.
       
   681      *
       
   682      * @param x - x coordinate of top left corner
       
   683      * @param y - y coordinate of top left corner
       
   684      * @param w - width of the rectangle
       
   685      * @param h - height of the rectangle
       
   686      */
       
   687     public void fillRect(int x, int y, int w, int h) {
       
   688         if ((w < 0) || (h < 0)) {
       
   689             return;
       
   690         }
       
   691         synchronized(flushLock) {
       
   692             if(!buffered) { 
       
   693                 final int x_ = x;
       
   694                 final int y_ = y;
       
   695                 final int w_ = w;
       
   696                 final int h_ = h;
       
   697         
       
   698                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   699                     public void run() {
       
   700                         gc.fillRect(x_, y_, w_, h_);
       
   701                     }});
       
   702             } else {
       
   703                 gc.fillRect(x, y, w, h);
       
   704             }
       
   705         }
       
   706     }
       
   707 
       
   708     /**
       
   709      * Draws a rectangle with specified color and stroke style.
       
   710      *
       
   711      * @param x - x coordinate of top left corner
       
   712      * @param y - y coordinate of top left corner
       
   713      * @param w - width of the rectangle
       
   714      * @param h - height of the rectangle
       
   715      */
       
   716     public void drawRect(int x, int y, int w, int h) {
       
   717         if ((w < 0) || (h < 0)) {
       
   718             return;
       
   719         }
       
   720         synchronized(flushLock) {
       
   721             if(!buffered) {
       
   722                 final int x_ = x;
       
   723                 final int y_ = y;
       
   724                 final int w_ = w;
       
   725                 final int h_ = h;
       
   726                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   727                     public void run() {
       
   728                         gc.drawRect(x_, y_, w_, h_);
       
   729                     }});
       
   730             } else {
       
   731                 gc.drawRect(x, y, w, h);
       
   732             }
       
   733         }
       
   734     }
       
   735 
       
   736     /**
       
   737      * Draws a rounded rectangle with specified color and stroke style.
       
   738      *
       
   739      * @param x - x coordinate of top left corner
       
   740      * @param y - y coordinate of top left corner
       
   741      * @param w - width of the rectangle
       
   742      * @param h - height of the rectangle
       
   743      * @param arcW - arc width for corner rounding.
       
   744      * @param arcH - arc height for corner rounding.
       
   745      */
       
   746     public void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH) {
       
   747         if ((w < 0) || (h < 0) || (arcW < 0) || (arcH < 0)) {
       
   748             return;
       
   749         }
       
   750         synchronized(flushLock) {
       
   751             if(!buffered) {
       
   752                 final int x_ = x;
       
   753                 final int y_ = y;
       
   754                 final int w_ = w;
       
   755                 final int h_ = h;
       
   756                 final int arcW_ = arcW;
       
   757                 final int arcH_ = arcH;
       
   758                 
       
   759                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   760                     public void run() {
       
   761                         gc.drawRoundRect(x_, y_, w_, h_, arcW_, arcH_);
       
   762                     }});
       
   763             } else {
       
   764                 gc.drawRoundRect(x, y, w, h, arcW, arcH);
       
   765             }
       
   766         }
       
   767     }
       
   768 
       
   769     /**
       
   770      * Fills a rounded rectangle with specified color.
       
   771      *
       
   772      * @param x - x coordinate of top left corner
       
   773      * @param y - y coordinate of top left corner
       
   774      * @param w - width of the rectangle
       
   775      * @param h - height of the rectangle
       
   776      * @param arcW - arc width for corner rounding.
       
   777      * @param arcH - arc height for corner rounding.
       
   778      */
       
   779     public void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH) {
       
   780         if ((w < 0) || (h < 0) || (arcW < 0) || (arcH < 0)) {
       
   781             return;
       
   782         }
       
   783         synchronized(flushLock) {
       
   784             if(!buffered) {
       
   785                 final int x_ = x;
       
   786                 final int y_ = y;
       
   787                 final int w_ = w;
       
   788                 final int h_ = h;
       
   789                 final int arcW_ = arcW;
       
   790                 final int arcH_ = arcH;
       
   791                 
       
   792                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   793                     public void run() {
       
   794                         gc.fillRoundRect(x_, y_, w_, h_, arcW_, arcH_);
       
   795                     }});
       
   796             } else {
       
   797                 gc.fillRoundRect(x, y, w, h, arcW, arcH);
       
   798             }
       
   799         }
       
   800     }
       
   801 
       
   802     /**
       
   803      * Fills an arc with specified color.
       
   804      *
       
   805      * @param x - X-coordinate of top left corner of the rectangle to contain
       
   806      *            the arc.
       
   807      * @param y - Y-coordinate of top left corner of the rectangle to contain
       
   808      *            the arc.
       
   809      * @param w - width of the rectangle to contain the arc.
       
   810      * @param h - height of the rectangle to contain the arc.
       
   811      * @param startAngle - starting angle of the arc in degrees.
       
   812      * @param arcAngle - angle to spread the arc in degrees.
       
   813      */
       
   814     public void fillArc(int x, int y, int w, int h, int startAngle, int arcAngle) {
       
   815         if ((w < 0) || (h < 0)) {
       
   816             return;
       
   817         }
       
   818         synchronized(flushLock) {
       
   819             if(!buffered) {
       
   820                 final int x_ = x;
       
   821                 final int y_ = y;
       
   822                 final int w_ = w;
       
   823                 final int h_ = h;
       
   824                 final int startAngle_ = startAngle;
       
   825                 final int arcAngle_ = arcAngle;
       
   826                 
       
   827                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   828                     public void run() {
       
   829                         gc.fillArc(x_, y_, w_, h_, startAngle_, arcAngle_);
       
   830                     }});
       
   831             } else {
       
   832                 gc.fillArc(x, y, w, h, startAngle, arcAngle);
       
   833             }
       
   834         }
       
   835     }
       
   836 
       
   837     /**
       
   838      * Draws an arc with specified color and stroke style.
       
   839      *
       
   840      * @param x - X-coordinate of top left corner of the rectangle to contain
       
   841      *            the arc.
       
   842      * @param y - Y-coordinate of top left corner of the rectangle to contain
       
   843      *            the arc.
       
   844      * @param w - width of the rectangle to contain the arc.
       
   845      * @param h - height of the rectangle to contain the arc.
       
   846      * @param startAngle - starting angle of the arc in degrees.
       
   847      * @param arcAngle - angle to spread the arc in degrees.
       
   848      */
       
   849     public void drawArc(int x, int y, int w, int h, int startAngle, int arcAngle) {
       
   850         if ((w < 0) || (h < 0)) {
       
   851             return;
       
   852         }
       
   853         synchronized(flushLock) {
       
   854             if(!buffered) {
       
   855                 final int x_ = x;
       
   856                 final int y_ = y;
       
   857                 final int w_ = w;
       
   858                 final int h_ = h;
       
   859                 final int startAngle_ = startAngle;
       
   860                 final int arcAngle_ = arcAngle;
       
   861                 
       
   862                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   863                     public void run() {
       
   864                         gc.drawArc(x_, y_, w_, h_, startAngle_, arcAngle_);
       
   865                     }});
       
   866             } else {
       
   867                 gc.drawArc(x, y, w, h, startAngle, arcAngle);
       
   868             }
       
   869         }
       
   870     }
       
   871 
       
   872     /**
       
   873      * Draws a string with specified color and font.
       
   874      *
       
   875      * @param string - the string to draw.
       
   876      * @param xPos - X-coordinate of the anchor point.
       
   877      * @param yPos - Y-coordinate of the anchor point
       
   878      * @param anch - anchor, specifies the way to locate the text around the anchor
       
   879      *            point. May be the combination of Graphics.TOP,
       
   880      *            Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
       
   881      *            Graphics.RIGHT, Graphics.HCENTER.
       
   882      */
       
   883     public void drawString(String string, int xPos, int yPos, int anch) {
       
   884         if (string == null) {
       
   885             throw new NullPointerException(
       
   886                     MsgRepository.GRAPHICS_EXCEPTION_STRING_IS_NULL);
       
   887         }
       
   888 
       
   889         if (!checkTextAnchors(anch)) {
       
   890             throw new IllegalArgumentException(
       
   891                     MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
       
   892         }
       
   893 
       
   894         final int alignments = GraphicsContext.ALIGNMENT_TOP | GraphicsContext.ALIGNMENT_LEFT;
       
   895         final int[] boundingBox = new int[4];
       
   896         final String localStr = string;
       
   897         
       
   898         if (paintCallBack) {
       
   899             gc.getTextBoundingBox(boundingBox, string, alignments, 0);
       
   900         }
       
   901         else {
       
   902             ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   903                 public void run() {
       
   904                     FontUtils fu = new FontUtils(Font.getESWTFont(currentFont).handle);
       
   905                     fu.getBoundingRect(boundingBox, localStr);
       
   906                 }
       
   907             });
       
   908         }
       
   909 
       
   910         // boundingBox[RECT_X] - top-left x of the text bounding box
       
   911         // boundingBox[RECT_Y] - top-left y of the text bounding box
       
   912         // boundingBox[RECT_WIDTH] - the width of the text bounding box
       
   913         // boundingBox[RECT_HEIGHT] - the height of the text bounding box
       
   914 
       
   915         // Arrange vertical alignments
       
   916         int y = yPos;
       
   917         if (isFlag(anch, Graphics.BOTTOM)) {
       
   918             y = yPos - boundingBox[GraphicsContext.RECT_HEIGHT];
       
   919         }
       
   920         if (isFlag(anch, Graphics.BASELINE)) {
       
   921             y = yPos - currentFont.getBaselinePosition();
       
   922         }
       
   923 
       
   924         // Arrange horizontal alignments
       
   925         int x = xPos;
       
   926         if (isFlag(anch, Graphics.RIGHT)) {
       
   927             x = xPos - boundingBox[GraphicsContext.RECT_WIDTH];
       
   928         }
       
   929         if (isFlag(anch, Graphics.HCENTER)) {
       
   930             x = xPos - boundingBox[GraphicsContext.RECT_WIDTH] / 2;
       
   931         }
       
   932         synchronized(flushLock) {
       
   933             if(!buffered) {
       
   934                 final int x_ = x;
       
   935                 final int y_ = y;
       
   936                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
   937                     public void run() {
       
   938                         gc.drawString(localStr, x_, y_, true);
       
   939                     }});
       
   940             } else {
       
   941                 gc.drawString(localStr, x, y, true);
       
   942             }
       
   943         }
       
   944     }
       
   945 
       
   946     private static boolean isFlag(int anchor, int flag) {
       
   947         return (anchor & flag) != 0;
       
   948     }
       
   949 
       
   950     /**
       
   951      * Draws a string with specified color and font.
       
   952      *
       
   953      * @param string - the string to draw.
       
   954      * @param offset - offset of substring in the string.
       
   955      * @param length - length of substring.
       
   956      * @param xPos - X-coordinate of the anchor point.
       
   957      * @param yPos - Y-coordinate of the anchor point
       
   958      * @param anch - anchor, specifies the way to locate the text around the
       
   959      *            anchor point. May be the combination of Graphics.TOP,
       
   960      *            Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
       
   961      *            Graphics.RIGHT, Graphics.HCENTER.
       
   962      */
       
   963     public void drawSubstring(java.lang.String string, int offset, int length,
       
   964             int xPos, int yPos, int anch) {
       
   965         drawString(string.substring(offset, length), xPos, yPos, anch);
       
   966     }
       
   967 
       
   968     /**
       
   969      * Draws a character with specified color and font.
       
   970      *
       
   971      * @param c - character to draw.
       
   972      * @param xPos - X-coordinate of the anchor point.
       
   973      * @param yPos - Y-coordinate of the anchor point
       
   974      * @param anch - anchor, specifies the way to locate the text around the
       
   975      *            anchor point. May be the combination of Graphics.TOP,
       
   976      *            Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
       
   977      *            Graphics.RIGHT, Graphics.HCENTER.
       
   978      */
       
   979     public void drawChar(char c, int xPos, int yPos, int anch) {
       
   980         drawString(String.valueOf(c), xPos, yPos, anch);
       
   981     }
       
   982 
       
   983     /**
       
   984      * Draws characters from array with specified color and font.
       
   985      *
       
   986      * @param ch -character array to draw.
       
   987      * @param offset - offset of the starting character in the array.
       
   988      * @param length - length of character sequence from the array to draw.
       
   989      * @param xPos - X-coordinate of the anchor point.
       
   990      * @param yPos - Y-coordinate of the anchor point
       
   991      * @param anch - anchor, specifies the way to locate the text around the
       
   992      *            anchor point. May be the combination of Graphics.TOP,
       
   993      *            Graphics.BOTTOM, Graphics.BASELINE, Graphics.LEFT,
       
   994      *            Graphics.RIGHT, Graphics.HCENTER.
       
   995      */
       
   996     public void drawChars(char[] ch, int offset, int length,
       
   997                           int xPos, int yPos, int anch) {
       
   998         if (ch == null) {
       
   999             throw new NullPointerException(
       
  1000                     MsgRepository.GRAPHICS_EXCEPTION_ARRAY_IS_NULL);
       
  1001         }
       
  1002         String str = null;
       
  1003         try {
       
  1004             str = String.valueOf(ch, offset, length);
       
  1005         }
       
  1006         catch (Exception e) {
       
  1007             throw new ArrayIndexOutOfBoundsException(
       
  1008                     MsgRepository.GRAPHICS_EXCEPTION_ARRAY_OUT_OF_BOUNDS);
       
  1009         }
       
  1010 
       
  1011         drawString(str, xPos, yPos, anch);
       
  1012     }
       
  1013 
       
  1014     /**
       
  1015      * Checks if anchors combination is valid.
       
  1016      */
       
  1017     private boolean checkTextAnchors(int anch) {
       
  1018         boolean retVal = false;
       
  1019 
       
  1020         int vertMask = Graphics.TOP | Graphics.BASELINE | Graphics.BOTTOM;
       
  1021         int horMask = Graphics.LEFT | Graphics.RIGHT | Graphics.HCENTER;
       
  1022 
       
  1023         if (anch == 0) {
       
  1024             return true;
       
  1025         }
       
  1026 
       
  1027         if ((anch & ~(vertMask | horMask)) != 0) {
       
  1028             return false;
       
  1029         }
       
  1030 
       
  1031         int vertAchor = anch & vertMask;
       
  1032         int horAchor = anch & horMask;
       
  1033 
       
  1034         if ((vertAchor == Graphics.TOP)
       
  1035             || (vertAchor == Graphics.BASELINE)
       
  1036             || (vertAchor == Graphics.BOTTOM)) {
       
  1037             retVal = true;
       
  1038         }
       
  1039 
       
  1040         if ((horAchor == Graphics.LEFT)
       
  1041                 || (vertAchor == Graphics.RIGHT)
       
  1042                 || (vertAchor == Graphics.HCENTER)) {
       
  1043             retVal = true;
       
  1044         }
       
  1045 
       
  1046         return retVal;
       
  1047     }
       
  1048 
       
  1049     /**
       
  1050      * Draw an Image to the graphical context.
       
  1051      *
       
  1052      * @param image - Image to be drawn.
       
  1053      * @param xPos - X-coordinate of the anchor point.
       
  1054      * @param yPos - Y-coordinate of the anchor point.
       
  1055      * @param anch - anchor value.
       
  1056      */
       
  1057     public void drawImage(javax.microedition.lcdui.Image image, int xPos,
       
  1058             int yPos, int anch) {
       
  1059 
       
  1060         if (image == null) {
       
  1061             throw new NullPointerException(
       
  1062                     MsgRepository.IMAGE_EXCEPTION_IS_NULL);
       
  1063         }
       
  1064         if (!checkImageAnchors(anch)) {
       
  1065             throw new IllegalArgumentException(
       
  1066                     MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
       
  1067         }
       
  1068 
       
  1069         int y = yPos;
       
  1070         if (isFlag(anch, Graphics.VCENTER)) {
       
  1071             y = yPos - image.getHeight() / 2;
       
  1072         }
       
  1073         if (isFlag(anch, Graphics.BOTTOM)) {
       
  1074             y = yPos - image.getHeight();
       
  1075         }
       
  1076 
       
  1077         int x = xPos;
       
  1078         if (isFlag(anch, Graphics.HCENTER)) {
       
  1079             x = xPos - image.getWidth() / 2;
       
  1080         }
       
  1081         if (isFlag(anch, Graphics.RIGHT)) {
       
  1082             x = xPos - image.getWidth();
       
  1083         }
       
  1084 
       
  1085         synchronized(flushLock) {
       
  1086             if(!buffered) {
       
  1087                 final int x_ = x;
       
  1088                 final int y_ = y;
       
  1089                 final org.eclipse.swt.internal.qt.graphics.Image image_ = 
       
  1090                     Internal_GfxPackageSupport.getImage(Image.getESWTImage(image));
       
  1091                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1092                     public void run() {
       
  1093                         gc.drawImage(image_, x_, y_);
       
  1094                     }});
       
  1095             } else {
       
  1096                 gc.drawImage(Internal_GfxPackageSupport.getImage(Image.getESWTImage(image)), x, y);
       
  1097             }
       
  1098         }
       
  1099     }
       
  1100 
       
  1101     /**
       
  1102      * Checks if anchors combination is valid.
       
  1103      */
       
  1104     private boolean checkImageAnchors(int anch) {
       
  1105         boolean retVal = false;
       
  1106 
       
  1107         int vertMask = Graphics.TOP | Graphics.VCENTER | Graphics.BOTTOM;
       
  1108         int horMask = Graphics.LEFT | Graphics.RIGHT | Graphics.HCENTER;
       
  1109 
       
  1110         if (anch == 0) {
       
  1111             return true;
       
  1112         }
       
  1113 
       
  1114         if ((anch & ~(vertMask | horMask)) != 0) {
       
  1115             return false;
       
  1116         }
       
  1117 
       
  1118         int vertAchor = anch & vertMask;
       
  1119         int horAchor = anch & horMask;
       
  1120 
       
  1121         if ((vertAchor == Graphics.TOP)
       
  1122             || (vertAchor == Graphics.VCENTER)
       
  1123             || (vertAchor == Graphics.BOTTOM)) {
       
  1124             retVal = true;
       
  1125         }
       
  1126 
       
  1127         if ((horAchor == Graphics.LEFT)
       
  1128                 || (vertAchor == Graphics.RIGHT)
       
  1129                 || (vertAchor == Graphics.HCENTER)) {
       
  1130             retVal = true;
       
  1131         }
       
  1132 
       
  1133         return retVal;
       
  1134     }
       
  1135 
       
  1136     /**
       
  1137      * Sets the stroke style for drawing graphical primitives.
       
  1138      *
       
  1139      * @param newStyle - new style, valid values are Graphics.SOLID and
       
  1140      *            Graphics.DOTTED.
       
  1141      * @throws IllegalArgumentException if the new style value is invalid.
       
  1142      */
       
  1143     public void setStrokeStyle(int newStyle) {
       
  1144         if (newStyle == currentStrokeSyle) {
       
  1145             return;
       
  1146         }
       
  1147         if (newStyle == SOLID) {
       
  1148             synchronized(flushLock) {
       
  1149                 if(!buffered) {
       
  1150                     ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1151                         public void run() {
       
  1152                             gc.setStrokeStyle(GraphicsContext.STROKE_SOLID);
       
  1153                         }});
       
  1154                 } else {
       
  1155                     gc.setStrokeStyle(GraphicsContext.STROKE_SOLID);
       
  1156                 }
       
  1157             }
       
  1158         } else {
       
  1159             if (newStyle == DOTTED) {
       
  1160                 synchronized(flushLock) {
       
  1161                     if(!buffered) {
       
  1162                         ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1163                             public void run() {
       
  1164                                 gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
       
  1165                             }});
       
  1166                     } else {
       
  1167                         gc.setStrokeStyle(GraphicsContext.STROKE_DOT);
       
  1168                     }
       
  1169                 }
       
  1170             } else {
       
  1171                 throw new IllegalArgumentException(
       
  1172                     MsgRepository.GRAPHICS_EXCEPTION_ILLEGAL_STROKE_STYLE);
       
  1173             }
       
  1174         }
       
  1175         currentStrokeSyle = newStyle;
       
  1176     }
       
  1177 
       
  1178     /**
       
  1179      * Returns current stroke style.
       
  1180      *
       
  1181      * @return Current stroke style.
       
  1182      */
       
  1183     public int getStrokeStyle() {
       
  1184         return currentStrokeSyle;
       
  1185     }
       
  1186 
       
  1187     /**
       
  1188      * Returns the color that will be used if the specified color is requested.
       
  1189      *
       
  1190      * @param color - color to use in 0x00RRGGBB form.
       
  1191      * @return Color that will be actually used in 0x00RRGGBB form.
       
  1192      */
       
  1193     public int getDisplayColor(int color) {
       
  1194         return color & RGB_MASK;
       
  1195     }
       
  1196 
       
  1197     /**
       
  1198      * Renders 0xAARRGGBB pixels.
       
  1199      *
       
  1200      * @param rgb - array of ARGB values
       
  1201      * @param offset - index of the first value in the array.
       
  1202      * @param scanlength - relative distance in the array between. corresponding
       
  1203      *            pixels of consecutive rows.
       
  1204      * @param x - X-coordinate of the top-left corner of the rectangle to be
       
  1205      *            rendered.
       
  1206      * @param y - Y-coordinate of the top-left corner of the rectangle to be
       
  1207      *            rendered.
       
  1208      * @param w - width of the rectangle to be rendered.
       
  1209      * @param h - height of the rectangle to be rendered.
       
  1210      * @param alpha - true if alpha values should be rendered, false otherwise.
       
  1211      */
       
  1212     public void drawRGB(int[] rgb,
       
  1213                         int offset,
       
  1214                         int scanlength,
       
  1215                         int x,
       
  1216                         int y,
       
  1217                         int w,
       
  1218                         int h,
       
  1219                         boolean alpha) {
       
  1220 
       
  1221         if (rgb == null) {
       
  1222             throw new NullPointerException(
       
  1223                 MsgRepository.IMAGE_EXCEPTION_DATA_IS_NULL);
       
  1224         }
       
  1225         synchronized(flushLock) {
       
  1226             if(!buffered) {
       
  1227                 final int[] rgb_ = rgb;
       
  1228                 final int offset_ = offset;
       
  1229                 final int scanlength_ = scanlength;
       
  1230                 final int x_ = x;
       
  1231                 final int y_ = y;
       
  1232                 final int w_ = w;
       
  1233                 final int h_ = h;
       
  1234                 final boolean alpha_ = alpha;
       
  1235                 
       
  1236                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1237                     public void run() {
       
  1238                         gc.drawRGB(rgb_, offset_, scanlength_, x_, y_, w_, h_, alpha_);
       
  1239                     }});
       
  1240             } else {
       
  1241                 gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha);
       
  1242             }
       
  1243         }
       
  1244     }
       
  1245 
       
  1246     /**
       
  1247      * Fills the specified triangle with current color.
       
  1248      *
       
  1249      * @param xPos1 - X-coordinate of first vertex.
       
  1250      * @param yPos1 - Y-coordinate of first vertex.
       
  1251      * @param xPos2 - X-coordinate of second vertex.
       
  1252      * @param yPos2 - Y-coordinate of second vertex.
       
  1253      * @param xPos3 - X-coordinate of third vertex.
       
  1254      * @param yPos3 - Y-coordinate of third vertex.
       
  1255      */
       
  1256     public void fillTriangle(int xPos1,
       
  1257                              int yPos1,
       
  1258                              int xPos2,
       
  1259                              int yPos2,
       
  1260                              int xPos3,
       
  1261                              int yPos3) {
       
  1262         final int[] points = {xPos1, yPos1, xPos2, yPos2, xPos3, yPos3};
       
  1263         synchronized(flushLock) {
       
  1264             if(!buffered) {
       
  1265                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1266                     public void run() {
       
  1267                         gc.fillPolygon(points);
       
  1268                     }});
       
  1269             } else {
       
  1270                 gc.fillPolygon(points);
       
  1271             }
       
  1272         }
       
  1273     }
       
  1274 
       
  1275     /**
       
  1276      * Copies the specified area.
       
  1277      *
       
  1278      * @param xFrom - X-coordinate of the top-left corner of the region to copy.
       
  1279      * @param yFrom - Y-coordinate of the top-left corner of the region to copy.
       
  1280      * @param w - width of the region to copy.
       
  1281      * @param h - height of the region to copy.
       
  1282      * @param xTo - X-coordinate of the anchor point to copy region to.
       
  1283      * @param yTo - Y-coordinate of the anchor point to copy region to.
       
  1284      * @param anch - anchor point specification.
       
  1285      */
       
  1286     public void copyArea(int xFrom,
       
  1287                          int yFrom,
       
  1288                          int w,
       
  1289                          int h,
       
  1290                          int xTo,
       
  1291                          int yTo,
       
  1292                          int anch) {
       
  1293 
       
  1294         if (this.parentImage == null) {
       
  1295             // this Graphics belongs to a screen device.
       
  1296             throw new IllegalStateException(
       
  1297                 MsgRepository.GRAPHICS_EXCEPTION_DESTINATION_IS_SCREEN);
       
  1298         }
       
  1299 
       
  1300         if (!javax.microedition.lcdui.Image.validateRegion(parentImage
       
  1301                 .getWidth(), parentImage.getHeight(), xFrom, yFrom, w, h)) {
       
  1302             throw new IllegalArgumentException(
       
  1303                 MsgRepository.IMAGE_EXCEPTION_INVALID_REGION);
       
  1304         }
       
  1305 
       
  1306         // Arrange vertical alignments
       
  1307         int destY = yTo;
       
  1308         if (isFlag(anch, Graphics.BOTTOM)) {
       
  1309             destY = yTo - h;
       
  1310         }
       
  1311         if (isFlag(anch, Graphics.VCENTER)) {
       
  1312             destY = yTo - h / 2;
       
  1313         }
       
  1314 
       
  1315         // Arrange horizontal alignments
       
  1316         int destX = xTo;
       
  1317         if (isFlag(anch, Graphics.RIGHT)) {
       
  1318             destX = xTo - w;
       
  1319         }
       
  1320         if (isFlag(anch, Graphics.HCENTER)) {
       
  1321             destX = xTo - w / 2;
       
  1322         }
       
  1323 
       
  1324         synchronized(flushLock) {
       
  1325             if(!buffered) {
       
  1326                 final int x1 = xFrom;
       
  1327                 final int y1 = yFrom;
       
  1328                 final int width = w;
       
  1329                 final int height = h;
       
  1330                 final int x2 = destX;
       
  1331                 final int y2 = destY;
       
  1332 
       
  1333                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1334                     public void run() {
       
  1335                         gc.copyArea(x1, y1, width, height, x2, y2);
       
  1336                     }});
       
  1337             } else {
       
  1338                 gc.copyArea(xFrom, yFrom, w, h, destX, destY);
       
  1339             }
       
  1340         }
       
  1341     }
       
  1342 
       
  1343     /**
       
  1344      * Renders a portion of source image with possible transforms.
       
  1345      *
       
  1346      * @param srcImage - source Image
       
  1347      * @param xSrc - X-coordinate of the top-left corner of the rectangle in
       
  1348      *            source image.
       
  1349      * @param ySrc - Y-coordinate of the top-left corner of the rectangle in
       
  1350      *            source image.
       
  1351      * @param width - width of the rectangle in source image.
       
  1352      * @param height - height of the rectangle in source image.
       
  1353      * @param transform - transform to apply to the image before rendering.
       
  1354      * @param xDst - X-coordinate of the anchor point in destination.
       
  1355      * @param yDst - Y-coordinate of the anchor point in destination.
       
  1356      * @param anch - anchor point definition.
       
  1357      */
       
  1358     public void drawRegion(javax.microedition.lcdui.Image srcImage,
       
  1359                            int xSrc,
       
  1360                            int ySrc,
       
  1361                            int width,
       
  1362                            int height,
       
  1363                            int transform,
       
  1364                            int xDst,
       
  1365                            int yDst,
       
  1366                            int anch) {
       
  1367       
       
  1368         if (srcImage == null) {
       
  1369             throw new NullPointerException(
       
  1370                     MsgRepository.IMAGE_EXCEPTION_IS_NULL);
       
  1371         }
       
  1372         if (srcImage == parentImage) {
       
  1373             throw new IllegalArgumentException(
       
  1374                     MsgRepository.GRAPHICS_EXCEPTION_SAME_SOURCE_AND_DESTINATION);
       
  1375         }
       
  1376         if (!javax.microedition.lcdui.Image.validateTransform(transform)) {
       
  1377             throw new IllegalArgumentException(
       
  1378                     MsgRepository.IMAGE_EXCEPTION_INVALID_TRANSFORM);
       
  1379         }
       
  1380         if (!checkImageAnchors(anch)) {
       
  1381             throw new IllegalArgumentException(
       
  1382                     MsgRepository.GRAPHICS_EXCEPTION_INVALID_ANCHOR);
       
  1383         }
       
  1384         if (!javax.microedition.lcdui.Image.validateRegion(srcImage.getWidth(),
       
  1385                 srcImage.getHeight(), xSrc, ySrc, width, height)) {
       
  1386             throw new IllegalArgumentException(
       
  1387                     MsgRepository.IMAGE_EXCEPTION_INVALID_REGION);
       
  1388         }
       
  1389 
       
  1390         // Arrange vertical alignments
       
  1391         int y = yDst;
       
  1392         if (isFlag(anch, Graphics.VCENTER)) {
       
  1393             y = yDst - srcImage.getHeight() / 2;
       
  1394         }
       
  1395         if (isFlag(anch, Graphics.BOTTOM)) {
       
  1396             y = yDst - srcImage.getHeight();
       
  1397         }
       
  1398 
       
  1399         // Arrange horizontal alignments
       
  1400         int x = xDst;
       
  1401         if (isFlag(anch, Graphics.HCENTER)) {
       
  1402             x = xDst - srcImage.getWidth() / 2;
       
  1403         }
       
  1404         if (isFlag(anch, Graphics.RIGHT)) {
       
  1405             x = xDst - srcImage.getWidth();
       
  1406         }
       
  1407         
       
  1408         final int gcTransform = Image.getCgTransformValue(transform);
       
  1409         synchronized(flushLock) {
       
  1410             if(!buffered) { 
       
  1411                 final int localXDst = x;
       
  1412                 final int localYDst = y;
       
  1413                 final int localW = width;
       
  1414                 final int localH = height;
       
  1415                 final int localXSrc = xSrc;
       
  1416                 final int localYSrc = ySrc;
       
  1417                 final org.eclipse.swt.internal.qt.graphics.Image localImage = 
       
  1418                     Internal_GfxPackageSupport.getImage(Image.getESWTImage(srcImage));
       
  1419                 ESWTUIThreadRunner.safeSyncExec(new Runnable() {
       
  1420                     public void run() {
       
  1421                         gc.drawImage(localImage, localXDst, localYDst, localW, localH, localXSrc, localYSrc, localW, localH, gcTransform);
       
  1422                     }});
       
  1423             } else {
       
  1424                 gc.drawImage(Internal_GfxPackageSupport.getImage(Image.getESWTImage(srcImage)), 
       
  1425                              x, y, width, height, xSrc, ySrc, width, height, gcTransform);
       
  1426             }
       
  1427         }
       
  1428     }
       
  1429 
       
  1430     /**
       
  1431      * Return DirectGraphics associated with this instance.
       
  1432      */
       
  1433     DirectGraphics getDirectGraphics() {
       
  1434         if (directGraphics == null) {
       
  1435             directGraphics = new DirectGraphicsImpl(this);
       
  1436         }
       
  1437         return directGraphics;
       
  1438     }
       
  1439 
       
  1440     /**
       
  1441      * Return native graphic context.
       
  1442      */
       
  1443     GraphicsContext getGc() {
       
  1444         return gc;
       
  1445     }
       
  1446 
       
  1447 }