summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java')
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java629
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();
+ }
+ }
}
-
OpenPOWER on IntegriCloud