javauis/lcdui_qt/src/javax/microedition/lcdui/Buffer.java
branchRCL_3
changeset 65 ae942d28ec0e
equal deleted inserted replaced
60:6c158198356e 65:ae942d28ec0e
       
     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 
       
    18 package javax.microedition.lcdui;
       
    19 
       
    20 import org.eclipse.swt.widgets.Control;
       
    21 import org.eclipse.swt.widgets.Widget;
       
    22 import org.eclipse.swt.graphics.Point;
       
    23 import org.eclipse.swt.graphics.Rectangle;
       
    24 import org.eclipse.swt.internal.qt.OS;
       
    25 import org.eclipse.swt.internal.qt.graphics.GraphicsContext;
       
    26 import org.eclipse.swt.internal.qt.graphics.JavaCommandBuffer;
       
    27 import org.eclipse.swt.internal.qt.graphics.WindowSurface;
       
    28 
       
    29 /**
       
    30  * This class works a proxy between instances of Graphics class and common graphics
       
    31  * (command buffer and GraphicsContext). The relation of this class to Graphics is one-to-many, i.e.
       
    32  * one GraphicsBuffer instance handles multiple Graphics instances.
       
    33  *
       
    34  * Each LCDUI API class instance providing access to Graphics (Image, Canvas, GameCanvas, CustomItem),
       
    35  * must instantiate one GraphicsBuffer and use it for creating instances of Graphics class.
       
    36  *
       
    37  * The implementation is not thread safe, thus all serialization must be implemented in
       
    38  * callers, for instance the Graphics implementation serializes all calls to this class.
       
    39  * Furthermore this class does not take care of switching to UI thread, it must be done by
       
    40  * caller object.
       
    41  */
       
    42 
       
    43 abstract class Buffer
       
    44 {
       
    45 
       
    46     // Default values for Graphics 
       
    47     final static Font defaultFont = Font.getDefaultFont();
       
    48     final static int defaultColor = 0xff000000;
       
    49     final static int defaultStrokeStyle = Graphics.SOLID;
       
    50     final static int defaultTranslateX = 0;
       
    51     final static int defaultTranslateY = 0;
       
    52 
       
    53     // Constants for buffer host types
       
    54     final static int HOST_TYPE_IMAGE = 1;
       
    55     final static int HOST_TYPE_CANVAS = 2;
       
    56     final static int HOST_TYPE_CUSTOMITEM = 3;
       
    57 
       
    58     // Flags for raising settings validation
       
    59     // FORCE_SETTINGS Forces settings to validated also in case
       
    60     // there's only one Graphics instance as client, normally 
       
    61     // settings are not checked in such case
       
    62     final static int NONE            = 0;
       
    63     final static int COLOR           = 1;
       
    64     final static int CLIP            = 2;
       
    65     final static int FONT            = 4;
       
    66     final static int STROKESTYLE     = 8;
       
    67     final static int COORDS_TRANSLATION = 16; 
       
    68     final static int FORCE_SETTINGS    = 32; 
       
    69 
       
    70     // Graphics settings active in buffer
       
    71     // all values are comparable to those
       
    72     // in Graphics except font which is stored
       
    73     // as handle instead of LCDUI Font
       
    74     private int bufferFontHandle;
       
    75     private int bufferColor;
       
    76     private int bufferStrokeStyle;
       
    77     private int bufferTranslateX;
       
    78     private int bufferTranslateY;
       
    79     private Rectangle bufferClip;
       
    80 
       
    81     private GraphicsContext gc;
       
    82     private JavaCommandBuffer commandBuffer;
       
    83     private Rectangle hostBounds;
       
    84     private Graphics currentClient;
       
    85     private boolean isInitialized;
       
    86     private int clientCount;
       
    87     
       
    88     private boolean isSurfaceSessionOpen;
       
    89 
       
    90     /**
       
    91      * Constructor
       
    92      */
       
    93     protected Buffer()
       
    94     {
       
    95         hostBounds = new Rectangle(0,0,0,0);
       
    96         bufferClip = new Rectangle(0,0,0,0);
       
    97         bufferFontHandle = 0;
       
    98         bufferColor = 0xff000000;
       
    99         bufferStrokeStyle = Graphics.SOLID;
       
   100         bufferTranslateX = 0;
       
   101         bufferTranslateY = 0;
       
   102     }
       
   103 
       
   104     /**
       
   105      * Creates Buffer instance based on the type of given host object 
       
   106      * and the platform (symbian/linux) currently running on.
       
   107      * 
       
   108      * @param host The host target where pixels are drawn. Given object must be Canvas, CustomItem or Image.
       
   109      * @param control The eSWT control associated with the target, or null if the host is Image
       
   110      * @return New buffer instance
       
   111      */
       
   112     static Buffer createInstance(Object host, Control control)
       
   113     {
       
   114         if(host instanceof Canvas) 
       
   115         {
       
   116             if(OS.windowServer == OS.WS_SYMBIAN_S60)
       
   117             {   
       
   118                 return new CanvasBufferSymbian((Canvas) host, control);
       
   119             }
       
   120             else if(OS.windowServer == OS.WS_X11)
       
   121             {
       
   122                 return new CanvasBufferLinux((Canvas) host, control);
       
   123             }
       
   124             return null;
       
   125         } 
       
   126         else if(host instanceof CustomItem)
       
   127         {
       
   128             if(OS.windowServer == OS.WS_SYMBIAN_S60)
       
   129             {   
       
   130                 return new CustomItemBufferSymbian((CustomItem) host, control);
       
   131             }
       
   132             else if(OS.windowServer == OS.WS_X11)
       
   133             {
       
   134                 return new CustomItemBufferLinux((CustomItem) host, control);
       
   135             }
       
   136             return null;
       
   137         } 
       
   138         else if(host instanceof Image) 
       
   139         {
       
   140             return new ImageBuffer((Image) host);   
       
   141         }
       
   142         return null;
       
   143     }
       
   144     
       
   145     /**
       
   146      * Initializes data, called once
       
   147      */
       
   148     protected void init()
       
   149     {
       
   150         clientCount = 0;
       
   151         gc = new GraphicsContext();
       
   152         commandBuffer = new JavaCommandBuffer();
       
   153         gc.bindTarget(commandBuffer);
       
   154         writeControlBoundsToBuffer(false);
       
   155         isInitialized = true;
       
   156     }
       
   157 
       
   158     /**
       
   159      * Defines the bounds of the host.
       
   160      * Bounds are used for restricting the rendering in
       
   161      * the area of the control that is being updated. 
       
   162      *
       
   163      * @param crtl The Control of the host
       
   164      * @param clienArea The area of the control which can be drawn by Graphics
       
   165      */
       
   166     void setControlBounds(final Control control)
       
   167     {
       
   168         // This implementation is based on the fact that
       
   169         // the QWindowSurface has the size of the shell active area
       
   170         // not the whole display, thus Shell clientArea equals QWindowSurface.
       
   171         // This might change in future if/when Qt starts
       
   172         // rendering e.g. the status pane i.e. the whole display
       
   173         // to window surface
       
   174         Point controlLoc = control.toDisplay(0,0);
       
   175         Point shellLoc = control.getShell().toDisplay(0,0);
       
   176         hostBounds.x = controlLoc.x - shellLoc.x;
       
   177         hostBounds.y = controlLoc.y - shellLoc.y;
       
   178         hostBounds.width = control.getBounds().width;
       
   179         hostBounds.height = control.getBounds().height;
       
   180     }
       
   181 
       
   182     /**
       
   183      * Defines the bounds of the host.
       
   184      *
       
   185      * @param crtl The Control of the host
       
   186      * @param clienArea The area of the control which can be drawn by Graphics
       
   187      */
       
   188     void setImageBounds(int width, int height)
       
   189     {
       
   190         hostBounds.x = 0;
       
   191         hostBounds.y = 0;
       
   192         hostBounds.width = width;
       
   193         hostBounds.height = height;
       
   194     }
       
   195 
       
   196     /**
       
   197      * Prepares surface for a new frame and starts paint session. 
       
   198      * Must be called in UI thread (sync calls this automatically)
       
   199      * and at the start of new frame. The rectangle provided as 
       
   200      * arguments are in control coordinates.
       
   201      * 
       
   202      * @param x The x-coordinate of the area to be painted
       
   203      * @param y The y-coordinate of the area to be painted
       
   204      * @param w The width of the area to be painted
       
   205      * @param h The height of the area to be painted
       
   206      */
       
   207     void startFrame(int x, int y, int w, int h)
       
   208     {
       
   209         if(!isSurfaceSessionOpen)
       
   210         {
       
   211             beginPaint(x, y, w, h);
       
   212             isSurfaceSessionOpen = true;
       
   213         }
       
   214     }
       
   215     
       
   216     /**
       
   217      * Ends frame painting session. Must be called in UI thread and
       
   218      * at the end of the frame. BlitToDisplay calls this automatically.
       
   219      */
       
   220     void endFrame()
       
   221     {
       
   222         if(isSurfaceSessionOpen)
       
   223         {
       
   224             endPaint();
       
   225             isSurfaceSessionOpen = false;
       
   226         }
       
   227     }
       
   228     
       
   229     /**
       
   230      * Transfers the result of rendering to display.
       
   231      * @param gc The graphics context used for blit, may be null in some cases
       
   232      * @param widget The widget that is the target 
       
   233      */
       
   234     void blitToDisplay(GraphicsContext gc, Widget widget)
       
   235     {
       
   236         endFrame();
       
   237         blit(gc, widget);
       
   238     }
       
   239     
       
   240     /** 
       
   241      * Prepares surface for painting, implemented by
       
   242      * child implementation.
       
   243      * @param x The x-coordinate of the area to be painted
       
   244      * @param y The y-coordinate of the area to be painted
       
   245      * @param w The width of the area to be painted
       
   246      * @param h The height of the area to be painted
       
   247      */
       
   248     abstract void beginPaint(int x, int y, int w, int h);
       
   249     
       
   250     /**
       
   251      * Ends frame painting session. Must be called in UI thread and
       
   252      * at the end of the frame. Implemented by
       
   253      * child implementation.
       
   254      */
       
   255     abstract void endPaint();
       
   256     
       
   257     /**
       
   258      * Performs binding to target in host specific way. Implemented by
       
   259      * child implementation.
       
   260      */
       
   261     abstract void bindToHost(GraphicsContext gc);
       
   262     
       
   263     /** 
       
   264      * Performs the actual blit operation in child class implementation.
       
   265      * @param gc The graphics context used for blit, may be null in some cases
       
   266      * @param widget The widget that is the target 
       
   267      */
       
   268     abstract void blit(GraphicsContext gc, Widget widget);
       
   269     
       
   270     /**
       
   271      * Getter for the host of the buffer, implemented by
       
   272      * child implementation.
       
   273      * @return The host
       
   274      */
       
   275     abstract Object getHost();
       
   276 
       
   277     /**
       
   278      * Getter for the host type,implemented by
       
   279      * child implementation.
       
   280      * @return One of host types defined in this class
       
   281      */
       
   282     abstract int getHostType();
       
   283 
       
   284     /**
       
   285      * Status checker that indicates if this instance has requested a synchronous paint event, 
       
   286      * implemented by child implementation.
       
   287      * @return True if this instance has requested a redraw paint event, otherwise false
       
   288      */
       
   289     abstract boolean isPaintingActive(); 
       
   290     
       
   291     /**
       
   292      * Creates and returns new Graphics instance
       
   293      * @return new Graphics instance
       
   294      */
       
   295     Graphics getGraphics()
       
   296     {
       
   297         if(!isInitialized)
       
   298         {
       
   299             init();
       
   300         }
       
   301         clientCount++;
       
   302         // In case this is the first Graphics instance
       
   303         // write the default values to the buffer
       
   304         if(clientCount == 1) 
       
   305         {
       
   306             writeDefaultValuesToBuffer();   
       
   307         }
       
   308         return new Graphics(this, hostBounds );
       
   309     }
       
   310 
       
   311     /**
       
   312      * Synchronizes this buffer with the actual target
       
   313      * must be called in UI thread. If no Graphics instances
       
   314      * are created, sync has no effect. This variant always closes 
       
   315      * the surface session unconditionally
       
   316      */
       
   317     void sync() 
       
   318     {
       
   319         sync(true);
       
   320     }
       
   321     
       
   322     /**
       
   323      * Synchronizes this buffer with the actual target
       
   324      * must be called in UI thread. If no Graphics instances
       
   325      * are created, sync has no effect
       
   326      * 
       
   327      * @param closeSurfaceSession If true the endFrame is called after sync has been 
       
   328      *                            performed closing the surface session, otherwise
       
   329      *                            endFrame is performed and surface session is left open
       
   330      */
       
   331     void sync(boolean closeSurfaceSession)
       
   332     {
       
   333         if(!isInitialized)
       
   334         {
       
   335             return;
       
   336         }
       
   337         
       
   338         // if there's nothing to flush return
       
   339         if(!commandBuffer.containsDrawnPrimitives())
       
   340         {
       
   341             return;
       
   342         }
       
   343         
       
   344         // Start surface session if not started yet
       
   345         startFrame(hostBounds.x, hostBounds.y , hostBounds.width , hostBounds.height);
       
   346         
       
   347         doRelease();
       
   348         bindToHost(gc);
       
   349         gc.render(commandBuffer);
       
   350         doRelease();
       
   351 
       
   352         // Close surface session
       
   353         if(closeSurfaceSession)
       
   354         {
       
   355             endFrame();
       
   356         }
       
   357         
       
   358         // Reset commands
       
   359         commandBuffer.reset();
       
   360 
       
   361         // Write last settings to buffer
       
   362         // as they are reset in bind
       
   363         gc.bindTarget(commandBuffer);
       
   364         gc.setFont(bufferFontHandle);
       
   365         gc.setBackgroundColor(bufferColor, true);
       
   366         gc.setForegroundColor(bufferColor, true);
       
   367         writeControlBoundsToBuffer(true);
       
   368     }
       
   369 
       
   370     /**
       
   371      * Decreases the client reference count,
       
   372      * should be called by Graphics instances when
       
   373      * they are about to be disposed
       
   374      */
       
   375     void removeRef()
       
   376     {
       
   377         clientCount--;
       
   378     }
       
   379 
       
   380     /**
       
   381      * Disposes this instance
       
   382      */
       
   383     void dispose()
       
   384     {
       
   385         if(gc != null) 
       
   386         {
       
   387             doRelease();
       
   388             gc.dispose();
       
   389             gc = null;
       
   390         }
       
   391         commandBuffer = null;
       
   392     }
       
   393 
       
   394     void copyArea(int x1, int y1, int width, int height, int x2, int y2, Graphics client)
       
   395     {
       
   396         gc.copyArea(x1, y1, width, height, x2, y2);
       
   397     }
       
   398 
       
   399     void fillRect(int x, int y, int w, int h, Graphics client)
       
   400     {
       
   401         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION), client);
       
   402         gc.fillRect(x, y, w, h);
       
   403     }
       
   404 
       
   405     void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH, Graphics client)
       
   406     {
       
   407         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION), client);
       
   408         gc.fillRoundRect(x, y, w, h, arcW, arcH);
       
   409     }
       
   410 
       
   411     void fillArc(int x, int y, int w, int h, int startAngle, int arcAngle, Graphics client)
       
   412     {
       
   413         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION), client);
       
   414         gc.fillArc(x, y, w, h, startAngle, arcAngle);
       
   415     }
       
   416 
       
   417     void fillTriangle(int[] points, Graphics client)
       
   418     {
       
   419         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION), client);
       
   420         gc.fillPolygon(points);
       
   421     }
       
   422 
       
   423     void setClip(int x, int y, int w, int h, Graphics client)
       
   424     {
       
   425         validateAndApplySettings(COORDS_TRANSLATION, client);
       
   426         // check if given clip is already active in buffer
       
   427         if((bufferClip.x == x) && (bufferClip.y == y) &&
       
   428                 (bufferClip.width == w) && (bufferClip.height== h))
       
   429         {
       
   430             return;
       
   431         }
       
   432         // Images do not need special handling
       
   433         if(getHostType() == HOST_TYPE_IMAGE)
       
   434         {
       
   435             gc.setClip(x, y, w, h, false);
       
   436             return;
       
   437         }
       
   438 
       
   439         // translate clip to display coordinates and apply
       
   440         Rectangle rect = clipToWindowCoords(x, y, w, h);
       
   441         if(rect.isEmpty())
       
   442         {
       
   443             // check is buffer clip is already up to date
       
   444             if(bufferClip.isEmpty())
       
   445             {
       
   446                 return;
       
   447             }
       
   448             else
       
   449             {
       
   450                 // This is a special case, where the clip defines
       
   451                 // an area outside control bounds and due to that the clip
       
   452                 // is set to zero size, in order t prevent drawing on top of other controls.
       
   453                 // In all other cases the buffer clip is always set
       
   454                 // to the same values as the client, i.e. Graphics has.
       
   455                 // So by setting the bufferClip here to zero means that the clip
       
   456                 // in Graphics and the buffer are not in sync and not comparable,
       
   457                 // however they will be back in sync when client sets clip
       
   458                 // with an area partly or completely inside the host control.
       
   459                 bufferClip = rect;
       
   460             }
       
   461         }
       
   462         else
       
   463         {
       
   464             bufferClip.x = x;
       
   465             bufferClip.y = y;
       
   466             bufferClip.width = w;
       
   467             bufferClip.height = h;
       
   468         }
       
   469         gc.setClip(rect.x, rect.y, rect.width, rect.height, false);
       
   470     }
       
   471 
       
   472     void setGraphicsDefaults(Graphics client)
       
   473     {
       
   474     	validateAndApplySettings((FONT|COLOR|STROKESTYLE|COORDS_TRANSLATION|FORCE_SETTINGS), client);
       
   475     }
       
   476     
       
   477     void setColor(int r, int g, int b, Graphics client)
       
   478     {
       
   479         // check if given color is already active in buffer
       
   480         if(bufferColor == (Graphics.OPAQUE_ALPHA | (r << 16) | (g << 8) | b))
       
   481         {
       
   482             return;
       
   483         }
       
   484         gc.setForegroundColor(r, g, b);
       
   485         gc.setBackgroundColor(r, g, b);
       
   486 
       
   487         // Cache active color
       
   488         bufferColor = (Graphics.OPAQUE_ALPHA | (r << 16) | (g << 8) | b);
       
   489     }
       
   490 
       
   491     void setFont(int fontHandle, Graphics client)
       
   492     {
       
   493         // check if given font is already active in buffer
       
   494         if(bufferFontHandle == fontHandle)
       
   495         {
       
   496             return;
       
   497         }
       
   498         gc.setFont(fontHandle);
       
   499         // Cache active setting
       
   500         bufferFontHandle = fontHandle;
       
   501     }
       
   502 
       
   503     void setStrokeStyle(int cgfxStyle, int graphicsStyle, Graphics client)
       
   504     {
       
   505         if(bufferStrokeStyle == graphicsStyle)
       
   506         {
       
   507             return;
       
   508         }
       
   509         gc.setStrokeStyle(cgfxStyle);
       
   510         // Cache active setting
       
   511         bufferStrokeStyle = graphicsStyle;
       
   512     }
       
   513 
       
   514     void translate(int xDelta, int yDelta, Graphics client)
       
   515     {
       
   516         if((xDelta == 0) && (yDelta == 0))
       
   517         {
       
   518             return;
       
   519         }
       
   520         gc.translate(xDelta, yDelta);
       
   521         // Cache active settings
       
   522         bufferTranslateX += xDelta;
       
   523         bufferTranslateY += yDelta;
       
   524     }
       
   525 
       
   526     void drawLine(int xStart, int yStart, int xEnd, int yEnd, Graphics client)
       
   527     {
       
   528         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|STROKESTYLE), client);
       
   529         gc.drawLine(xStart, yStart, xEnd, yEnd);
       
   530     }
       
   531 
       
   532     void drawRect(int x, int y, int w, int h, Graphics client)
       
   533     {
       
   534         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|STROKESTYLE), client);
       
   535         gc.drawRect(x, y, w, h);
       
   536     }
       
   537 
       
   538     void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH, Graphics client)
       
   539     {
       
   540         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|STROKESTYLE), client);
       
   541         gc.drawRoundRect(x, y, w, h, arcW, arcH);
       
   542     }
       
   543 
       
   544     void drawArc(int x, int y, int w, int h, int startAngle, int arcAngle, Graphics client)
       
   545     {
       
   546         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|STROKESTYLE), client);
       
   547         gc.drawArc(x, y, w, h, startAngle, arcAngle);
       
   548     }
       
   549 
       
   550     void drawString(String string, int x, int y, Graphics client)
       
   551     {
       
   552         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|FONT), client);
       
   553         gc.drawString(string, x, y, true);
       
   554     }
       
   555 
       
   556     void drawImage(org.eclipse.swt.internal.qt.graphics.Image image, int x,int y, Graphics client)
       
   557     {
       
   558         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   559         gc.drawImage(image, x, y);
       
   560     }
       
   561 
       
   562     void drawImage(org.eclipse.swt.internal.qt.graphics.Image image, int xDst, int yDst,
       
   563                    int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc,
       
   564                    int transform, Graphics client)
       
   565     {
       
   566         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   567         gc.drawImage(image, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, transform);
       
   568     }
       
   569 
       
   570     void drawRGB(int[] rgb,
       
   571                  int offset,
       
   572                  int scanlength,
       
   573                  int x,
       
   574                  int y,
       
   575                  int w,
       
   576                  int h,
       
   577                  boolean alpha,
       
   578                  Graphics client)
       
   579     {
       
   580         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   581         gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha);
       
   582     }
       
   583 
       
   584     void drawRGB(int[] rgb,
       
   585                  int offset,
       
   586                  int scanlength,
       
   587                  int x,
       
   588                  int y,
       
   589                  int w,
       
   590                  int h,
       
   591                  boolean alpha,
       
   592                  int manipulation,
       
   593                  Graphics client)
       
   594     {
       
   595         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   596         gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha, manipulation);
       
   597     }
       
   598 
       
   599     void drawRGB(byte[] rgb,
       
   600                  byte[] transparencyMask,
       
   601                  int offset,
       
   602                  int scanlength,
       
   603                  int x,
       
   604                  int y,
       
   605                  int w,
       
   606                  int h,
       
   607                  int manipulation,
       
   608                  int format,
       
   609                  Graphics client)
       
   610     {
       
   611         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   612         gc.drawRGB(rgb, transparencyMask, offset, scanlength, x, y, w, h, manipulation, format);
       
   613     }
       
   614 
       
   615     void drawRGB(short[] rgb,
       
   616                  int offset,
       
   617                  int scanlength,
       
   618                  int x,
       
   619                  int y,
       
   620                  int w,
       
   621                  int h,
       
   622                  boolean alpha,
       
   623                  int manipulation,
       
   624                  int format,
       
   625                  Graphics client)
       
   626     {
       
   627         validateAndApplySettings((CLIP|COORDS_TRANSLATION), client);
       
   628         gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha, manipulation, format);
       
   629     }
       
   630 
       
   631     void drawPolygon(int[] points, Graphics client)
       
   632     {
       
   633         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION|STROKESTYLE), client);
       
   634         gc.drawPolygon(points);
       
   635     }
       
   636 
       
   637     void fillPolygon(int[] points, Graphics client)
       
   638     {
       
   639         validateAndApplySettings((COLOR|CLIP|COORDS_TRANSLATION), client);
       
   640         gc.fillPolygon(points);
       
   641     }
       
   642 
       
   643     void setARGBColor(int argb, Graphics client)
       
   644     {
       
   645         if(bufferColor == argb)
       
   646         {
       
   647             return;
       
   648         }
       
   649         gc.setBackgroundColor(argb, true);
       
   650         gc.setForegroundColor(argb, true);
       
   651         // Cache active color
       
   652         bufferColor = argb;
       
   653     }
       
   654 
       
   655     /**
       
   656      * Translates given rectangle to window coordinates.
       
   657      * Coordinate system translation does not affect on this method.
       
   658      *
       
   659      * @param x The x-coordinate of the rectangle
       
   660      * @param y The y-coordinate of the rectangle
       
   661      * @param w The width of the rectangle
       
   662      * @param h The height of the rectangle
       
   663      * @return
       
   664      */
       
   665     Rectangle toWindowCoordinates(int x, int y, int w, int h)
       
   666     {
       
   667         final int xInDpy = hostBounds.x + x;
       
   668         final int yInDpy = hostBounds.y + y;
       
   669         return new Rectangle(xInDpy, yInDpy, xInDpy + w, yInDpy + h);
       
   670     }
       
   671 
       
   672 
       
   673     /**
       
   674      * Returns the WindowSurface that relates to this Buffer
       
   675      *
       
   676      * @return WindowSurface owned by this Buffer
       
   677      */
       
   678     WindowSurface getWindowSurface()
       
   679     {
       
   680         return null;
       
   681     }
       
   682     
       
   683     boolean containsDrawnPrimitives() {
       
   684         boolean result = false;
       
   685         if(commandBuffer != null) {
       
   686             result = commandBuffer.containsDrawnPrimitives();
       
   687         }
       
   688         return result;
       
   689     }
       
   690     
       
   691     /**
       
   692      * Translates given rectangle to window surface coordinates
       
   693      * and outlines the clip inside the control bounds.
       
   694      *
       
   695      * @param x The x-coordinate of the rectangle
       
   696      * @param y The y-coordinate of the rectangle
       
   697      * @param w The width of the rectangle
       
   698      * @param h The height of the rectangle
       
   699      *
       
   700      */
       
   701     private Rectangle clipToWindowCoords(int x, int y, int w, int h)
       
   702     {
       
   703         // Bottom-right corner of control bounds in window coordinates
       
   704         final int hostX2 = hostBounds.x + hostBounds.width;
       
   705         final int hostY2 = hostBounds.y + hostBounds.height;
       
   706         // clip in window coordinates
       
   707         final int clipX1Dpy = hostBounds.x + bufferTranslateX + x;
       
   708         final int clipY1Dpy = hostBounds.y + bufferTranslateY + y;
       
   709         final int clipX2Dpy = hostBounds.x + bufferTranslateX + x + w;
       
   710         final int clipY2Dpy = hostBounds.y + bufferTranslateY + y + h;
       
   711         int clipX1 = x;
       
   712         int clipY1 = y;
       
   713         int clipX2 = x + w;
       
   714         int clipY2 = y + h;
       
   715 
       
   716         // check if the clip is completely outside of control bounds
       
   717         if(!hostBounds.contains(clipX1Dpy, clipY1Dpy) && !hostBounds.contains(clipX2Dpy, clipY2Dpy))
       
   718         {
       
   719             return new Rectangle(0,0,0,0);
       
   720         }
       
   721 
       
   722         // At least one corner is inside control bounds so
       
   723         // adjust clip coordinates so that they lie within control bounds
       
   724         clipX1 = clipX1Dpy < hostBounds.x ? (x + (hostBounds.x - clipX1Dpy)) : x;
       
   725         clipX1 = clipX1Dpy > hostX2 ? (x - (clipX1Dpy - hostX2)) : x;
       
   726         clipY1 = clipY1Dpy < hostBounds.y ? (y + (hostBounds.y - clipY1Dpy)) : y;
       
   727         clipY1 = clipY1Dpy > hostY2 ? (y - (clipY1Dpy - hostY2)) : y;
       
   728 
       
   729         clipX2 = clipX2Dpy < hostBounds.x ? (clipX2 + (hostBounds.x - clipX1Dpy)) : clipX2;
       
   730         clipX2 = clipX2Dpy > hostX2 ? (clipX2 - (clipX1Dpy - hostX2)) : clipX2;
       
   731         clipY2 = clipY2Dpy < hostBounds.y ? (clipY2 + (hostBounds.y - clipY1Dpy)) : clipY2;
       
   732         clipY2 = clipY2Dpy > hostY2 ? (clipY2 - (clipY1Dpy - hostY2)) : clipY2;
       
   733 
       
   734         return new Rectangle(clipX1, clipY1, (clipX2 - clipX1) , (clipY2 - clipY1));
       
   735     }
       
   736 
       
   737     /**
       
   738      * Validates the current settings active in buffer against
       
   739      * caller settings and updated needed settings in buffer when
       
   740      * that is required. This method does not update anything if
       
   741      * there is only one (reference_count == 1)Graphics instance using this buffer.
       
   742      *
       
   743      * @param flags The settings that need to be checked
       
   744      * @param client The Graphics instance that made the call
       
   745      */
       
   746     private void validateAndApplySettings(int flags, Graphics client)
       
   747     {
       
   748         if(!clientChanged(client) && (FORCE_SETTINGS & flags) == 0)
       
   749         {
       
   750             return;
       
   751         }
       
   752         if((COLOR & flags) != 0)
       
   753         {
       
   754             if(bufferColor != client.currentColor)
       
   755             {
       
   756                 gc.setBackgroundColor(client.currentColor, true);
       
   757                 gc.setForegroundColor(client.currentColor, true);
       
   758                 bufferColor = client.currentColor;
       
   759             }
       
   760         }
       
   761         if((CLIP & flags) != 0)
       
   762         {
       
   763             if(client.currentClip[0] != bufferClip.x &&
       
   764                     client.currentClip[1] != bufferClip.y &&
       
   765                     client.currentClip[2] != bufferClip.width &&
       
   766                     client.currentClip[3] != bufferClip.height)
       
   767             {
       
   768 
       
   769                 Rectangle rect = clipToWindowCoords(client.currentClip[0], client.currentClip[1],
       
   770                                                      client.currentClip[2], client.currentClip[3]);
       
   771                 gc.setClip(rect.x, rect.y, rect.width, rect.height, false);
       
   772                 bufferClip.x = client.currentClip[0];
       
   773                 bufferClip.y = client.currentClip[1];
       
   774                 bufferClip.width = client.currentClip[2];
       
   775                 bufferClip.height = client.currentClip[3];
       
   776             }
       
   777         }
       
   778         if((COORDS_TRANSLATION & flags) != 0)
       
   779         {
       
   780             if((bufferTranslateX != client.translateX) && (bufferTranslateY != client.translateY))
       
   781             {
       
   782                 gc.translate((client.translateX - bufferTranslateX), (client.translateY - bufferTranslateY));
       
   783                 bufferTranslateX = client.translateX;
       
   784                 bufferTranslateY = client.translateY;
       
   785             }
       
   786         }
       
   787         if((FONT & flags) != 0)
       
   788         {
       
   789             int fontHandle = Font.getESWTFont(client.currentFont).handle;
       
   790             if(bufferFontHandle != fontHandle)
       
   791             {
       
   792                 gc.setFont(fontHandle);
       
   793                 bufferFontHandle = fontHandle;
       
   794             }
       
   795         }
       
   796         if((STROKESTYLE & flags) != 0)
       
   797         {
       
   798             if(bufferStrokeStyle != client.currentStrokeStyle)
       
   799             {
       
   800                 gc.setStrokeStyle(Graphics.mapStrokeStyle(client.currentStrokeStyle));
       
   801                 bufferStrokeStyle = client.currentStrokeStyle;
       
   802             }
       
   803         }
       
   804     }
       
   805 
       
   806     private boolean clientChanged(Graphics client)
       
   807     {
       
   808         if(clientCount == 1)
       
   809         {
       
   810             return false;
       
   811         }
       
   812         if(currentClient != client)
       
   813         {
       
   814             currentClient = client;
       
   815             return true;
       
   816         }
       
   817         return false;
       
   818     }
       
   819 
       
   820     /**
       
   821      * Writes control bounds to buffer, including translation and clip
       
   822      * @param writeClientTranslation If true write also client translation to buffer, otherwise not
       
   823      */
       
   824     private void writeControlBoundsToBuffer(boolean writeClientTranslation)
       
   825     {
       
   826         if((hostBounds.x != 0) || (hostBounds.y != 0))
       
   827         {
       
   828             gc.translate(hostBounds.x, hostBounds.y);
       
   829         }
       
   830         gc.setClip(0, 0, hostBounds.width, hostBounds.height, false);
       
   831         // Cache buffer settings
       
   832         bufferClip.x = 0;
       
   833         bufferClip.y = 0;
       
   834         bufferClip.width = hostBounds.width;
       
   835         bufferClip.height = hostBounds.height;
       
   836         // write client translation if requested
       
   837         if(writeClientTranslation)
       
   838         {
       
   839             if((bufferTranslateX != 0) || (bufferTranslateY != 0))
       
   840             {
       
   841                 gc.translate(bufferTranslateX, bufferTranslateY);
       
   842             }
       
   843         }
       
   844     }
       
   845 
       
   846    /**
       
   847     * Writes Graphics default values to buffer
       
   848     * @param force If true defaults are written unconditionally to buffer, 
       
   849     *              otherwise only values that different than the ones in buffer
       
   850     *              are written
       
   851     */
       
   852     private void writeDefaultValuesToBuffer()
       
   853     {
       
   854         int handle = Font.getESWTFont(defaultFont).handle;
       
   855         gc.setFont(handle);
       
   856         bufferFontHandle = handle;
       
   857         gc.setBackgroundColor(defaultColor, true);
       
   858         gc.setForegroundColor(defaultColor, true);
       
   859         bufferColor = defaultColor;
       
   860         gc.setStrokeStyle(Graphics.mapStrokeStyle(defaultStrokeStyle));
       
   861         bufferStrokeStyle = defaultStrokeStyle;
       
   862         gc.resetTransform();
       
   863         bufferTranslateX = defaultTranslateX;
       
   864         bufferTranslateY = defaultTranslateY;
       
   865     }
       
   866     
       
   867     private void doRelease()
       
   868     {
       
   869         gc.releaseTarget();
       
   870     }
       
   871 }