diff options
Diffstat (limited to 'libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java')
-rw-r--r-- | libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java | 629 |
1 files changed, 498 insertions, 131 deletions
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java index 098052ae961..be82f81ecbd 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java @@ -112,6 +112,14 @@ public class ComponentGraphics extends CairoGraphics2D */ 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 = (Integer) hasLock.get(); @@ -124,6 +132,9 @@ public class ComponentGraphics extends CairoGraphics2D hasLock.set(Integer.valueOf(i.intValue() + 1)); } + /** + * Release the re-entrant GDK lock. + */ private void unlock() { Integer i = (Integer) hasLock.get(); @@ -219,78 +230,54 @@ public class ComponentGraphics extends CairoGraphics2D */ public void draw(Shape s) { - lock(); - try - { - if (comp == null || comp instanceof AlphaComposite) - super.draw(s); + if (comp == null || comp instanceof AlphaComposite) + super.draw(s); - else - { - createBuffer(); + else + { + createBuffer(); - Graphics2D g2d = (Graphics2D)buffer.getGraphics(); - g2d.setStroke(this.getStroke()); - g2d.setColor(this.getColor()); - g2d.draw(s); + Graphics2D g2d = (Graphics2D)buffer.getGraphics(); + g2d.setStroke(this.getStroke()); + g2d.setColor(this.getColor()); + g2d.draw(s); - drawComposite(s.getBounds2D(), null); - } - } - finally - { - unlock(); + drawComposite(s.getBounds2D(), null); } } public void fill(Shape s) { - lock(); - try - { - if (comp == null || comp instanceof AlphaComposite) - super.fill(s); + if (comp == null || comp instanceof AlphaComposite) + super.fill(s); - else - { - createBuffer(); + else + { + createBuffer(); - Graphics2D g2d = (Graphics2D)buffer.getGraphics(); - g2d.setPaint(this.getPaint()); - g2d.setColor(this.getColor()); - g2d.fill(s); + Graphics2D g2d = (Graphics2D)buffer.getGraphics(); + g2d.setPaint(this.getPaint()); + g2d.setColor(this.getColor()); + g2d.fill(s); - drawComposite(s.getBounds2D(), null); - } - } - finally - { - unlock(); + drawComposite(s.getBounds2D(), null); } } public void drawRenderedImage(RenderedImage image, AffineTransform xform) { - lock(); - try - { - if (comp == null || comp instanceof AlphaComposite) - super.drawRenderedImage(image, xform); + if (comp == null || comp instanceof AlphaComposite) + super.drawRenderedImage(image, xform); - else - { - createBuffer(); + else + { + createBuffer(); - Graphics2D g2d = (Graphics2D)buffer.getGraphics(); - g2d.setRenderingHints(this.getRenderingHints()); - g2d.drawRenderedImage(image, xform); + Graphics2D g2d = (Graphics2D)buffer.getGraphics(); + g2d.setRenderingHints(this.getRenderingHints()); + g2d.drawRenderedImage(image, xform); - drawComposite(buffer.getRaster().getBounds(), null); - } - } - finally - { - unlock(); + drawComposite(buffer.getRaster().getBounds(), null); } } @@ -298,81 +285,65 @@ public class ComponentGraphics extends CairoGraphics2D Color bgcolor, ImageObserver obs) { boolean rv; - lock(); - try - { - if (comp == null || comp instanceof AlphaComposite) - rv = super.drawImage(img, xform, bgcolor, obs); + if (comp == null || comp instanceof AlphaComposite) + rv = super.drawImage(img, xform, bgcolor, obs); - else + else + { + // Get buffered image of source + if( !(img instanceof BufferedImage) ) { - // 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; + 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); - } + // 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(); + // 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); - } - } - finally - { - unlock(); + 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) { - lock(); - try - { - if (comp == null || comp instanceof AlphaComposite) - super.drawGlyphVector(gv, x, y); + if (comp == null || comp instanceof AlphaComposite) + super.drawGlyphVector(gv, x, y); - else - { - createBuffer(); + else + { + createBuffer(); - Graphics2D g2d = (Graphics2D)buffer.getGraphics(); - g2d.setPaint(this.getPaint()); - g2d.setStroke(this.getStroke()); - g2d.drawGlyphVector(gv, x, y); + 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); - } - } - finally - { - unlock(); + Rectangle2D bounds = gv.getLogicalBounds(); + bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(), + bounds.getWidth(), bounds.getHeight()); + drawComposite(bounds, null); } } @@ -466,20 +437,6 @@ public class ComponentGraphics extends CairoGraphics2D return super.drawImage(bimg, x, y, width, height, observer); } - public void setClip(Shape s) - { - lock(); - try - { - super.setClip(s); - } - finally - { - unlock(); - } - } - - private boolean drawComposite(Rectangle2D bounds, ImageObserver observer) { // Clip source to visible areas that need updating @@ -507,12 +464,10 @@ public class ComponentGraphics extends CairoGraphics2D Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds); // Get current image on the component - unlock(); GtkImage img = grab(component); Graphics gr = componentBuffer.createGraphics(); gr.drawImage(img, 0, 0, null); gr.dispose(); - lock(); BufferedImage cBuffer = componentBuffer; if (!deviceBounds.equals(cBuffer.getRaster().getBounds())) @@ -573,5 +528,417 @@ public class ComponentGraphics extends CairoGraphics2D { 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. + */ + @Override + protected long init(long pointer) + { + long ret; + + try + { + lock(); + ret = super.init(pointer); + } + finally + { + unlock(); + } + + return ret; + } + + @Override + public void disposeNative(long pointer) + { + try + { + lock(); + super.disposeNative(pointer); + } + finally + { + unlock(); + } + } + + @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 cairoDrawGlyphVector(long pointer, GdkFontPeer font, + float x, float y, int n, + int[] codes, float[] positions) + { + try + { + lock(); + super.cairoDrawGlyphVector(pointer, font, x, y, n, codes, positions); + } + finally + { + unlock(); + } + } + + @Override + protected void cairoSetFont(long pointer, GdkFontPeer font) + { + try + { + lock(); + super.cairoSetFont(pointer, font); + } + 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(); + } + } } - |