aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@redhat.com>2003-09-17 20:03:02 +0000
committerGraydon Hoare <graydon@gcc.gnu.org>2003-09-17 20:03:02 +0000
commit1fe2d5fb0998455d5faec36e62a8919ad16c939f (patch)
treef6def737e08704bfb28fabae57e50f10d4bd3e3f
parenteeae7b417a7a1e90d7da1f512048d697f5b3a4f6 (diff)
downloadgcc-1fe2d5fb0998455d5faec36e62a8919ad16c939f.zip
gcc-1fe2d5fb0998455d5faec36e62a8919ad16c939f.tar.gz
gcc-1fe2d5fb0998455d5faec36e62a8919ad16c939f.tar.bz2
GdkGraphics2D.java, [...]: New files.
2003-09-17 Graydon Hoare <graydon@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java, gnu/java/awt/peer/gtk/GdkPixbufDecoder.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c, jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: New files. From-SVN: r71475
-rw-r--r--libjava/ChangeLog8
-rw-r--r--libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java1146
-rw-r--r--libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java217
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c1069
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c236
5 files changed, 2676 insertions, 0 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 6c208a4..9b98128 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,11 @@
+2003-09-17 Graydon Hoare <graydon@redhat.com>
+
+ * gnu/java/awt/peer/gtk/GdkGraphics2D.java,
+ gnu/java/awt/peer/gtk/GdkPixbufDecoder.java,
+ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c,
+ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c:
+ New files.
+
2003-09-16 Graydon Hoare <graydon@redhat.com>
* java/awt/BufferedImage.java (setData): Support non-component
diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java
new file mode 100644
index 0000000..11c0371
--- /dev/null
+++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java
@@ -0,0 +1,1146 @@
+/* GdkGraphics2D.java
+ Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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 java.awt.*;
+import java.awt.geom.*;
+import java.awt.font.*;
+import java.awt.color.*;
+import java.awt.image.*;
+import java.awt.image.renderable.*;
+
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+import java.lang.Integer;
+import gnu.classpath.Configuration;
+
+public class GdkGraphics2D extends Graphics2D
+{
+
+ //////////////////////////////////////
+ ////// State Management Methods //////
+ //////////////////////////////////////
+
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("gtkpeer");
+ }
+ initStaticState ();
+ }
+ native static void initStaticState ();
+ private final int native_state = GtkGenericPeer.getUniqueInteger();
+
+ private Paint paint;
+ private Stroke stroke;
+ private Color fg;
+ private Color bg;
+ private Shape clip;
+ private AffineTransform transform;
+ private GtkComponentPeer component;
+ private GdkFont font;
+
+ native private int[] initState (GtkComponentPeer component);
+ native private void initState (int width, int height);
+ native private void copyState (GdkGraphics2D g);
+ native public void dispose ();
+
+ public void finalize ()
+ {
+ dispose();
+ }
+
+ public Graphics create ()
+ {
+ return new GdkGraphics2D (this);
+ }
+
+ public Graphics create (int x, int y, int width, int height)
+ {
+ return new GdkGraphics2D (width, height);
+ }
+
+ GdkGraphics2D (GdkGraphics2D g)
+ {
+ paint = g.paint;
+ stroke = g.stroke;
+
+ if (g.fg.getAlpha() != -1)
+ fg = new Color (g.fg.getRed (), g.fg.getGreen (),
+ g.fg.getBlue (), g.fg.getAlpha ());
+ else
+ fg = new Color (g.fg.getRGB ());
+
+ if (g.bg.getAlpha() != -1)
+ bg = new Color(g.bg.getRed (), g.bg.getGreen (),
+ g.bg.getBlue (), g.bg.getAlpha ());
+ else
+ bg = new Color (g.bg.getRGB ());
+
+ if (g.clip == null)
+ clip = null;
+ else
+ clip = new Rectangle (g.getClipBounds ());
+
+ if (g.transform == null)
+ transform = null;
+ else
+ transform = new AffineTransform (g.transform);
+
+ component = g.component;
+ copyState (g);
+
+ setColor (fg);
+ setClip (clip);
+ setTransform (transform);
+ }
+
+ GdkGraphics2D (int width, int height)
+ {
+ initState (width, height);
+ bg = Color.black;
+ fg = Color.black;
+ transform = new AffineTransform ();
+ }
+
+ GdkGraphics2D (GtkComponentPeer component)
+ {
+ this.component = component;
+ int rgb[] = initState (component);
+ fg = new Color (rgb[0], rgb[1], rgb[2]);
+ bg = new Color (rgb[3], rgb[4], rgb[5]);
+ transform = new AffineTransform ();
+ }
+
+
+ ////////////////////////////////////
+ ////// Native Drawing Methods //////
+ ////////////////////////////////////
+
+ // GDK drawing methods
+ private native void gdkDrawDrawable (GdkGraphics2D other, int x, int y);
+
+ // drawing utility methods
+ private native void drawPixels (int pixels[], int w, int h, int stride);
+ private native void setTexturePixels (int pixels[], int w, int h, int stride);
+ private native void setGradient (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);
+
+ // simple passthroughs to cairo
+ private native void cairoSave ();
+ private native void cairoRestore ();
+ private native void cairoSetMatrix (double m00, double m10,
+ double m01, double m11,
+ double m02, double m12);
+ private native void cairoSetOperator (int cairoOperator);
+ private native void cairoSetRGBColor (double red, double green, double blue);
+ private native void cairoSetAlpha (double alpha);
+ private native void cairoSetFillRule (int cairoFillRule);
+ private native void cairoSetLineWidth (double width);
+ private native void cairoSetLineCap (int cairoLineCap);
+ private native void cairoSetLineJoin (int cairoLineJoin);
+ private native void cairoSetDash (double dashes[], int ndash, double offset);
+ private native void cairoSetMiterLimit (double limit);
+ private native void cairoTranslate (double tx, double ty);
+ private native void cairoScale (double sx, double sy);
+ private native void cairoRotate (double angle);
+ private native void cairoNewPath ();
+ private native void cairoMoveTo (double x, double y);
+ private native void cairoLineTo (double x, double y);
+ private native void cairoCurveTo (double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+ private native void cairoRelMoveTo (double dx, double dy);
+ private native void cairoRelLineTo (double dx, double dy);
+ private native void cairoRelCurveTo (double dx1, double dy1,
+ double dx2, double dy2,
+ double dx3, double dy3);
+ private native void cairoRectangle (double x, double y,
+ double width, double height);
+ private native void cairoClosePath ();
+ private native void cairoStroke ();
+ private native void cairoFill ();
+ private native void cairoClip ();
+
+
+ /////////////////////////////////////////////
+ ////// General Drawing Support Methods //////
+ /////////////////////////////////////////////
+
+ double x;
+ double y;
+ private void setPos (double nx, double ny)
+ {
+ x = nx;
+ y = ny;
+ }
+
+ private void walkPath(PathIterator p)
+ {
+ double coords[] = new double[6];
+
+ cairoSetFillRule (p.getWindingRule ());
+ for ( ; ! p.isDone (); p.next())
+ {
+ int seg = p.currentSegment (coords);
+ switch(seg)
+ {
+
+ case PathIterator.SEG_MOVETO:
+ setPos(coords[0], coords[1]);
+ cairoMoveTo (coords[0], coords[1]);
+ break;
+
+ case PathIterator.SEG_LINETO:
+ setPos(coords[0], coords[1]);
+ cairoLineTo (coords[0], coords[1]);
+ break;
+
+ case PathIterator.SEG_QUADTO:
+
+ // splitting a quadratic bezier into a cubic:
+ // see: http://pfaedit.sourceforge.net/bezier.html
+
+ double x1 = x + (2.0/3.0) * (coords[0] - x);
+ double y1 = y + (2.0/3.0) * (coords[1] - y);
+
+ double x2 = x1 + (1.0/3.0) * (coords[2] - x);
+ double y2 = y1 + (1.0/3.0) * (coords[3] - y);
+
+ setPos(coords[2], coords[3]);
+ cairoCurveTo (x1, y1,
+ x2, y2,
+ coords[2], coords[3]);
+ break;
+
+ case PathIterator.SEG_CUBICTO:
+ setPos(coords[4], coords[5]);
+ cairoCurveTo (coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]);
+ break;
+
+ case PathIterator.SEG_CLOSE:
+ cairoClosePath ();
+ break;
+ }
+ }
+ }
+
+
+ //////////////////////////////////////////////////
+ ////// Implementation of Graphics2D Methods //////
+ //////////////////////////////////////////////////
+
+ public void draw (Shape s)
+ {
+
+ if (stroke != null &&
+ !(stroke instanceof BasicStroke))
+ {
+ fill (stroke.createStrokedShape (s));
+ return;
+ }
+
+ cairoSave ();
+ cairoNewPath ();
+ if (s instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D)s;
+ cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
+ }
+ else
+ walkPath (s.getPathIterator (null));
+ cairoStroke ();
+ cairoRestore ();
+ }
+
+ public void fill(Shape s)
+ {
+ cairoSave();
+ cairoNewPath ();
+ if (s instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D)s;
+ cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
+ }
+ else
+ walkPath (s.getPathIterator (null));
+ cairoFill ();
+ cairoRestore ();
+ }
+
+ public void clip (Shape s)
+ {
+ clip = s;
+ cairoNewPath ();
+ if (s instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D)s;
+ cairoRectangle (r.getX (), r.getY (),
+ r.getWidth (), r.getHeight ());
+ }
+ else
+ walkPath (s.getPathIterator (null));
+ cairoClosePath ();
+ cairoClip ();
+ }
+
+ public Paint getPaint ()
+ {
+ return paint;
+ }
+
+ public AffineTransform getTransform ()
+ {
+ return transform;
+ }
+
+ public void setPaint (Paint p)
+ {
+ paint = p;
+ if (paint instanceof Color)
+ {
+ setColor ((Color) paint);
+ }
+ else if (paint instanceof TexturePaint)
+ {
+ TexturePaint tp = (TexturePaint) paint;
+ BufferedImage img = tp.getImage ();
+ int pixels[] = img.getRGB(0, 0, img.getWidth (),
+ img.getHeight (), null,
+ 0, img.getWidth ());
+ setTexturePixels (pixels, img.getWidth (),
+ img.getHeight (), img.getWidth ());
+ }
+ else if (paint instanceof GradientPaint)
+ {
+ GradientPaint gp = (GradientPaint) paint;
+ Point2D p1 = gp.getPoint1 ();
+ Point2D p2 = gp.getPoint2 ();
+ Color c1 = gp.getColor1 ();
+ Color c2 = gp.getColor2 ();
+ setGradient (p1.getX (), p1.getY (),
+ p2.getX (), p2.getY (),
+ c1.getRed (), c1.getGreen (),
+ c1.getBlue (), c1.getAlpha (),
+ c2.getRed (), c2.getGreen (),
+ c2.getBlue (), c2.getAlpha (),
+ gp.isCyclic ());
+ }
+ else
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void setTransform (AffineTransform tx)
+ {
+ transform = tx;
+ if (transform != null)
+ {
+ double m[] = new double[6];
+ transform.getMatrix (m);
+ cairoSetMatrix (m[0], m[1], m[2], m[3], m[4], m[5]);
+ }
+ }
+
+ public void transform (AffineTransform tx)
+ {
+ if (transform == null)
+ transform = new AffineTransform (tx);
+ else
+ transform.concatenate (tx);
+ setTransform (transform);
+ }
+
+ public void rotate(double theta)
+ {
+ if (transform != null)
+ transform.rotate (theta);
+ cairoRotate (theta);
+ }
+
+ public void rotate(double theta, double x, double y)
+ {
+ if (transform != null)
+ transform.rotate (theta, x, y);
+ cairoTranslate (x, y);
+ cairoRotate (theta);
+ cairoTranslate (-x, -y);
+ }
+
+ public void scale(double sx, double sy)
+ {
+ if (transform != null)
+ transform.scale (sx, sy);
+ cairoScale (sx, sy);
+ }
+
+ public void translate (double tx, double ty)
+ {
+ if (transform != null)
+ transform.translate (tx, ty);
+ cairoTranslate (tx, ty);
+ }
+
+ public void translate (int x, int y)
+ {
+ translate ((double) x, (double) y);
+ }
+
+ public Stroke getStroke()
+ {
+ return stroke;
+ }
+
+ public void setStroke (Stroke st)
+ {
+ stroke = st;
+ if (stroke instanceof BasicStroke)
+ {
+ BasicStroke bs = (BasicStroke) stroke;
+ cairoSetLineCap (bs.getEndCap());
+ cairoSetLineWidth (bs.getLineWidth());
+ cairoSetLineJoin (bs.getLineJoin());
+ cairoSetMiterLimit (bs.getMiterLimit());
+ float dashes[] = bs.getDashArray();
+ if (dashes != null)
+ {
+ double double_dashes[] = new double[dashes.length];
+ for (int i = 0; i < dashes.length; i++)
+ double_dashes[i] = dashes[i];
+ cairoSetDash (double_dashes, double_dashes.length,
+ (double) bs.getDashPhase ());
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////
+ ////// Implementation of Graphics Methods //////
+ ////////////////////////////////////////////////
+
+ public void setPaintMode ()
+ {
+ setComposite (java.awt.AlphaComposite.Xor);
+ }
+
+ public void setXORMode (Color c)
+ {
+ setComposite (new BitwiseXorComposite (c));
+ }
+
+ public void setColor (Color c)
+ {
+ fg = c;
+ cairoSetRGBColor (fg.getRed() / 255.0,
+ fg.getGreen() / 255.0,
+ fg.getBlue() / 255.0);
+ cairoSetAlpha ((fg.getAlpha() & 255) / 255.0);
+ }
+
+ public Color getColor ()
+ {
+ return fg;
+ }
+
+ public void clipRect (int x, int y, int width, int height)
+ {
+ // this is *slightly* different than all the other clip functions: it
+ // intersects the clip area with the new clip rectangle. obviously. of
+ // course, since Shape doesn't *have* any way of intersecting with a
+ // rectangle, we will promote the current clipping region to its
+ // bounding rectangle and then intersect with that.
+ if (clip == null)
+ {
+ cairoNewPath ();
+ cairoRectangle (x, y, width, height);
+ cairoClosePath ();
+ cairoClip ();
+ clip = new Rectangle (x, y, width, height);
+ }
+ else
+ {
+ clip (clip.getBounds ().intersection
+ (new Rectangle (x, y, width, height)));
+ }
+ }
+
+ public Shape getClip ()
+ {
+ return clip;
+ }
+
+ public Rectangle getClipBounds ()
+ {
+ if (clip == null)
+ return null;
+ else
+ return clip.getBounds ();
+ }
+
+ public void setClip (int x, int y, int width, int height)
+ {
+ cairoNewPath ();
+ cairoRectangle (x, y, width, height);
+ cairoClosePath ();
+ cairoClip ();
+ clip = new Rectangle (x, y, width, height);
+ }
+
+ public void setClip (Shape s)
+ {
+ clip (s);
+ }
+
+ public void draw3DRect(int x, int y, int width,
+ int height, boolean raised)
+ {
+ Color std = fg;
+ Color light = std.brighter();
+ Color dark = std.darker();
+
+ if (!raised)
+ {
+ Color t = light;
+ light = dark;
+ dark = t;
+ }
+
+ double x1 = (double) x;
+ double x2 = (double) x + width;
+
+ double y1 = (double) y;
+ double y2 = (double) y + height;
+
+ cairoSave ();
+
+ cairoNewPath ();
+ setColor (light);
+ cairoMoveTo (x1, y1);
+ cairoLineTo (x2, y1);
+ cairoLineTo (x2, y2);
+ cairoStroke ();
+
+ cairoNewPath ();
+ setColor (dark);
+ cairoMoveTo (x1, y1);
+ cairoLineTo (x1, y2);
+ cairoLineTo (x2, y2);
+ cairoStroke ();
+
+ cairoRestore ();
+ setColor (std);
+
+ }
+
+ public void fill3DRect(int x, int y, int width,
+ int height, boolean raised)
+ {
+ double step = 1.0;
+ if (stroke != null && stroke instanceof BasicStroke)
+ {
+ BasicStroke bs = (BasicStroke) stroke;
+ step = bs.getLineWidth();
+ }
+
+ Color bright = fg.brighter ();
+ Color dark = fg.darker ();
+
+ draw3DRect (x, y, width, height, raised);
+
+ cairoSave ();
+ cairoTranslate (step/2.0, step/2.0);
+ cairoNewPath ();
+ cairoRectangle ((double) x, (double) y,
+ ((double) width) - step,
+ ((double) height) - step );
+ cairoClosePath ();
+ cairoFill ();
+ cairoRestore ();
+ }
+
+
+ public void drawRect (int x, int y, int width, int height)
+ {
+ draw(new Rectangle (x, y, width, height));
+ }
+
+ public void fillRect (int x, int y, int width, int height)
+ {
+ fill(new Rectangle (x, y, width, height));
+ }
+
+ public void clearRect (int x, int y, int width, int height)
+ {
+ cairoSave ();
+ cairoSetRGBColor (bg.getRed() / 255.0,
+ bg.getGreen() / 255.0,
+ bg.getBlue() / 255.0);
+ cairoSetAlpha (1.0);
+ cairoNewPath ();
+ cairoRectangle (x, y, width, height);
+ cairoClosePath ();
+ cairoFill ();
+ cairoRestore ();
+ }
+
+ public void setBackground(Color c)
+ {
+ bg = c;
+ }
+
+
+ public Color getBackground()
+ {
+ return bg;
+ }
+
+
+ private void doPolygon(int[] xPoints, int[] yPoints, int nPoints,
+ boolean close, boolean fill)
+ {
+ if (nPoints < 1)
+ return;
+ GeneralPath gp = new GeneralPath ();
+ gp.moveTo ((float)xPoints[0], (float)yPoints[0]);
+ for (int i = 1; i < nPoints; i++)
+ gp.lineTo ((float)xPoints[i], (float)yPoints[i]);
+
+ if (close)
+ gp.closePath ();
+
+ Shape sh = gp;
+ if (fill == false &&
+ stroke != null &&
+ !(stroke instanceof BasicStroke))
+ {
+ sh = stroke.createStrokedShape (gp);
+ fill = true;
+ }
+
+ if (fill)
+ fill (sh);
+ else
+ draw (sh);
+ }
+
+ public void drawLine (int x1, int y1, int x2, int y2)
+ {
+ int xp[] = new int[2];
+ int yp[] = new int[2];
+
+ xp[0] = x1;
+ xp[1] = x2;
+ yp[0] = y1;
+ yp[1] = y2;
+
+ doPolygon (xp, yp, 2, false, false);
+ }
+
+ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ doPolygon (xPoints, yPoints, nPoints, true, true);
+ }
+
+ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ doPolygon (xPoints, yPoints, nPoints, true, false);
+ }
+
+ public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ doPolygon (xPoints, yPoints, nPoints, false, false);
+ }
+
+ private boolean drawRaster (ColorModel cm, Raster r)
+ {
+ if (r == null)
+ return false;
+
+ SampleModel sm = r.getSampleModel ();
+ DataBuffer db = r.getDataBuffer ();
+
+ if (db == null || sm == null)
+ return false;
+
+ if (cm == null)
+ cm = ColorModel.getRGBdefault ();
+
+ int pixels[] = null;
+
+ if (sm.getDataType () == DataBuffer.TYPE_INT &&
+ db instanceof DataBufferInt &&
+ db.getNumBanks () == 1)
+ {
+ // single bank, ARGB-ints buffer in sRGB space
+ DataBufferInt dbi = (DataBufferInt)db;
+ pixels = dbi.getData ();
+ }
+ else
+ pixels = r.getPixels (0, 0, r.getWidth (), r.getHeight (), pixels);
+
+ ColorSpace cs = cm.getColorSpace ();
+ if (cs != null &&
+ cs.getType () != ColorSpace.CS_sRGB)
+ {
+ int pixels2[] = new int[pixels.length];
+ for (int i = 0; i < pixels2.length; i++)
+ pixels2[i] = cm.getRGB (pixels[i]);
+ pixels = pixels2;
+ }
+
+ cairoSave ();
+ cairoTranslate (x, y);
+ drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth ());
+ cairoRestore ();
+ return true;
+ }
+
+ public boolean drawImage (Image img, int x, int y,
+ ImageObserver observer)
+ {
+ if (img instanceof GtkOffScreenImage &&
+ img.getGraphics () instanceof GdkGraphics2D &&
+ (transform == null || transform.isIdentity ()))
+ {
+ // we are being asked to flush a double buffer from Gdk
+ GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics ();
+ gdkDrawDrawable (g2, x, y);
+ return true;
+ }
+ else
+ {
+ if (img instanceof BufferedImage)
+ {
+ // draw an image which has actually been loaded into memory fully
+ BufferedImage b = (BufferedImage) img;
+ return drawRaster (b.getColorModel (), b.getData ());
+ }
+ else
+ {
+ // begin progressive loading in a separate thread
+ new PainterThread (this, img);
+ return false;
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////
+ ////// Supporting Private Classes //////
+ ////////////////////////////////////////
+
+ private class PainterThread implements Runnable, ImageConsumer
+ {
+
+ // this is a helper which is spun off when someone tries to do
+ // Graphics2D.drawImage on an image we cannot determine to be either
+ // one of our own offscreen images or a BufferedImage; that is, when
+ // someone wants to draw an image which is possibly still loading over
+ // a network or something. you run it in a separate thread and it
+ // writes through to the underlying Graphics2D as pixels becomg
+ // available.
+
+ GdkGraphics2D gr;
+ Image image;
+ ColorModel defaultModel;
+
+ public PainterThread (GdkGraphics2D g, Image im)
+ {
+ image = im;
+ this.gr = (GdkGraphics2D) g.create ();
+ new Thread (this).start ();
+ }
+
+ public void imageComplete (int status)
+ {
+ }
+
+ public void setColorModel (ColorModel model)
+ {
+ defaultModel = model;
+ }
+
+ public void setDimensions (int width, int height)
+ {
+ }
+
+ public void setHints (int hintflags)
+ {
+ }
+
+ public void setPixels (int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int off, int scansize)
+ {
+ }
+
+ public void setPixels (int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int off, int scansize)
+ {
+ gr.cairoSave ();
+ gr.cairoTranslate (x, y);
+
+ if (model == null)
+ model = defaultModel;
+
+ int pixels2[];
+ if (model != null)
+ {
+ pixels2 = new int[pixels.length];
+ for (int yy = 0; yy < h; yy++)
+ for (int xx = 0; xx < w; xx++)
+ {
+ int i = yy * scansize + xx;
+ pixels2[i] = model.getRGB (pixels[i]);
+ }
+ }
+ else
+ pixels2 = pixels;
+
+ gr.drawPixels (pixels2, w, h, scansize);
+ gr.cairoRestore ();
+ }
+
+ public void setProperties (java.util.Hashtable props)
+ {
+ }
+
+ public void run ()
+ {
+ image.getSource ().startProduction (this);
+ gr.dispose ();
+ }
+ }
+
+
+ private class BitwiseXorComposite implements Composite
+ {
+ // this is a special class which does a bitwise XOR composite, for
+ // backwards compatibility sake. it does *not* implement the
+ // porter-duff XOR operator. the porter-duff XOR is unrelated to
+ // bitwise XOR; it just happens to have a similar name but it
+ // represents a desire to composite the exclusive or of overlapping
+ // subpixel regions. bitwise XOR is for drawing "highlights" such as
+ // cursors (in a cheap oldskool bitblit fashion) by inverting colors
+ // temporarily and then inverting them back.
+
+ Color xorColor;
+
+ class BitwiseXorCompositeContext implements CompositeContext
+ {
+ ColorModel srcColorModel;
+ ColorModel dstColorModel;
+
+ public BitwiseXorCompositeContext (ColorModel s,
+ ColorModel d)
+ {
+ srcColorModel = s;
+ dstColorModel = d;
+ }
+
+ public void dispose ()
+ {
+ }
+
+ public void compose (Raster src,
+ Raster dstIn,
+ WritableRaster dstOut)
+ {
+ Rectangle srcRect = src.getBounds ();
+ Rectangle dstInRect = dstIn.getBounds ();
+ Rectangle dstOutRect = dstOut.getBounds ();
+
+ int xp = xorColor.getRGB ();
+ int x = 0, y = 0;
+ int w = Math.min (Math.min (srcRect.width, dstOutRect.width), dstInRect.width);
+ int h = Math.min (Math.min (srcRect.height, dstOutRect.height), dstInRect.height);
+ Object srcPix = null, dstPix = null;
+
+ for (y = 0; y < h; y++)
+ for (x = 0; x < w; x++)
+ {
+ srcPix = src.getDataElements (x + srcRect.x, y + srcRect.y, srcPix);
+ dstPix = dstIn.getDataElements (x + dstInRect.x, y + dstInRect.y, dstPix);
+ int sp = srcColorModel.getRGB (srcPix);
+ int dp = dstColorModel.getRGB (dstPix);
+ int rp = sp ^ xp ^ dp;
+ dstOut.setDataElements (x + dstOutRect.x, y + dstOutRect.y,
+ dstColorModel.getDataElements (rp, null));
+ }
+ }
+ }
+
+ public BitwiseXorComposite (Color c)
+ {
+ xorColor = c;
+ }
+
+ public CompositeContext createContext (ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints)
+ {
+ return new BitwiseXorCompositeContext (srcColorModel, dstColorModel);
+ }
+ }
+
+
+ ///////////////////////////////////////////////
+ ////// Unimplemented Stubs and Overloads //////
+ ///////////////////////////////////////////////
+
+ public boolean drawImage(Image image,
+ AffineTransform xform,
+ ImageObserver obs)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawImage(BufferedImage image,
+ BufferedImageOp op,
+ int x,
+ int y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawRenderedImage(RenderedImage image,
+ AffineTransform xform)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawRenderableImage(RenderableImage image,
+ AffineTransform xform)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawString(String text, float x, float y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawString(AttributedCharacterIterator iterator,
+ float x, float y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean hit(Rectangle rect, Shape text,
+ boolean onStroke)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void setComposite(Composite comp)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void setRenderingHint(RenderingHints.Key hintKey,
+ Object hintValue)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public Object getRenderingHint(RenderingHints.Key hintKey)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void setRenderingHints(Map hints)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void addRenderingHints(Map hints)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void shear(double shearX, double shearY)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public Composite getComposite()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public FontRenderContext getFontRenderContext ()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawGlyphVector (GlyphVector g, float x, float y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void copyArea (int x, int y, int width, int height, int dx, int dy)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawArc (int x, int y, int width, int height,
+ int startAngle, int arcAngle)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean drawImage (Image img, int x, int y, Color bgcolor,
+ ImageObserver observer)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean drawImage (Image img, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver observer)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean drawImage (Image img, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ ImageObserver observer)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawOval(int x, int y, int width, int height)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawString (String str, int x, int y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void drawString (AttributedCharacterIterator ci, int x, int y)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void fillArc (int x, int y, int width, int height,
+ int startAngle, int arcAngle)
+ {
+ cairoNewPath ();
+ walkPath (new Arc2D.Double((double)x, (double)y,
+ (double)width, (double)height,
+ (double)startAngle, (double)arcAngle,
+ Arc2D.PIE).getPathIterator (null));
+ cairoClosePath ();
+ cairoFill ();
+ }
+
+ public void fillOval(int x, int y, int width, int height)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void fillRoundRect (int x, int y, int width, int height,
+ int arcWidth, int arcHeight)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public Font getFont ()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public FontMetrics getFontMetrics ()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public FontMetrics getFontMetrics (Font f)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public void setFont (Font f)
+ {
+ if (f instanceof GdkFont)
+ font = (GdkFont) f;
+ else
+ font = new GdkFont (f.getAttributes ());
+ }
+
+ public String toString()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+}
diff --git a/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
new file mode 100644
index 0000000..55f3338
--- /dev/null
+++ b/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -0,0 +1,217 @@
+/* GdkPixbufDecoder.java -- Image data decoding object
+ Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 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 java.awt.image.*;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Vector;
+import java.util.Hashtable;
+import gnu.classpath.Configuration;
+
+public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
+{
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("gtkpeer");
+ }
+ initStaticState ();
+ }
+ native static void initStaticState ();
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ // the current set of ImageConsumers for this decoder
+ Vector curr;
+
+ // interface to GdkPixbuf
+ native void initState ();
+ native void pumpBytes (byte bytes[], int len);
+ native void finish ();
+
+ // gdk-pixbuf provids data in RGBA format
+ static final ColorModel cm = new DirectColorModel (32, 0xff000000,
+ 0x00ff0000,
+ 0x0000ff00,
+ 0x000000ff);
+ public GdkPixbufDecoder (String filename)
+ {
+ super (filename);
+ initState ();
+ }
+
+ public GdkPixbufDecoder (URL url)
+ {
+ super (url);
+ initState ();
+ }
+
+ // called back by native side
+ void areaPrepared (int width, int height)
+ {
+
+ if (curr == null)
+ return;
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.setDimensions (width, height);
+ ic.setColorModel (cm);
+ ic.setHints (ImageConsumer.RANDOMPIXELORDER);
+ }
+ }
+
+ // called back by native side
+ void areaUpdated (int x, int y, int width, int height,
+ int pixels[], int scansize)
+ {
+ if (curr == null)
+ return;
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.setPixels (x, y, width, height, cm, pixels, 0, scansize);
+ }
+ }
+
+ // called from an async image loader of one sort or another, this method
+ // repeatedly reads bytes from the input stream and passes them through a
+ // GdkPixbufLoader using the native method pumpBytes. pumpBytes in turn
+ // decodes the image data and calls back areaPrepared and areaUpdated on
+ // this object, feeding back decoded pixel blocks, which we pass to each
+ // of the ImageConsumers in the provided Vector.
+
+ void produce (Vector v, FileInputStream is) throws IOException
+ {
+ curr = v;
+
+ byte bytes[] = new byte[4096];
+ int len = 0;
+ while ((len = is.read (bytes)) != -1)
+ pumpBytes (bytes, len);
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
+ }
+
+ curr = null;
+ }
+
+ // remaining helper class and static method is a convenience for the Gtk
+ // peers, for loading a BufferedImage in off a disk file. one would think
+ // this ought to be fairly straightforward, but it does not appear
+ // anywhere else I can find.
+
+ private class BufferedImageBuilder implements ImageConsumer
+ {
+ BufferedImage bufferedImage;
+ ColorModel defaultModel;
+
+ public BufferedImage getBufferedImage()
+ {
+ return bufferedImage;
+ }
+
+ public void setDimensions(int width, int height)
+ {
+ bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public void setProperties(Hashtable props) {}
+
+ public void setColorModel(ColorModel model)
+ {
+ defaultModel = model;
+ }
+
+ public void setHints(int flags) {}
+
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ }
+
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ if (bufferedImage != null)
+ {
+
+ if (model == null)
+ model = defaultModel;
+
+ int pixels2[];
+ if (model != null)
+ {
+ pixels2 = new int[pixels.length];
+ for (int yy = 0; yy < h; yy++)
+ for (int xx = 0; xx < w; xx++)
+ {
+ int i = yy * scansize + xx;
+ pixels2[i] = model.getRGB (pixels[i]);
+ }
+ }
+ else
+ pixels2 = pixels;
+
+ bufferedImage.setRGB (x, y, w, h, pixels2, offset, scansize);
+ }
+ }
+
+ public void imageComplete(int status) {}
+ }
+
+ public static BufferedImage createBufferedImage (String filename)
+ {
+ BufferedImageBuilder bb = new BufferedImageBuilder ();
+ GdkPixbufDecoder dec = new GdkPixbufDecoder (filename);
+ dec.startProduction (bb);
+ return bb.getBufferedImage ();
+ }
+
+}
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
new file mode 100644
index 0000000..04eb2e5
--- /dev/null
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
@@ -0,0 +1,1069 @@
+/* gnu_java_awt_peer_gtk_GdkGraphics2d.c
+ Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 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. */
+
+#include "gtkpeer.h"
+#include "gnu_java_awt_peer_gtk_GdkGraphics2D.h"
+#include <gdk/gdktypes.h>
+#include <gdk/gdkprivate.h>
+#include <gdk/gdkx.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixdata.h>
+
+#include <cairo.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct state_table *native_graphics2d_state_table;
+
+#define NSA_G2D_INIT(env, clazz) \
+ native_graphics2d_state_table = init_state_table (env, clazz)
+
+#define NSA_GET_G2D_PTR(env, obj) \
+ get_state (env, obj, native_graphics2d_state_table)
+
+#define NSA_SET_G2D_PTR(env, obj, ptr) \
+ set_state (env, obj, native_graphics2d_state_table, (void *)ptr)
+
+#define NSA_DEL_G2D_PTR(env, obj) \
+ remove_state_slot (env, obj, native_graphics2d_state_table)
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState
+ (JNIEnv *env, jclass clazz)
+{
+ NSA_G2D_INIT (env, clazz);
+}
+
+/* these public final constants are part of the java2d public API, so we
+ write them explicitly here to save fetching them from the constant pool
+ all the time. */
+
+#ifndef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+enum java_awt_alpha_composite_rule
+ {
+ java_awt_alpha_composite_CLEAR = 1,
+ java_awt_alpha_composite_SRC = 2,
+ java_awt_alpha_composite_SRC_OVER = 3,
+ java_awt_alpha_composite_DST_OVER = 4,
+ java_awt_alpha_composite_SRC_IN = 5,
+ java_awt_alpha_composite_DST_IN = 6,
+ java_awt_alpha_composite_SRC_OUT = 7,
+ java_awt_alpha_composite_DST_OUT = 8,
+ java_awt_alpha_composite_DST = 9,
+ java_awt_alpha_composite_SRC_ATOP = 10,
+ java_awt_alpha_composite_DST_ATOP = 11,
+ java_awt_alpha_composite_XOR = 12
+ };
+
+enum java_awt_basic_stroke_join_rule
+ {
+ java_awt_basic_stroke_JOIN_MITER = 0,
+ java_awt_basic_stroke_JOIN_ROUND = 1,
+ java_awt_basic_stroke_JOIN_BEVEL = 2
+ };
+
+enum java_awt_basic_stroke_cap_rule
+ {
+ java_awt_basic_stroke_CAP_BUTT = 0,
+ java_awt_basic_stroke_CAP_ROUND = 1,
+ java_awt_basic_stroke_CAP_SQUARE = 2
+ };
+
+enum java_awt_geom_path_iterator_winding_rule
+ {
+ java_awt_geom_path_iterator_WIND_EVEN_ODD = 0,
+ java_awt_geom_path_iterator_WIND_NON_ZERO = 1
+ };
+
+
+static void
+grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win)
+{
+ g_assert (widget != NULL);
+ g_assert (draw != NULL);
+ g_assert (win != NULL);
+
+ if (GTK_IS_WINDOW (widget))
+ {
+ *win = find_gtk_layout (widget)->bin_window;
+ }
+ else if (GTK_IS_LAYOUT (widget))
+ {
+ *win = GTK_LAYOUT (widget)->bin_window;
+ }
+ else
+ {
+ *win = widget->window;
+ }
+
+ *draw = *win;
+ gdk_window_get_internal_paint_info (*win, draw, 0, 0);
+ g_object_ref (*draw);
+}
+
+
+static int
+x_server_has_render_extension (void)
+{
+ int ev = 0, err = 0;
+ return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err);
+}
+
+
+static void
+init_graphics2d_as_pixbuf (struct graphics2d *gr)
+{
+ gint width, height;
+ gint bits_per_sample = 8;
+ gint total_channels = 4;
+ gboolean has_alpha = TRUE;
+
+ g_assert (gr != NULL);
+ g_assert (gr->drawable != NULL);
+
+ if (gr->debug) printf ("initializing graphics2d as pixbuf\n");
+ gdk_drawable_get_size (gr->drawable, &width, &height);
+ gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ has_alpha, bits_per_sample,
+ width, height);
+ g_assert (gr->drawbuf != NULL);
+ g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample);
+ g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels);
+
+ gr->surface = cairo_surface_create_for_image (gdk_pixbuf_get_pixels (gr->drawbuf),
+ CAIRO_FORMAT_ARGB32,
+ gdk_pixbuf_get_width (gr->drawbuf),
+ gdk_pixbuf_get_height (gr->drawbuf),
+ gdk_pixbuf_get_rowstride (gr->drawbuf));
+ g_assert (gr->surface != NULL);
+ g_assert (gr->cr != NULL);
+ cairo_set_target_surface (gr->cr, gr->surface);
+}
+
+static void
+init_graphics2d_as_renderable (struct graphics2d *gr)
+{
+ Drawable draw;
+ Display * dpy;
+ Visual * vis;
+
+ g_assert (gr != NULL);
+ g_assert (gr->drawable != NULL);
+
+ gr->drawbuf = NULL;
+
+ if (gr->debug) printf ("initializing graphics2d as renderable\n");
+ draw = gdk_x11_drawable_get_xid (gr->drawable);
+
+ dpy = gdk_x11_drawable_get_xdisplay (gr->drawable);
+ g_assert (dpy != NULL);
+
+ vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable));
+ g_assert (vis != NULL);
+
+ gr->surface = cairo_surface_create_for_drawable (dpy, draw, vis,
+ CAIRO_FORMAT_ARGB32,
+ DefaultColormap (dpy, DefaultScreen (dpy)));
+ g_assert (gr->surface != NULL);
+ g_assert (gr->cr != NULL);
+ cairo_set_target_surface (gr->cr, gr->surface);
+}
+
+static void
+begin_drawing_operation (struct graphics2d * gr)
+{
+ gdk_threads_enter ();
+ if (gr->drawbuf)
+ {
+
+ gint drawable_width, drawable_height;
+ gint pixbuf_width, pixbuf_height;
+ gint width, height;
+
+ gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
+ pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
+ pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
+ width = min (drawable_width, pixbuf_width);
+ height = min (drawable_height, pixbuf_height);
+
+ gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */
+ gr->drawable,
+ NULL, /* colormap */
+ 0, 0, 0, 0,
+ width, height);
+
+ if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n",
+ width, height);
+ }
+}
+
+static void
+end_drawing_operation (struct graphics2d * gr)
+{
+ if (gr->drawbuf)
+ {
+ gint drawable_width, drawable_height;
+ gint pixbuf_width, pixbuf_height;
+ gint width, height;
+
+ gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
+ pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
+ pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
+ width = min (drawable_width, pixbuf_width);
+ height = min (drawable_height, pixbuf_height);
+
+ gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf,
+ 0, 0, 0, 0,
+ width, height,
+ GDK_RGB_DITHER_NORMAL, 0, 0);
+
+ if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n",
+ width, height);
+ }
+ gdk_threads_leave ();
+}
+
+
+static void
+update_pattern_transform (struct graphics2d *gr)
+{
+ double a, b, c, d, tx, ty;
+ cairo_matrix_t *mat = NULL;
+
+ g_assert (gr != NULL);
+ if (gr->pattern == NULL)
+ return;
+
+ return;
+ /* temporarily disabled: ambiguous behavior */
+ /* cairo_get_matrix (gr->cr, &a, &b, &c, &d, &tx, &ty); */
+ mat = cairo_matrix_create ();
+ g_assert (mat != NULL);
+ cairo_matrix_set_affine (mat, a, b, c, d, tx, ty);
+ cairo_surface_set_matrix (gr->pattern, mat);
+ cairo_matrix_destroy (mat);
+}
+
+static void
+check_for_debug (struct graphics2d *gr)
+{
+ gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState
+ (JNIEnv *env, jobject obj, jobject old)
+{
+ struct graphics2d *g = NULL, *g_old = NULL;
+
+ g = (struct graphics2d *) malloc (sizeof (struct graphics2d));
+ g_assert (g != NULL);
+ memset (g, 0, sizeof(struct graphics2d));
+
+ g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old);
+ g_assert (g_old != NULL);
+
+ g->drawable = g_old->drawable;
+ g->debug = g_old->debug;
+
+ gdk_threads_enter ();
+ g_object_ref (g->drawable);
+
+ g->cr = cairo_create();
+ g_assert (g->cr != NULL);
+
+ if (x_server_has_render_extension ())
+ init_graphics2d_as_renderable (g);
+ else
+ init_graphics2d_as_pixbuf (g);
+
+ cairo_surface_set_filter (g->surface, CAIRO_FILTER_BILINEAR);
+
+ gdk_threads_leave ();
+
+ NSA_SET_G2D_PTR (env, obj, g);
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II
+ (JNIEnv *env, jobject obj, jint width, jint height)
+{
+ struct graphics2d *gr;
+
+ gdk_threads_enter ();
+
+ gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
+ g_assert (gr != NULL);
+ memset (gr, 0, sizeof(struct graphics2d));
+
+ check_for_debug (gr);
+
+ if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n",
+ width, height);
+
+ gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height,
+ gdk_rgb_get_visual ()->depth);
+ g_assert (gr->drawable != NULL);
+
+ gr->cr = cairo_create();
+ g_assert (gr->cr != NULL);
+
+ if (x_server_has_render_extension ())
+ init_graphics2d_as_renderable (gr);
+ else
+ init_graphics2d_as_pixbuf (gr);
+
+ gdk_threads_leave ();
+ if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n",
+ width, height);
+ NSA_SET_G2D_PTR (env, obj, gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
+ (JNIEnv *env, jobject self, jobject other, jint x, jint y)
+{
+ struct graphics2d *src = NULL, *dst = NULL;
+ gint s_height, s_width, d_height, d_width, height, width;
+ GdkGC *gc;
+
+ src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other);
+ dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, self);
+ g_assert (src != NULL);
+ g_assert (dst != NULL);
+
+ if (src->debug) printf ("copying from offscreen drawable\n");
+
+ gdk_threads_enter ();
+ gdk_drawable_get_size (src->drawable, &s_width, &s_height);
+ gdk_drawable_get_size (dst->drawable, &d_width, &d_height);
+ width = min (s_width, d_width);
+ height = min (s_width, d_height);
+
+ gc = gdk_gc_new (dst->drawable);
+ g_assert (gc != NULL);
+
+ gdk_draw_drawable(dst->drawable, gc, src->drawable,
+ 0, 0, x, y, width, height);
+
+ g_object_unref (gc);
+
+ if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height);
+ gdk_threads_leave ();
+}
+
+static jintArray
+current_colors_of_widget (GtkWidget *widget, JNIEnv *env)
+{
+ GdkColor color;
+ jintArray array;
+ jint *rgb;
+
+ g_assert (widget != NULL);
+ g_assert (env != NULL);
+
+ color = widget->style->fg[GTK_STATE_NORMAL];
+ array = (*env)->NewIntArray (env, 6);
+
+ rgb = (*env)->GetIntArrayElements (env, array, NULL);
+ rgb[0] = color.red >> 8;
+ rgb[1] = color.green >> 8;
+ rgb[2] = color.blue >> 8;
+
+ color = widget->style->bg[GTK_STATE_NORMAL];
+ rgb[3] = color.red >> 8;
+ rgb[4] = color.green >> 8;
+ rgb[5] = color.blue >> 8;
+
+ (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
+
+ return array;
+}
+
+JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
+ (JNIEnv *env, jobject obj, jobject peer)
+{
+ struct graphics2d *gr = NULL;
+ GtkWidget *widget = NULL;
+ void *ptr = NULL;
+ jintArray color;
+
+ ptr = NSA_GET_PTR (env, peer);
+ g_assert (ptr != NULL);
+ gdk_threads_enter ();
+
+ gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
+ g_assert (gr != NULL);
+ memset (gr, 0, sizeof(struct graphics2d));
+
+ check_for_debug (gr);
+
+ gr->cr = cairo_create();
+ g_assert (gr->cr != NULL);
+
+ widget = GTK_WIDGET (ptr);
+ g_assert (widget != NULL);
+
+ grab_current_drawable (widget, &(gr->drawable), &(gr->win));
+ g_assert (gr->drawable != NULL);
+
+ if (x_server_has_render_extension ())
+ init_graphics2d_as_renderable (gr);
+ else
+ init_graphics2d_as_pixbuf (gr);
+
+ color = current_colors_of_widget (widget, env);
+
+ gdk_threads_leave ();
+ NSA_SET_G2D_PTR (env, obj, gr);
+ return color;
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+
+ gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj);
+ if (gr == NULL)
+ return; /* dispose has been called more than once */
+
+ gdk_threads_enter ();
+
+ if (gr->surface)
+ cairo_surface_destroy (gr->surface);
+
+ cairo_destroy (gr->cr);
+
+ if (gr->drawbuf)
+ g_object_unref (gr->drawbuf);
+
+ g_object_unref (gr->drawable);
+ free (gr);
+
+ if (gr->pattern)
+ cairo_surface_destroy (gr->pattern);
+
+ if (gr->pattern_pixels)
+ free (gr->pattern_pixels);
+
+ if (gr->debug) printf ("disposed of graphics2d\n");
+
+ gdk_threads_leave ();
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient
+ (JNIEnv *env, jobject obj,
+ jdouble x1, jdouble y1,
+ jdouble x2, jdouble y2,
+ jint r1, jint g1, jint b1, jint a1,
+ jint r2, jint g2, jint b2, jint a2,
+ jboolean cyclic)
+{
+ struct graphics2d *gr = NULL;
+ cairo_surface_t *surf = NULL;
+ cairo_matrix_t *mat = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+
+ if (gr->debug) printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",
+ x1, y1,
+ x2, y2,
+ r1, g1, b1, a1,
+ r2, g2, b2, a2);
+
+ cairo_save (gr->cr);
+
+ if (cyclic)
+ surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2);
+ else
+ surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2);
+ g_assert (surf != NULL);
+
+ cairo_set_target_surface (gr->cr, surf);
+
+ cairo_identity_matrix (gr->cr);
+
+ cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
+ cairo_set_alpha (gr->cr, a1 / 255.0);
+ cairo_rectangle (gr->cr, 0, 0, 1, 2);
+ cairo_fill (gr->cr);
+
+ cairo_set_rgb_color (gr->cr, r2 / 255.0, g2 / 255.0, b2 / 255.0);
+ cairo_set_alpha (gr->cr, a2 / 255.0);
+ cairo_rectangle (gr->cr, 1, 0, 1, 2);
+ cairo_fill (gr->cr);
+
+ if (cyclic)
+ {
+ cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
+ cairo_set_alpha (gr->cr, a1 / 255.0);
+ cairo_rectangle (gr->cr, 2, 0, 1, 2);
+ cairo_fill (gr->cr);
+ }
+
+ mat = cairo_matrix_create ();
+ g_assert (mat != NULL);
+
+ /*
+ consider the vector [x2 - x1, y2 - y1] = [p,q]
+
+ this is a line in space starting at an 'origin' x1, y1.
+
+ it can also be thought of as a "transformed" unit vector in either the
+ x or y directions. we have just *drawn* our gradient as a unit vector
+ (well, a 2-3x unit vector) in the x dimension. so what we want to know
+ is which transformation turns our existing unit vector into [p,q].
+
+ which means solving for M in
+
+ [p,q] = M[1,0]
+
+ [p,q] = |a b| [1,0]
+ |c d|
+
+ [p,q] = [a,c], with b = d = 0.
+
+ what does this mean? it means that our gradient is 1-dimensional; as
+ you move through the x axis of our 2 or 3 pixel gradient from logical
+ x positions 0 to 1, the transformation of your x coordinate under the
+ matrix M causes you to accumulate both x and y values in fill
+ space. the y value of a gradient coordinate is ignored, since the
+ gradient is one dimensional. which is correct.
+
+ unfortunately we want the opposite transformation, it seems, because of
+ the way cairo is going to use this transformation. I'm a bit confused by
+ that, but it seems to work right, so we take reciprocals of values and
+ negate offsets. oh well.
+
+ */
+
+ double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1));
+ double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1));
+ double dx = (x1 == 0.) ? 0. : 1. / x1;
+ double dy = (y1 == 0.) ? 0. : 1. / y1;
+
+ cairo_matrix_set_affine (mat,
+ a, 0.,
+ c, 0.,
+ dx, dy);
+
+ cairo_surface_set_matrix (surf, mat);
+ cairo_matrix_destroy (mat);
+ cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
+
+ /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */
+ /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */
+
+ if (gr->pattern)
+ cairo_surface_destroy (gr->pattern);
+
+ if (gr->pattern_pixels)
+ {
+ free (gr->pattern_pixels);
+ gr->pattern_pixels = NULL;
+ }
+
+ gr->pattern = surf;
+
+ cairo_restore (gr->cr);
+ cairo_set_pattern (gr->cr, gr->pattern);
+
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels
+ (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride)
+{
+ struct graphics2d *gr = NULL;
+ jint *jpixels = NULL;
+
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+
+ if (gr->debug) printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n",
+ (*env)->GetArrayLength (env, jarr), w, h, stride);
+
+ if (gr->pattern)
+ cairo_surface_destroy (gr->pattern);
+
+ if (gr->pattern_pixels)
+ free (gr->pattern_pixels);
+
+ gr->pattern = NULL;
+ gr->pattern_pixels = NULL;
+
+ gr->pattern_pixels = (char *) malloc (h * stride * 4);
+ g_assert (gr->pattern_pixels != NULL);
+
+ jpixels = (*env)->GetIntArrayElements (env, jarr, NULL);
+ g_assert (jpixels != NULL);
+ memcpy (gr->pattern_pixels, jpixels, h * stride * 4);
+ (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
+
+ gr->pattern = cairo_surface_create_for_image (gr->pattern_pixels,
+ CAIRO_FORMAT_ARGB32,
+ w, h, stride * 4);
+ g_assert (gr->pattern != NULL);
+ cairo_surface_set_repeat (gr->pattern, 1);
+ cairo_set_pattern (gr->cr, gr->pattern);
+
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels
+ (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride)
+{
+ struct graphics2d *gr = NULL;
+ jint *jpixels = NULL;
+
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+
+ if (gr->debug) printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n",
+ (*env)->GetArrayLength (env, jarr), w, h, stride);
+
+ jpixels = (*env)->GetIntArrayElements (env, jarr, NULL);
+ g_assert (jpixels != NULL);
+
+ begin_drawing_operation (gr);
+
+ {
+ cairo_surface_t *surf = cairo_surface_create_for_image ((char *)jpixels,
+ CAIRO_FORMAT_ARGB32,
+ w, h, stride * 4);
+ cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
+ cairo_show_surface (gr->cr, surf, w, h);
+ cairo_surface_destroy (surf);
+ }
+
+ end_drawing_operation (gr);
+
+ (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
+
+}
+
+/* passthrough methods to cairo */
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_save\n");
+ cairo_save (gr->cr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_restore\n");
+ cairo_restore (gr->cr);
+ update_pattern_transform (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix
+ (JNIEnv *env, jobject obj,
+ jdouble m00, jdouble m10,
+ jdouble m01, jdouble m11,
+ jdouble m02, jdouble m12)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_matrix\n");
+
+ {
+ cairo_matrix_t * mat = cairo_matrix_create ();
+ cairo_matrix_set_affine (mat,
+ m00, m10,
+ m01, m11,
+ m02, m12);
+ cairo_set_matrix (gr->cr, mat);
+ cairo_matrix_destroy (mat);
+ }
+ update_pattern_transform (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator
+ (JNIEnv *env, jobject obj, jint op)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_operator %d\n", op);
+ switch ((enum java_awt_alpha_composite_rule) op)
+ {
+ case java_awt_alpha_composite_CLEAR:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR);
+ break;
+
+ case java_awt_alpha_composite_SRC:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_SRC);
+ break;
+
+ case java_awt_alpha_composite_SRC_OVER:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER);
+ break;
+
+ case java_awt_alpha_composite_DST_OVER:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER_REVERSE);
+ break;
+
+ case java_awt_alpha_composite_SRC_IN:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN);
+ break;
+
+ case java_awt_alpha_composite_DST_IN:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN_REVERSE);
+ break;
+
+ case java_awt_alpha_composite_SRC_OUT:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT);
+ break;
+
+ case java_awt_alpha_composite_DST_OUT:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT_REVERSE);
+ break;
+
+ case java_awt_alpha_composite_DST:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_DST);
+ break;
+
+ case java_awt_alpha_composite_SRC_ATOP:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP);
+ break;
+
+ case java_awt_alpha_composite_DST_ATOP:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP_REVERSE);
+ break;
+
+ case java_awt_alpha_composite_XOR:
+ cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR);
+ break;
+ }
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBColor
+ (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+
+ /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider
+ colors in opposite pixel order. I have no idea why. thus when you
+ draw to a PixBuf, you must exchange the R and B components of your
+ color. */
+
+ if (gr->debug) printf ("cairo_set_rgb_color (%f, %f, %f)\n", r, g, b);
+
+ if (gr->drawbuf)
+ cairo_set_rgb_color (gr->cr, b, g, r);
+ else
+ cairo_set_rgb_color (gr->cr, r, g, b);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetAlpha
+ (JNIEnv *env, jobject obj, jdouble a)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_alpha %f\n", a);
+ cairo_set_alpha (gr->cr, a);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule
+ (JNIEnv *env, jobject obj, jint rule)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule);
+ g_assert (gr != NULL);
+ switch ((enum java_awt_geom_path_iterator_winding_rule) rule)
+ {
+ case java_awt_geom_path_iterator_WIND_NON_ZERO:
+ cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING);
+ break;
+ case java_awt_geom_path_iterator_WIND_EVEN_ODD:
+ cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD);
+ break;
+ }
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth
+ (JNIEnv *env, jobject obj, jdouble width)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_line_width %f\n", width);
+ cairo_set_line_width (gr->cr, width);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap
+ (JNIEnv *env, jobject obj, jint cap)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_line_cap %d\n", cap);
+ switch ((enum java_awt_basic_stroke_cap_rule) cap)
+ {
+ case java_awt_basic_stroke_CAP_BUTT:
+ cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT);
+ break;
+
+ case java_awt_basic_stroke_CAP_ROUND:
+ cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND);
+ break;
+
+ case java_awt_basic_stroke_CAP_SQUARE:
+ cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE);
+ break;
+ }
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin
+ (JNIEnv *env, jobject obj, jint join)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_line_join %d\n", join);
+ switch ((enum java_awt_basic_stroke_join_rule) join)
+ {
+ case java_awt_basic_stroke_JOIN_MITER:
+ cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER);
+ break;
+
+ case java_awt_basic_stroke_JOIN_ROUND:
+ cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND);
+ break;
+
+ case java_awt_basic_stroke_JOIN_BEVEL:
+ cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL);
+ break;
+ }
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash
+ (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset)
+{
+ struct graphics2d *gr = NULL;
+ jdouble *dasharr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_dash\n");
+ dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL);
+ g_assert (dasharr != NULL);
+ cairo_set_dash (gr->cr, dasharr, ndash, offset);
+ (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit
+ (JNIEnv *env, jobject obj, jdouble miter)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter);
+ cairo_set_miter_limit (gr->cr, miter);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoTranslate
+ (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_translate (%f, %f)\n", dx, dy);
+ cairo_translate (gr->cr, dx, dy);
+ update_pattern_transform (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoScale
+ (JNIEnv *env, jobject obj, jdouble sx, jdouble sy)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_scale (%f, %f)\n", sx, sy);
+ cairo_scale (gr->cr, sx, sy);
+ update_pattern_transform (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRotate
+ (JNIEnv *env, jobject obj, jdouble angle)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_rotate %f\n", angle);
+ cairo_rotate (gr->cr, angle);
+ update_pattern_transform (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_new_path\n");
+ cairo_new_path (gr->cr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo
+ (JNIEnv *env, jobject obj, jdouble x, jdouble y)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y);
+ cairo_move_to (gr->cr, x, y);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo
+ (JNIEnv *env, jobject obj, jdouble x, jdouble y)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y);
+ cairo_line_to (gr->cr, x, y);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo
+ (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", x1, y1, x2, y2, x3, y3);
+ cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo
+ (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy);
+ cairo_rel_move_to (gr->cr, dx, dy);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo
+ (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy);
+ cairo_rel_line_to (gr->cr, dx, dy);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo
+ (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", dx1, dy1, dx2, dy2, dx3, dy3);
+ cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle
+ (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height);
+ cairo_rectangle (gr->cr, x, y, width, height);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_close_path\n");
+ cairo_close_path (gr->cr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_stroke\n");
+ begin_drawing_operation (gr);
+ cairo_stroke (gr->cr);
+ end_drawing_operation (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_fill\n");
+ begin_drawing_operation (gr);
+ cairo_fill (gr->cr);
+ end_drawing_operation (gr);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip
+ (JNIEnv *env, jobject obj)
+{
+ struct graphics2d *gr = NULL;
+ gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+ g_assert (gr != NULL);
+ if (gr->debug) printf ("cairo_clip\n");
+ cairo_clip (gr->cr);
+}
+
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
new file mode 100644
index 0000000..0d75572
--- /dev/null
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
@@ -0,0 +1,236 @@
+/* gdkpixbufdecoder.c
+ Copyright (C) 1999, 2003 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., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 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. */
+
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixbuf-loader.h>
+
+#include "gtkpeer.h"
+#include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
+
+struct state_table *native_pixbufdecoder_state_table;
+
+#define NSA_PB_INIT(env, clazz) \
+ native_pixbufdecoder_state_table = init_state_table (env, clazz)
+
+#define NSA_GET_PB_PTR(env, obj) \
+ get_state (env, obj, native_pixbufdecoder_state_table)
+
+#define NSA_SET_PB_PTR(env, obj, ptr) \
+ set_state (env, obj, native_pixbufdecoder_state_table, (void *)ptr)
+
+#define NSA_DEL_PB_PTR(env, obj) \
+ remove_state_slot (env, obj, native_pixbufdecoder_state_table)
+
+
+jmethodID areaPreparedID;
+jmethodID areaUpdatedID;
+
+static void
+area_prepared (GdkPixbufLoader *loader,
+ jobject *decoder)
+{
+ jint width, height;
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf == NULL)
+ return;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf),
+
+ gdk_threads_leave ();
+
+ g_assert (decoder != NULL);
+
+ (*gdk_env)->CallVoidMethod (gdk_env,
+ *decoder,
+ areaPreparedID,
+ width, height);
+
+ gdk_threads_enter ();
+}
+
+static void
+area_updated (GdkPixbufLoader *loader,
+ gint x, gint y,
+ gint width, gint height,
+ jobject *decoder)
+{
+ jint stride_bytes, stride_pixels, n_channels, n_pixels;
+ int i, px;
+ jintArray jpixels;
+ jint *java_pixels;
+ guchar *gdk_pixels;
+
+ GdkPixbuf *pixbuf_no_alpha = NULL;
+ GdkPixbuf *pixbuf = NULL;
+
+ pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf_no_alpha == NULL)
+ return;
+
+ pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0);
+ g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
+
+ stride_bytes = gdk_pixbuf_get_rowstride (pixbuf);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ stride_pixels = stride_bytes / n_channels;
+ n_pixels = height * stride_pixels;
+ gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ jpixels = (*gdk_env)->NewIntArray (gdk_env, n_pixels);
+ java_pixels = (*gdk_env)->GetIntArrayElements (gdk_env, jpixels, NULL);
+
+ memcpy (java_pixels,
+ gdk_pixels + (y * stride_bytes),
+ (height * stride_bytes));
+
+ for (i = 0; i < n_pixels; ++i)
+ {
+ px = java_pixels[i];
+
+ /* move alpha around (GdkPixbufLoader results are AGBR not GBRA, in
+ the lsb sense) */
+ /* px = ((px >> 24) & 0xff) | ((px << 8) & 0xffffff00); */
+
+ /* it appears to require a full byte swap, now, not just a shift to
+ the A channel. why did this change? don't know. */
+ px = ((px >> 8) & 0x00ff00ff) | ((px << 8) & 0xff00ff00);
+ px = ((px >> 16) & 0x0000ffff) | ((px << 16) & 0xffff0000);
+
+ java_pixels[i] = px;
+ }
+
+ g_object_unref (pixbuf);
+
+ gdk_threads_leave ();
+
+ (*gdk_env)->ReleaseIntArrayElements (gdk_env, jpixels, java_pixels, 0);
+ (*gdk_env)->CallVoidMethod (gdk_env,
+ *decoder,
+ areaUpdatedID,
+ (jint) x, (jint) y,
+ (jint) width, (jint) height,
+ jpixels,
+ stride_pixels);
+ gdk_threads_enter ();
+}
+
+static void
+closed (GdkPixbufLoader *loader, jobject *decoder)
+{
+ gdk_threads_leave ();
+ (*gdk_env)->DeleteGlobalRef (gdk_env, *decoder);
+ free (decoder);
+ gdk_threads_enter ();
+}
+
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
+ (JNIEnv *env, jobject obj)
+{
+ GdkPixbufLoader *loader = NULL;
+ jobject *decoder = NULL;
+
+ decoder = (jobject *) malloc (sizeof (jobject));
+ g_assert (decoder != NULL);
+ *decoder = (*env)->NewGlobalRef (env, obj);
+
+ gdk_threads_enter ();
+ loader = gdk_pixbuf_loader_new ();
+ g_assert (loader != NULL);
+ g_signal_connect (loader, "area-prepared", G_CALLBACK (area_prepared), decoder);
+ g_signal_connect (loader, "area-updated", G_CALLBACK (area_updated), decoder);
+ g_signal_connect (loader, "closed", G_CALLBACK (closed), decoder);
+ gdk_threads_leave ();
+
+ NSA_SET_PB_PTR (env, obj, loader);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
+ (JNIEnv *env, jclass clazz)
+{
+ areaPreparedID = (*env)->GetMethodID (env, clazz,
+ "areaPrepared",
+ "(II)V");
+
+ areaUpdatedID = (*env)->GetMethodID (env, clazz,
+ "areaUpdated",
+ "(IIII[II)V");
+ NSA_PB_INIT (env, clazz);
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
+ (JNIEnv *env, jobject obj)
+{
+ GdkPixbufLoader *loader = NULL;
+
+ loader = (GdkPixbufLoader *)NSA_DEL_PB_PTR (env, obj);
+ if (loader == NULL)
+ return;
+
+ gdk_threads_enter ();
+ gdk_pixbuf_loader_close (loader, NULL);
+ g_object_unref (loader);
+ gdk_threads_leave ();
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
+ (JNIEnv *env, jobject obj, jbyteArray jarr, jint len)
+{
+ GdkPixbufLoader *loader = NULL;
+ jbyte *bytes = NULL;
+
+ if (len < 1)
+ return;
+
+ bytes = (*gdk_env)->GetByteArrayElements (gdk_env, jarr, NULL);
+ g_assert (bytes != NULL);
+ loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
+ g_assert (loader != NULL);
+
+ gdk_threads_enter ();
+ gdk_pixbuf_loader_write (loader, bytes, len, NULL);
+ gdk_threads_leave ();
+
+ (*gdk_env)->ReleaseByteArrayElements (gdk_env, jarr, bytes, 0);
+}