| /* ComponentGraphics.java -- |
| Copyright (C) 2006 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package gnu.java.awt.peer.gtk; |
| |
| import gnu.classpath.Pointer; |
| |
| import java.awt.AlphaComposite; |
| import java.awt.Color; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.Image; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.Shape; |
| import java.awt.Toolkit; |
| import java.awt.font.GlyphVector; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.Point2D; |
| import java.awt.geom.Rectangle2D; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ColorModel; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.ImageProducer; |
| import java.awt.image.Raster; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.WritableRaster; |
| import java.util.Hashtable; |
| |
| /** |
| * ComponentGraphics - context for drawing directly to a component, |
| * as this is an X drawable, it requires that we use GTK locks. |
| * |
| * This context draws directly to the drawable and requires xrender. |
| */ |
| public class ComponentGraphics extends CairoGraphics2D |
| { |
| private static final boolean hasXRenderExtension = hasXRender(); |
| |
| private GtkComponentPeer component; |
| protected long cairo_t; |
| private BufferedImage buffer, componentBuffer; |
| |
| private static ThreadLocal<Integer> hasLock = new ThreadLocal<Integer>(); |
| private static Integer ONE = Integer.valueOf(1); |
| |
| ComponentGraphics() |
| { |
| } |
| |
| private ComponentGraphics(GtkComponentPeer component) |
| { |
| this.component = component; |
| cairo_t = initState(component); |
| setup( cairo_t ); |
| Rectangle bounds = component.awtComponent.getBounds(); |
| setClip( new Rectangle( 0, 0, bounds.width, bounds.height) ); |
| setBackground(component.awtComponent.getBackground()); |
| setColor(component.awtComponent.getForeground()); |
| } |
| |
| private ComponentGraphics(ComponentGraphics cg) |
| { |
| component = cg.component; |
| cairo_t = initState(component); |
| copy( cg, cairo_t ); |
| Rectangle bounds = component.awtComponent.getBounds(); |
| setClip( new Rectangle( 0, 0, bounds.width, bounds.height) ); |
| setBackground(component.awtComponent.getBackground()); |
| setColor(component.awtComponent.getForeground()); |
| } |
| |
| /** |
| * Creates a cairo_t for the component surface and return it. |
| */ |
| private native long initState(GtkComponentPeer component); |
| |
| /** |
| * Obtain and hold a GDK lock, which is required for all drawing operations |
| * in this graphics context (since it is backed by an X surface). |
| * |
| * This method causes the GDK locking behaviour to be re-entrant. No race |
| * conditions are caused since a ThreadLocal is used and each thread has its |
| * own lock counter. |
| */ |
| private void lock() |
| { |
| Integer i = hasLock.get(); |
| if (i == null) |
| { |
| start_gdk_drawing(); |
| hasLock.set(ONE); |
| } |
| else |
| hasLock.set(Integer.valueOf(i.intValue() + 1)); |
| } |
| |
| /** |
| * Release the re-entrant GDK lock. |
| */ |
| private void unlock() |
| { |
| Integer i = hasLock.get(); |
| if (i == null) |
| throw new IllegalStateException(); |
| if (i == ONE) |
| { |
| hasLock.set(null); |
| end_gdk_drawing(); |
| } |
| else if (i.intValue() == 2) |
| hasLock.set(ONE); |
| else |
| hasLock.set(Integer.valueOf(i.intValue() - 1)); |
| } |
| |
| /** |
| * Creates a cairo_t for a volatile image |
| */ |
| protected native long initFromVolatile( long pixmapPtr); |
| |
| /** |
| * Grab lock |
| */ |
| private native void start_gdk_drawing(); |
| |
| /** |
| * Release lock |
| */ |
| private native void end_gdk_drawing(); |
| |
| /** |
| * Query if the system has the XRender extension. |
| */ |
| public static native boolean hasXRender(); |
| |
| /** |
| * This is a utility method (used by GtkComponentPeer) for grabbing the |
| * image of a component. |
| */ |
| private static native Pointer nativeGrab(GtkComponentPeer component); |
| |
| private native void copyAreaNative(GtkComponentPeer component, int x, int y, |
| int width, int height, int dx, int dy); |
| |
| private native void drawVolatile(GtkComponentPeer component, |
| long vimg, int x, int y, |
| int width, int height, int cx, int cy, |
| int cw, int ch); |
| |
| /** |
| * Not really related (moveme?). Utility method used by GtkComponent. |
| */ |
| public static GtkImage grab( GtkComponentPeer component ) |
| { |
| return new GtkImage( nativeGrab( component ) ); |
| } |
| |
| /** |
| * Returns a Graphics2D object for a component, either an instance of this |
| * class (if xrender is supported), or a context which copies. |
| */ |
| public static Graphics2D getComponentGraphics(GtkComponentPeer component) |
| { |
| if( hasXRenderExtension ) |
| return new ComponentGraphics(component); |
| |
| Rectangle r = component.awtComponent.getBounds(); |
| return new ComponentGraphicsCopy(r.width, r.height, component); |
| } |
| |
| public GraphicsConfiguration getDeviceConfiguration() |
| { |
| return component.getGraphicsConfiguration(); |
| } |
| |
| public Graphics create() |
| { |
| return new ComponentGraphics(this); |
| } |
| |
| protected Rectangle2D getRealBounds() |
| { |
| return component.awtComponent.getBounds(); |
| } |
| |
| public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy) |
| { |
| copyAreaNative(component, x, y, width, height, dx, dy); |
| } |
| |
| /** |
| * Overloaded methods that do actual drawing need to enter the gdk threads |
| * and also do certain things before and after. |
| */ |
| public void draw(Shape s) |
| { |
| if (comp == null || comp instanceof AlphaComposite) |
| super.draw(s); |
| |
| else |
| { |
| createBuffer(); |
| |
| Graphics2D g2d = (Graphics2D)buffer.getGraphics(); |
| g2d.setStroke(this.getStroke()); |
| g2d.setColor(this.getColor()); |
| g2d.draw(s); |
| |
| drawComposite(s.getBounds2D(), null); |
| } |
| } |
| |
| public void fill(Shape s) |
| { |
| if (comp == null || comp instanceof AlphaComposite) |
| super.fill(s); |
| |
| else |
| { |
| createBuffer(); |
| |
| Graphics2D g2d = (Graphics2D)buffer.getGraphics(); |
| g2d.setPaint(this.getPaint()); |
| g2d.setColor(this.getColor()); |
| g2d.fill(s); |
| |
| drawComposite(s.getBounds2D(), null); |
| } |
| } |
| |
| public void drawRenderedImage(RenderedImage image, AffineTransform xform) |
| { |
| if (comp == null || comp instanceof AlphaComposite) |
| super.drawRenderedImage(image, xform); |
| |
| else |
| { |
| createBuffer(); |
| |
| Graphics2D g2d = (Graphics2D)buffer.getGraphics(); |
| g2d.setRenderingHints(this.getRenderingHints()); |
| g2d.drawRenderedImage(image, xform); |
| |
| drawComposite(buffer.getRaster().getBounds(), null); |
| } |
| } |
| |
| protected boolean drawImage(Image img, AffineTransform xform, |
| Color bgcolor, ImageObserver obs) |
| { |
| boolean rv; |
| if (comp == null || comp instanceof AlphaComposite) |
| rv = super.drawImage(img, xform, bgcolor, obs); |
| |
| else |
| { |
| // Get buffered image of source |
| if( !(img instanceof BufferedImage) ) |
| { |
| ImageProducer source = img.getSource(); |
| if (source == null) |
| return false; |
| img = Toolkit.getDefaultToolkit().createImage(source); |
| } |
| BufferedImage bImg = (BufferedImage) img; |
| |
| // Find translated bounds |
| Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY()); |
| Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(), |
| bImg.getHeight() + bImg.getMinY()); |
| if (xform != null) |
| { |
| origin = xform.transform(origin, origin); |
| pt = xform.transform(pt, pt); |
| } |
| |
| // Create buffer and draw image |
| createBuffer(); |
| |
| Graphics2D g2d = (Graphics2D)buffer.getGraphics(); |
| g2d.setRenderingHints(this.getRenderingHints()); |
| g2d.drawImage(img, xform, obs); |
| |
| // Perform compositing |
| rv = drawComposite(new Rectangle2D.Double(origin.getX(), |
| origin.getY(), |
| pt.getX(), pt.getY()), |
| obs); |
| } |
| return rv; |
| } |
| |
| public void drawGlyphVector(GlyphVector gv, float x, float y) |
| { |
| if (comp == null || comp instanceof AlphaComposite) |
| super.drawGlyphVector(gv, x, y); |
| |
| else |
| { |
| createBuffer(); |
| |
| Graphics2D g2d = (Graphics2D)buffer.getGraphics(); |
| g2d.setPaint(this.getPaint()); |
| g2d.setStroke(this.getStroke()); |
| g2d.drawGlyphVector(gv, x, y); |
| |
| Rectangle2D bounds = gv.getLogicalBounds(); |
| bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(), |
| bounds.getWidth(), bounds.getHeight()); |
| drawComposite(bounds, null); |
| } |
| } |
| |
| public boolean drawImage(Image img, int x, int y, ImageObserver observer) |
| { |
| // If it is a GtkVolatileImage with an "easy" transform then |
| // draw directly. Always pass a BufferedImage to super to avoid |
| // deadlock (see Note in CairoGraphics.drawImage()). |
| if (img instanceof GtkVolatileImage) |
| { |
| GtkVolatileImage vimg = (GtkVolatileImage) img; |
| int type = transform.getType(); |
| if ((type == AffineTransform.TYPE_IDENTITY |
| || type == AffineTransform.TYPE_TRANSLATION) |
| && (clip == null || clip instanceof Rectangle2D)) |
| { |
| Rectangle2D r = (Rectangle2D) clip; |
| if (r == null) |
| r = getRealBounds(); |
| x += transform.getTranslateX(); |
| y += transform.getTranslateY(); |
| drawVolatile(component, vimg.nativePointer, |
| x, y, vimg.width, vimg.height, |
| (int) (r.getX() + transform.getTranslateX()), |
| (int) (r.getY() + transform.getTranslateY()), |
| (int) r.getWidth(), |
| (int) r.getHeight()); |
| return true; |
| } |
| else |
| return super.drawImage(vimg.getSnapshot(), x, y, observer); |
| } |
| |
| BufferedImage bimg; |
| if (img instanceof BufferedImage) |
| bimg = (BufferedImage) img; |
| else |
| { |
| ImageProducer source = img.getSource(); |
| if (source == null) |
| return false; |
| bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source); |
| } |
| return super.drawImage(bimg, x, y, observer); |
| } |
| |
| public boolean drawImage(Image img, int x, int y, int width, int height, |
| ImageObserver observer) |
| { |
| // If it is a GtkVolatileImage with an "easy" transform then |
| // draw directly. Always pass a BufferedImage to super to avoid |
| // deadlock (see Note in CairoGraphics.drawImage()). |
| if (img instanceof GtkVolatileImage |
| && (clip == null || clip instanceof Rectangle2D)) |
| { |
| GtkVolatileImage vimg = (GtkVolatileImage) img; |
| int type = transform.getType(); |
| if ((type == AffineTransform.TYPE_IDENTITY |
| || type == AffineTransform.TYPE_TRANSLATION) |
| && (clip == null || clip instanceof Rectangle2D)) |
| { |
| Rectangle2D r = (Rectangle2D) clip; |
| if (r == null) |
| r = getRealBounds(); |
| x += transform.getTranslateX(); |
| y += transform.getTranslateY(); |
| drawVolatile(component, vimg.nativePointer, |
| x, y, width, height, |
| (int) (r.getX() + transform.getTranslateX()), |
| (int) (r.getY() + transform.getTranslateY()), |
| (int) r.getWidth(), |
| (int) r.getHeight()); |
| return true; |
| } |
| else |
| return super.drawImage(vimg.getSnapshot(), x, y, |
| width, height, observer); |
| } |
| |
| BufferedImage bimg; |
| img = AsyncImage.realImage(img, observer); |
| if (img instanceof BufferedImage) |
| bimg = (BufferedImage) img; |
| else |
| { |
| ImageProducer source = img.getSource(); |
| if (source == null) |
| return false; |
| bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source); |
| } |
| return super.drawImage(bimg, x, y, width, height, observer); |
| } |
| |
| private boolean drawComposite(Rectangle2D bounds, ImageObserver observer) |
| { |
| // Clip source to visible areas that need updating |
| Rectangle2D clip = this.getClipBounds(); |
| Rectangle2D.intersect(bounds, clip, bounds); |
| clip = new Rectangle(buffer.getMinX(), buffer.getMinY(), |
| buffer.getWidth(), buffer.getHeight()); |
| Rectangle2D.intersect(bounds, clip, bounds); |
| |
| BufferedImage buffer2 = buffer; |
| if (!bounds.equals(buffer2.getRaster().getBounds())) |
| buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(), |
| (int)bounds.getWidth(), |
| (int)bounds.getHeight()); |
| |
| // Get destination clip to bounds |
| double[] points = new double[] {bounds.getX(), bounds.getY(), |
| bounds.getMaxX(), bounds.getMaxY()}; |
| transform.transform(points, 0, points, 0, 2); |
| |
| Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1], |
| points[2] - points[0], |
| points[3] - points[1]); |
| |
| Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds); |
| |
| // Get current image on the component |
| GtkImage img = grab(component); |
| Graphics gr = componentBuffer.createGraphics(); |
| gr.drawImage(img, 0, 0, null); |
| gr.dispose(); |
| |
| BufferedImage cBuffer = componentBuffer; |
| if (!deviceBounds.equals(cBuffer.getRaster().getBounds())) |
| cBuffer = cBuffer.getSubimage((int)deviceBounds.getX(), |
| (int)deviceBounds.getY(), |
| (int)deviceBounds.getWidth(), |
| (int)deviceBounds.getHeight()); |
| |
| // Perform actual composite operation |
| compCtx.compose(buffer2.getRaster(), cBuffer.getRaster(), |
| cBuffer.getRaster()); |
| |
| // This MUST call directly into the "action" method in CairoGraphics2D, |
| // not one of the wrappers, to ensure that the composite isn't processed |
| // more than once! |
| boolean rv = super.drawImage(cBuffer, |
| AffineTransform.getTranslateInstance(bounds.getX(), |
| bounds.getY()), |
| null, null); |
| return rv; |
| } |
| |
| private void createBuffer() |
| { |
| if (buffer == null) |
| { |
| WritableRaster rst; |
| rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(), |
| component.awtComponent.getHeight()), |
| new Point(0,0)); |
| |
| buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst, |
| GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(), |
| new Hashtable()); |
| } |
| else |
| { |
| Graphics2D g2d = ((Graphics2D)buffer.getGraphics()); |
| |
| g2d.setBackground(new Color(0,0,0,0)); |
| g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight()); |
| } |
| |
| if (componentBuffer == null) |
| { |
| WritableRaster rst; |
| rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(), |
| component.awtComponent.getHeight()), |
| new Point(0,0)); |
| |
| componentBuffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst, |
| GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(), |
| new Hashtable()); |
| } |
| } |
| |
| protected ColorModel getNativeCM() |
| { |
| return GtkVolatileImage.gdkColorModel; |
| } |
| |
| /* --- START OVERRIDDEN NATIVE METHODS ---- |
| * All native methods in CairoGraphics2D should be overridden here and |
| * enclosed in locks, since the cairo surface is backed by an X surface |
| * in this graphics context and the X surface requires external locking. |
| * |
| * We lock everything "just in case", since it's difficult to know which |
| * calls are and aren't thread-safe. Overriding and locking the native |
| * methods allows superclass code in CairoGraphics2D to execute properly, |
| * without the need to override every single method. |
| * |
| * CAVEAT: if native code obtains a lock (using gdk_threads_enter(), not the |
| * lock() method provided here) and then calls back into Java and one of these |
| * methods ends up being called, we will deadlock. The lock is only reentrant |
| * when called via our lock() method. |
| */ |
| |
| /* These methods are already locked in the superclass CairoGraphics2D |
| * so they do not need to be overridden: |
| * |
| * public void disposeNative |
| * |
| * protected void cairoDrawGlyphVector |
| * |
| * protected void cairoSetFont |
| */ |
| |
| @Override |
| protected long init(long pointer) |
| { |
| long ret; |
| |
| try |
| { |
| lock(); |
| ret = super.init(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| protected void drawPixels(long pointer, int[] pixels, int w, int h, |
| int stride, double[] i2u, double alpha, |
| int interpolation) |
| { |
| try |
| { |
| lock(); |
| super.drawPixels(pointer, pixels, w, h, stride, i2u, alpha, |
| interpolation); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void setGradient(long pointer, double x1, double y1, |
| double x2, double y2, |
| int r1, int g1, int b1, int a1, |
| int r2, int g2, int b2, int a2, boolean cyclic) |
| { |
| try |
| { |
| lock(); |
| super.setGradient(pointer, x1, y1, x2, y2, r1, g1, b1, a1, r2, g2, b2, a2, |
| cyclic); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void setPaintPixels(long pointer, int[] pixels, int w, int h, |
| int stride, boolean repeat, int x, int y) |
| { |
| try |
| { |
| lock(); |
| super.setPaintPixels(pointer, pixels, w, h, stride, repeat, x, y); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetMatrix(long pointer, double[] m) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetMatrix(pointer, m); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoScale(long pointer, double x, double y) |
| { |
| try |
| { |
| lock(); |
| super.cairoScale(pointer, x, y); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetOperator(long pointer, int cairoOperator) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetOperator(pointer, cairoOperator); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetRGBAColor(long pointer, double red, double green, |
| double blue, double alpha) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetRGBAColor(pointer, red, green, blue, alpha); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetFillRule(long pointer, int cairoFillRule) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetFillRule(pointer, cairoFillRule); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetLine(long pointer, double width, int cap, int join, |
| double miterLimit) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetLine(pointer, width, cap, join, miterLimit); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetDash(long pointer, double[] dashes, int ndash, |
| double offset) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetDash(pointer, dashes, ndash, offset); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoRectangle(long pointer, double x, double y, |
| double width, double height) |
| { |
| try |
| { |
| lock(); |
| super.cairoRectangle(pointer, x, y, width, height); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoArc(long pointer, double x, double y, |
| double radius, double angle1, double angle2) |
| { |
| try |
| { |
| lock(); |
| super.cairoArc(pointer, x, y, radius, angle1, angle2); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSave(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoSave(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoRestore(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoRestore(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoNewPath(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoNewPath(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoClosePath(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoClosePath(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoMoveTo(long pointer, double x, double y) |
| { |
| try |
| { |
| lock(); |
| super.cairoMoveTo(pointer, x, y); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoLineTo(long pointer, double x, double y) |
| { |
| try |
| { |
| lock(); |
| super.cairoLineTo(pointer, x, y); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoCurveTo(long pointer, double x1, double y1, double x2, |
| double y2, double x3, double y3) |
| { |
| try |
| { |
| lock(); |
| super.cairoCurveTo(pointer, x1, y1, x2, y2, x3, y3); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoStroke(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoStroke(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoFill(long pointer, double alpha) |
| { |
| try |
| { |
| lock(); |
| super.cairoFill(pointer, alpha); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoClip(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoClip(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoResetClip(long pointer) |
| { |
| try |
| { |
| lock(); |
| super.cairoResetClip(pointer); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void cairoSetAntialias(long pointer, boolean aa) |
| { |
| try |
| { |
| lock(); |
| super.cairoSetAntialias(pointer, aa); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| |
| @Override |
| protected void drawCairoSurface(CairoSurface surface, AffineTransform tx, |
| double alpha, int interpolation) |
| { |
| try |
| { |
| lock(); |
| super.drawCairoSurface(surface, tx, alpha, interpolation); |
| } |
| finally |
| { |
| unlock(); |
| } |
| } |
| } |