Source for gnu.java.awt.peer.gtk.ComponentGraphics

   1: /* ComponentGraphics.java --
   2:    Copyright (C) 2006  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.awt.peer.gtk;
  40: 
  41: import gnu.classpath.Pointer;
  42: 
  43: import java.awt.AlphaComposite;
  44: import java.awt.Color;
  45: import java.awt.Graphics;
  46: import java.awt.Graphics2D;
  47: import java.awt.GraphicsConfiguration;
  48: import java.awt.Image;
  49: import java.awt.Point;
  50: import java.awt.Rectangle;
  51: import java.awt.Shape;
  52: import java.awt.Toolkit;
  53: import java.awt.font.GlyphVector;
  54: import java.awt.geom.AffineTransform;
  55: import java.awt.geom.Point2D;
  56: import java.awt.geom.Rectangle2D;
  57: import java.awt.image.BufferedImage;
  58: import java.awt.image.ColorModel;
  59: import java.awt.image.ImageObserver;
  60: import java.awt.image.ImageProducer;
  61: import java.awt.image.Raster;
  62: import java.awt.image.RenderedImage;
  63: import java.awt.image.WritableRaster;
  64: import java.util.Hashtable;
  65: 
  66: /**
  67:  * ComponentGraphics - context for drawing directly to a component,
  68:  * as this is an X drawable, it requires that we use GTK locks.
  69:  *
  70:  * This context draws directly to the drawable and requires xrender.
  71:  */
  72: public class ComponentGraphics extends CairoGraphics2D
  73: {
  74:   private static final boolean hasXRenderExtension = hasXRender();
  75: 
  76:   private GtkComponentPeer component;
  77:   protected long cairo_t;
  78:   private BufferedImage buffer, componentBuffer;
  79: 
  80:   private static ThreadLocal<Integer> hasLock = new ThreadLocal<Integer>();
  81:   private static Integer ONE = Integer.valueOf(1);
  82: 
  83:   ComponentGraphics()
  84:   {
  85:   }
  86: 
  87:   private ComponentGraphics(GtkComponentPeer component)
  88:   {
  89:     this.component = component;
  90:     cairo_t = initState(component);
  91:     setup( cairo_t );
  92:     Rectangle bounds = component.awtComponent.getBounds();
  93:     setClip( new Rectangle( 0, 0, bounds.width, bounds.height) );
  94:     setBackground(component.awtComponent.getBackground());
  95:     setColor(component.awtComponent.getForeground());
  96:   }
  97: 
  98:   private ComponentGraphics(ComponentGraphics cg)
  99:   {
 100:     component = cg.component;
 101:     cairo_t = initState(component);
 102:     copy( cg, cairo_t );
 103:     Rectangle bounds = component.awtComponent.getBounds();
 104:     setClip( new Rectangle( 0, 0, bounds.width, bounds.height) );
 105:     setBackground(component.awtComponent.getBackground());
 106:     setColor(component.awtComponent.getForeground());
 107:   }
 108: 
 109:   /**
 110:    * Creates a cairo_t for the component surface and return it.
 111:    */
 112:   private native long initState(GtkComponentPeer component);
 113: 
 114:   /**
 115:    * Obtain and hold a GDK lock, which is required for all drawing operations
 116:    * in this graphics context (since it is backed by an X surface).
 117:    *
 118:    * This method causes the GDK locking behaviour to be re-entrant.  No race
 119:    * conditions are caused since a ThreadLocal is used and each thread has its
 120:    * own lock counter.
 121:    */
 122:   private void lock()
 123:   {
 124:     Integer i = hasLock.get();
 125:     if (i == null)
 126:       {
 127:         start_gdk_drawing();
 128:         hasLock.set(ONE);
 129:       }
 130:     else
 131:       hasLock.set(Integer.valueOf(i.intValue() + 1));
 132:   }
 133: 
 134:   /**
 135:    * Release the re-entrant GDK lock.
 136:    */
 137:   private void unlock()
 138:   {
 139:     Integer i = hasLock.get();
 140:     if (i == null)
 141:       throw new IllegalStateException();
 142:     if (i == ONE)
 143:       {
 144:         hasLock.set(null);
 145:         end_gdk_drawing();
 146:       }
 147:     else if (i.intValue() == 2)
 148:       hasLock.set(ONE);
 149:     else
 150:       hasLock.set(Integer.valueOf(i.intValue() - 1));
 151:   }
 152: 
 153:   /**
 154:    * Creates a cairo_t for a volatile image
 155:    */
 156:   protected native long initFromVolatile( long pixmapPtr);
 157: 
 158:   /**
 159:    * Grab lock
 160:    */
 161:   private native void start_gdk_drawing();
 162: 
 163:   /**
 164:    * Release lock
 165:    */
 166:   private native void end_gdk_drawing();
 167: 
 168:   /**
 169:    * Query if the system has the XRender extension.
 170:    */
 171:   public static native boolean hasXRender();
 172: 
 173:   /**
 174:    * This is a utility method (used by GtkComponentPeer) for grabbing the
 175:    * image of a component.
 176:    */
 177:   private static native Pointer nativeGrab(GtkComponentPeer component);
 178: 
 179:   private native void copyAreaNative(GtkComponentPeer component, int x, int y,
 180:                                      int width, int height, int dx, int dy);
 181: 
 182:   private native void drawVolatile(GtkComponentPeer component,
 183:                                    long vimg, int x, int y,
 184:                                    int width, int height, int cx, int cy,
 185:                                    int cw, int ch);
 186: 
 187:   /**
 188:    * Not really related (moveme?). Utility method used by GtkComponent.
 189:    */
 190:   public static GtkImage grab( GtkComponentPeer component )
 191:   {
 192:     return new GtkImage( nativeGrab( component ) );
 193:   }
 194: 
 195:   /**
 196:    * Returns a Graphics2D object for a component, either an instance of this
 197:    * class (if xrender is supported), or a context which copies.
 198:    */
 199:   public static Graphics2D getComponentGraphics(GtkComponentPeer component)
 200:   {
 201:     if( hasXRenderExtension )
 202:       return new ComponentGraphics(component);
 203: 
 204:     Rectangle r = component.awtComponent.getBounds();
 205:     return new ComponentGraphicsCopy(r.width, r.height, component);
 206:   }
 207: 
 208:   public GraphicsConfiguration getDeviceConfiguration()
 209:   {
 210:     return component.getGraphicsConfiguration();
 211:   }
 212: 
 213:   public Graphics create()
 214:   {
 215:     return new ComponentGraphics(this);
 216:   }
 217: 
 218:   protected Rectangle2D getRealBounds()
 219:   {
 220:     return component.awtComponent.getBounds();
 221:   }
 222: 
 223:   public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
 224:   {
 225:     copyAreaNative(component, x, y, width, height, dx, dy);
 226:   }
 227: 
 228:   /**
 229:    * Overloaded methods that do actual drawing need to enter the gdk threads
 230:    * and also do certain things before and after.
 231:    */
 232:   public void draw(Shape s)
 233:   {
 234:     if (comp == null || comp instanceof AlphaComposite)
 235:       super.draw(s);
 236: 
 237:     else
 238:       {
 239:         createBuffer();
 240: 
 241:         Graphics2D g2d = (Graphics2D)buffer.getGraphics();
 242:         g2d.setStroke(this.getStroke());
 243:         g2d.setColor(this.getColor());
 244:         g2d.draw(s);
 245: 
 246:         drawComposite(s.getBounds2D(), null);
 247:       }
 248:   }
 249: 
 250:   public void fill(Shape s)
 251:   {
 252:     if (comp == null || comp instanceof AlphaComposite)
 253:       super.fill(s);
 254: 
 255:     else
 256:       {
 257:         createBuffer();
 258: 
 259:         Graphics2D g2d = (Graphics2D)buffer.getGraphics();
 260:         g2d.setPaint(this.getPaint());
 261:         g2d.setColor(this.getColor());
 262:         g2d.fill(s);
 263: 
 264:         drawComposite(s.getBounds2D(), null);
 265:       }
 266:   }
 267: 
 268:   public void drawRenderedImage(RenderedImage image, AffineTransform xform)
 269:   {
 270:     if (comp == null || comp instanceof AlphaComposite)
 271:       super.drawRenderedImage(image, xform);
 272: 
 273:     else
 274:       {
 275:         createBuffer();
 276: 
 277:         Graphics2D g2d = (Graphics2D)buffer.getGraphics();
 278:         g2d.setRenderingHints(this.getRenderingHints());
 279:         g2d.drawRenderedImage(image, xform);
 280: 
 281:         drawComposite(buffer.getRaster().getBounds(), null);
 282:       }
 283:   }
 284: 
 285:   protected boolean drawImage(Image img, AffineTransform xform,
 286:                               Color bgcolor, ImageObserver obs)
 287:   {
 288:     boolean rv;
 289:     if (comp == null || comp instanceof AlphaComposite)
 290:       rv = super.drawImage(img, xform, bgcolor, obs);
 291: 
 292:     else
 293:       {
 294:         // Get buffered image of source
 295:         if( !(img instanceof BufferedImage) )
 296:           {
 297:             ImageProducer source = img.getSource();
 298:             if (source == null)
 299:               return false;
 300:             img = Toolkit.getDefaultToolkit().createImage(source);
 301:           }
 302:         BufferedImage bImg = (BufferedImage) img;
 303: 
 304:         // Find translated bounds
 305:         Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
 306:         Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
 307:                                         bImg.getHeight() + bImg.getMinY());
 308:         if (xform != null)
 309:           {
 310:             origin = xform.transform(origin, origin);
 311:             pt = xform.transform(pt, pt);
 312:           }
 313: 
 314:         // Create buffer and draw image
 315:         createBuffer();
 316: 
 317:         Graphics2D g2d = (Graphics2D)buffer.getGraphics();
 318:         g2d.setRenderingHints(this.getRenderingHints());
 319:         g2d.drawImage(img, xform, obs);
 320: 
 321:         // Perform compositing
 322:         rv = drawComposite(new Rectangle2D.Double(origin.getX(),
 323:                                                     origin.getY(),
 324:                                                     pt.getX(), pt.getY()),
 325:                            obs);
 326:       }
 327:     return rv;
 328:   }
 329: 
 330:   public void drawGlyphVector(GlyphVector gv, float x, float y)
 331:   {
 332:     if (comp == null || comp instanceof AlphaComposite)
 333:       super.drawGlyphVector(gv, x, y);
 334: 
 335:     else
 336:       {
 337:         createBuffer();
 338: 
 339:         Graphics2D g2d = (Graphics2D)buffer.getGraphics();
 340:         g2d.setPaint(this.getPaint());
 341:         g2d.setStroke(this.getStroke());
 342:         g2d.drawGlyphVector(gv, x, y);
 343: 
 344:         Rectangle2D bounds = gv.getLogicalBounds();
 345:         bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
 346:                                         bounds.getWidth(), bounds.getHeight());
 347:         drawComposite(bounds, null);
 348:       }
 349:   }
 350: 
 351:   public boolean drawImage(Image img, int x, int y, ImageObserver observer)
 352:   {
 353:     // If it is a GtkVolatileImage with an "easy" transform then
 354:     // draw directly. Always pass a BufferedImage to super to avoid
 355:     // deadlock (see Note in CairoGraphics.drawImage()).
 356:     if (img instanceof GtkVolatileImage)
 357:       {
 358:         GtkVolatileImage vimg = (GtkVolatileImage) img;
 359:         int type = transform.getType();
 360:         if ((type == AffineTransform.TYPE_IDENTITY
 361:              || type == AffineTransform.TYPE_TRANSLATION)
 362:              && (clip == null || clip instanceof Rectangle2D))
 363:           {
 364:             Rectangle2D r = (Rectangle2D) clip;
 365:             if (r == null)
 366:               r = getRealBounds();
 367:             x += transform.getTranslateX();
 368:             y += transform.getTranslateY();
 369:             drawVolatile(component, vimg.nativePointer,
 370:                          x, y, vimg.width, vimg.height,
 371:                          (int) (r.getX() + transform.getTranslateX()),
 372:                          (int) (r.getY() + transform.getTranslateY()),
 373:                          (int) r.getWidth(),
 374:                          (int) r.getHeight());
 375:             return true;
 376:           }
 377:         else
 378:           return super.drawImage(vimg.getSnapshot(), x, y, observer);
 379:       }
 380: 
 381:     BufferedImage bimg;
 382:     if (img instanceof BufferedImage)
 383:       bimg = (BufferedImage) img;
 384:     else
 385:       {
 386:         ImageProducer source = img.getSource();
 387:         if (source == null)
 388:           return false;
 389:         bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
 390:       }
 391:     return super.drawImage(bimg, x, y, observer);
 392:   }
 393: 
 394:   public boolean drawImage(Image img, int x, int y, int width, int height,
 395:                            ImageObserver observer)
 396:   {
 397:     // If it is a GtkVolatileImage with an "easy" transform then
 398:     // draw directly. Always pass a BufferedImage to super to avoid
 399:     // deadlock (see Note in CairoGraphics.drawImage()).
 400:     if (img instanceof GtkVolatileImage
 401:         && (clip == null || clip instanceof Rectangle2D))
 402:       {
 403:         GtkVolatileImage vimg = (GtkVolatileImage) img;
 404:         int type = transform.getType();
 405:         if ((type == AffineTransform.TYPE_IDENTITY
 406:              || type == AffineTransform.TYPE_TRANSLATION)
 407:              && (clip == null || clip instanceof Rectangle2D))
 408:           {
 409:             Rectangle2D r = (Rectangle2D) clip;
 410:             if (r == null)
 411:               r = getRealBounds();
 412:             x += transform.getTranslateX();
 413:             y += transform.getTranslateY();
 414:             drawVolatile(component, vimg.nativePointer,
 415:                          x, y, width, height,
 416:                          (int) (r.getX() + transform.getTranslateX()),
 417:                          (int) (r.getY() + transform.getTranslateY()),
 418:                          (int) r.getWidth(),
 419:                          (int) r.getHeight());
 420:             return true;
 421:           }
 422:         else
 423:           return super.drawImage(vimg.getSnapshot(), x, y,
 424:                                  width, height, observer);
 425:       }
 426: 
 427:     BufferedImage bimg;
 428:     img = AsyncImage.realImage(img, observer);
 429:     if (img instanceof BufferedImage)
 430:       bimg = (BufferedImage) img;
 431:     else
 432:       {
 433:         ImageProducer source = img.getSource();
 434:         if (source == null)
 435:           return false;
 436:         bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
 437:       }
 438:     return super.drawImage(bimg, x, y, width, height, observer);
 439:   }
 440: 
 441:   private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
 442:   {
 443:     // Clip source to visible areas that need updating
 444:     Rectangle2D clip = this.getClipBounds();
 445:     Rectangle2D.intersect(bounds, clip, bounds);
 446:     clip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
 447:                          buffer.getWidth(), buffer.getHeight());
 448:     Rectangle2D.intersect(bounds, clip, bounds);
 449: 
 450:     BufferedImage buffer2 = buffer;
 451:     if (!bounds.equals(buffer2.getRaster().getBounds()))
 452:       buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
 453:                                     (int)bounds.getWidth(),
 454:                                     (int)bounds.getHeight());
 455: 
 456:     // Get destination clip to bounds
 457:     double[] points = new double[] {bounds.getX(), bounds.getY(),
 458:                                     bounds.getMaxX(), bounds.getMaxY()};
 459:     transform.transform(points, 0, points, 0, 2);
 460: 
 461:     Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
 462:                                                       points[2] - points[0],
 463:                                                       points[3] - points[1]);
 464: 
 465:     Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
 466: 
 467:     // Get current image on the component
 468:     GtkImage img = grab(component);
 469:     Graphics gr = componentBuffer.createGraphics();
 470:     gr.drawImage(img, 0, 0, null);
 471:     gr.dispose();
 472: 
 473:     BufferedImage cBuffer = componentBuffer;
 474:     if (!deviceBounds.equals(cBuffer.getRaster().getBounds()))
 475:       cBuffer = cBuffer.getSubimage((int)deviceBounds.getX(),
 476:                                     (int)deviceBounds.getY(),
 477:                                     (int)deviceBounds.getWidth(),
 478:                                     (int)deviceBounds.getHeight());
 479: 
 480:     // Perform actual composite operation
 481:     compCtx.compose(buffer2.getRaster(), cBuffer.getRaster(),
 482:                     cBuffer.getRaster());
 483: 
 484:     // This MUST call directly into the "action" method in CairoGraphics2D,
 485:     // not one of the wrappers, to ensure that the composite isn't processed
 486:     // more than once!
 487:     boolean rv = super.drawImage(cBuffer,
 488:                                  AffineTransform.getTranslateInstance(bounds.getX(),
 489:                                                                       bounds.getY()),
 490:                                  null, null);
 491:     return rv;
 492:   }
 493: 
 494:   private void createBuffer()
 495:   {
 496:     if (buffer == null)
 497:       {
 498:         WritableRaster rst;
 499:         rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
 500:                                                                                 component.awtComponent.getHeight()),
 501:                                           new Point(0,0));
 502: 
 503:         buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
 504:                                    GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
 505:                                    new Hashtable());
 506:       }
 507:     else
 508:       {
 509:         Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
 510: 
 511:         g2d.setBackground(new Color(0,0,0,0));
 512:         g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
 513:       }
 514: 
 515:     if (componentBuffer == null)
 516:       {
 517:         WritableRaster rst;
 518:         rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
 519:                                                                                 component.awtComponent.getHeight()),
 520:                                           new Point(0,0));
 521: 
 522:         componentBuffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
 523:                                             GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
 524:                                             new Hashtable());
 525:       }
 526:   }
 527: 
 528:   protected ColorModel getNativeCM()
 529:   {
 530:     return GtkVolatileImage.gdkColorModel;
 531:   }
 532: 
 533:   /* --- START OVERRIDDEN NATIVE METHODS ----
 534:    * All native methods in CairoGraphics2D should be overridden here and
 535:    * enclosed in locks, since the cairo surface is backed by an X surface
 536:    * in this graphics context and the X surface requires external locking.
 537:    *
 538:    * We lock everything "just in case", since it's difficult to know which
 539:    * calls are and aren't thread-safe.  Overriding and locking the native
 540:    * methods allows superclass code in CairoGraphics2D to execute properly,
 541:    * without the need to override every single method.
 542:    *
 543:    * CAVEAT: if native code obtains a lock (using gdk_threads_enter(), not the
 544:    * lock() method provided here) and then calls back into Java and one of these
 545:    * methods ends up being called, we will deadlock.  The lock is only reentrant
 546:    * when called via our lock() method.
 547:    */
 548: 
 549:   /* These methods are already locked in the superclass CairoGraphics2D
 550:    * so they do not need to be overridden:
 551:    *
 552:    * public void disposeNative
 553:    *
 554:    * protected void cairoDrawGlyphVector
 555:    *
 556:    * protected void cairoSetFont
 557:    */
 558: 
 559:   @Override
 560:   protected long init(long pointer)
 561:   {
 562:     long ret;
 563: 
 564:     try
 565:     {
 566:       lock();
 567:       ret = super.init(pointer);
 568:     }
 569:     finally
 570:     {
 571:       unlock();
 572:     }
 573: 
 574:     return ret;
 575:   }
 576: 
 577:   @Override
 578:   protected void drawPixels(long pointer, int[] pixels, int w, int h,
 579:                             int stride, double[] i2u, double alpha,
 580:                             int interpolation)
 581:   {
 582:     try
 583:     {
 584:       lock();
 585:       super.drawPixels(pointer, pixels, w, h, stride, i2u, alpha,
 586:                        interpolation);
 587:     }
 588:     finally
 589:     {
 590:       unlock();
 591:     }
 592:   }
 593: 
 594:   @Override
 595:   protected void setGradient(long pointer, double x1, double y1,
 596:                              double x2, double y2,
 597:                              int r1, int g1, int b1, int a1,
 598:                              int r2, int g2, int b2, int a2, boolean cyclic)
 599:   {
 600:     try
 601:     {
 602:       lock();
 603:       super.setGradient(pointer, x1, y1, x2, y2, r1, g1, b1, a1, r2, g2, b2, a2,
 604:                         cyclic);
 605:     }
 606:     finally
 607:     {
 608:       unlock();
 609:     }
 610:   }
 611: 
 612:   @Override
 613:   protected void setPaintPixels(long pointer, int[] pixels, int w, int h,
 614:                                 int stride, boolean repeat, int x, int y)
 615:   {
 616:     try
 617:     {
 618:       lock();
 619:       super.setPaintPixels(pointer, pixels, w, h, stride, repeat, x, y);
 620:     }
 621:     finally
 622:     {
 623:       unlock();
 624:     }
 625:   }
 626: 
 627:   @Override
 628:   protected void cairoSetMatrix(long pointer, double[] m)
 629:   {
 630:     try
 631:     {
 632:       lock();
 633:       super.cairoSetMatrix(pointer, m);
 634:     }
 635:     finally
 636:     {
 637:       unlock();
 638:     }
 639:   }
 640: 
 641:   @Override
 642:   protected void cairoScale(long pointer, double x, double y)
 643:   {
 644:     try
 645:     {
 646:       lock();
 647:       super.cairoScale(pointer, x, y);
 648:     }
 649:     finally
 650:     {
 651:       unlock();
 652:     }
 653:   }
 654: 
 655:   @Override
 656:   protected void cairoSetOperator(long pointer, int cairoOperator)
 657:   {
 658:     try
 659:     {
 660:       lock();
 661:       super.cairoSetOperator(pointer, cairoOperator);
 662:     }
 663:     finally
 664:     {
 665:       unlock();
 666:     }
 667:   }
 668: 
 669:   @Override
 670:   protected void cairoSetRGBAColor(long pointer, double red, double green,
 671:                                    double blue, double alpha)
 672:   {
 673:     try
 674:     {
 675:       lock();
 676:       super.cairoSetRGBAColor(pointer, red, green, blue, alpha);
 677:     }
 678:     finally
 679:     {
 680:       unlock();
 681:     }
 682:   }
 683: 
 684:   @Override
 685:   protected void cairoSetFillRule(long pointer, int cairoFillRule)
 686:   {
 687:     try
 688:     {
 689:       lock();
 690:       super.cairoSetFillRule(pointer, cairoFillRule);
 691:     }
 692:     finally
 693:     {
 694:       unlock();
 695:     }
 696:   }
 697: 
 698:   @Override
 699:   protected void cairoSetLine(long pointer, double width, int cap, int join,
 700:                               double miterLimit)
 701:   {
 702:     try
 703:     {
 704:       lock();
 705:       super.cairoSetLine(pointer, width, cap, join, miterLimit);
 706:     }
 707:     finally
 708:     {
 709:       unlock();
 710:     }
 711:   }
 712: 
 713:   @Override
 714:   protected void cairoSetDash(long pointer, double[] dashes, int ndash,
 715:                               double offset)
 716:   {
 717:     try
 718:     {
 719:       lock();
 720:       super.cairoSetDash(pointer, dashes, ndash, offset);
 721:     }
 722:     finally
 723:     {
 724:       unlock();
 725:     }
 726:   }
 727: 
 728:   @Override
 729:   protected void cairoRectangle(long pointer, double x, double y,
 730:                                 double width, double height)
 731:   {
 732:     try
 733:     {
 734:       lock();
 735:       super.cairoRectangle(pointer, x, y, width, height);
 736:     }
 737:     finally
 738:     {
 739:       unlock();
 740:     }
 741:   }
 742: 
 743:   @Override
 744:   protected void cairoArc(long pointer, double x, double y,
 745:                           double radius, double angle1, double angle2)
 746:   {
 747:     try
 748:     {
 749:       lock();
 750:       super.cairoArc(pointer, x, y, radius, angle1, angle2);
 751:     }
 752:     finally
 753:     {
 754:       unlock();
 755:     }
 756:   }
 757: 
 758:   @Override
 759:   protected void cairoSave(long pointer)
 760:   {
 761:     try
 762:     {
 763:       lock();
 764:       super.cairoSave(pointer);
 765:     }
 766:     finally
 767:     {
 768:       unlock();
 769:     }
 770:   }
 771: 
 772:   @Override
 773:   protected void cairoRestore(long pointer)
 774:   {
 775:     try
 776:     {
 777:       lock();
 778:       super.cairoRestore(pointer);
 779:     }
 780:     finally
 781:     {
 782:       unlock();
 783:     }
 784:   }
 785: 
 786:   @Override
 787:   protected void cairoNewPath(long pointer)
 788:   {
 789:     try
 790:     {
 791:       lock();
 792:       super.cairoNewPath(pointer);
 793:     }
 794:     finally
 795:     {
 796:       unlock();
 797:     }
 798:   }
 799: 
 800:   @Override
 801:   protected void cairoClosePath(long pointer)
 802:   {
 803:     try
 804:     {
 805:       lock();
 806:       super.cairoClosePath(pointer);
 807:     }
 808:     finally
 809:     {
 810:       unlock();
 811:     }
 812:   }
 813: 
 814:   @Override
 815:   protected void cairoMoveTo(long pointer, double x, double y)
 816:   {
 817:     try
 818:     {
 819:       lock();
 820:       super.cairoMoveTo(pointer, x, y);
 821:     }
 822:     finally
 823:     {
 824:       unlock();
 825:     }
 826:   }
 827: 
 828:   @Override
 829:   protected void cairoLineTo(long pointer, double x, double y)
 830:   {
 831:     try
 832:     {
 833:       lock();
 834:       super.cairoLineTo(pointer, x, y);
 835:     }
 836:     finally
 837:     {
 838:       unlock();
 839:     }
 840:   }
 841: 
 842:   @Override
 843:   protected void cairoCurveTo(long pointer, double x1, double y1, double x2,
 844:                               double y2, double x3, double y3)
 845:   {
 846:     try
 847:     {
 848:       lock();
 849:       super.cairoCurveTo(pointer, x1, y1, x2, y2, x3, y3);
 850:     }
 851:     finally
 852:     {
 853:       unlock();
 854:     }
 855:   }
 856: 
 857:   @Override
 858:   protected void cairoStroke(long pointer)
 859:   {
 860:     try
 861:     {
 862:       lock();
 863:       super.cairoStroke(pointer);
 864:     }
 865:     finally
 866:     {
 867:       unlock();
 868:     }
 869:   }
 870: 
 871:   @Override
 872:   protected void cairoFill(long pointer, double alpha)
 873:   {
 874:     try
 875:     {
 876:       lock();
 877:       super.cairoFill(pointer, alpha);
 878:     }
 879:     finally
 880:     {
 881:       unlock();
 882:     }
 883:   }
 884: 
 885:   @Override
 886:   protected void cairoClip(long pointer)
 887:   {
 888:     try
 889:     {
 890:       lock();
 891:       super.cairoClip(pointer);
 892:     }
 893:     finally
 894:     {
 895:       unlock();
 896:     }
 897:   }
 898: 
 899:   @Override
 900:   protected void cairoResetClip(long pointer)
 901:   {
 902:     try
 903:     {
 904:       lock();
 905:       super.cairoResetClip(pointer);
 906:     }
 907:     finally
 908:     {
 909:       unlock();
 910:     }
 911:   }
 912: 
 913:   @Override
 914:   protected void cairoSetAntialias(long pointer, boolean aa)
 915:   {
 916:     try
 917:     {
 918:       lock();
 919:       super.cairoSetAntialias(pointer, aa);
 920:     }
 921:     finally
 922:     {
 923:       unlock();
 924:     }
 925:   }
 926: 
 927:   @Override
 928:   protected void drawCairoSurface(CairoSurface surface, AffineTransform tx,
 929:                                   double alpha, int interpolation)
 930:   {
 931:     try
 932:     {
 933:       lock();
 934:       super.drawCairoSurface(surface, tx, alpha, interpolation);
 935:     }
 936:     finally
 937:     {
 938:       unlock();
 939:     }
 940:   }
 941: }