OSDN Git Service

2004-08-31 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GdkGraphics2D.c
1 /* gnu_java_awt_peer_gtk_GdkGraphics2d.c
2    Copyright (C) 2003 Free Software Foundation, Inc.
3
4    This file is part of GNU Classpath.
5    
6    GNU Classpath is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10    
11    GNU Classpath is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with GNU Classpath; see the file COPYING.  If not, write to the
18    Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.
20    
21    Linking this library statically or dynamically with other modules is
22    making a combined work based on this library.  Thus, the terms and
23    conditions of the GNU General Public License cover the whole
24    combination.
25    
26    As a special exception, the copyright holders of this library give you
27    permission to link this library with independent modules to produce an
28    executable, regardless of the license terms of these independent
29    modules, and to copy and distribute the resulting executable under
30    terms of your choice, provided that you also meet, for each linked
31    independent module, the terms and conditions of the license of that
32    module.  An independent module is a module which is not derived from
33    or based on this library.  If you modify this library, you may extend
34    this exception to your version of the library, but you are not
35    obligated to do so.  If you do not wish to do so, delete this
36    exception statement from your version. */
37
38 #include "gtkcairopeer.h"
39 #include "gdkfont.h"
40 #include "gnu_java_awt_peer_gtk_GdkGraphics2D.h"
41 #include <gdk/gdktypes.h>
42 #include <gdk/gdkprivate.h>
43 #include <gdk/gdkx.h>
44
45 #include <gdk-pixbuf/gdk-pixbuf.h>
46 #include <gdk-pixbuf/gdk-pixdata.h>
47
48 #include <cairo.h>
49
50 #include <stdio.h>
51 #include <stdlib.h>
52
53 struct state_table *native_graphics2d_state_table;
54
55 #define NSA_G2D_INIT(env, clazz) \
56   native_graphics2d_state_table = init_state_table (env, clazz)
57
58 #define NSA_GET_G2D_PTR(env, obj) \
59   get_state (env, obj, native_graphics2d_state_table)
60
61 #define NSA_SET_G2D_PTR(env, obj, ptr) \
62   set_state (env, obj, native_graphics2d_state_table, (void *)ptr)
63
64 #define NSA_DEL_G2D_PTR(env, obj) \
65   remove_state_slot (env, obj, native_graphics2d_state_table)
66
67 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState 
68   (JNIEnv *env, jclass clazz)
69 {
70    gdk_threads_enter();
71    NSA_G2D_INIT (env, clazz);
72    gdk_threads_leave();
73 }
74
75 /* these public final constants are part of the java2d public API, so we
76    write them explicitly here to save fetching them from the constant pool
77    all the time. */
78
79 #ifndef min
80 #define min(x,y) ((x) < (y) ? (x) : (y))
81 #endif
82
83 enum java_awt_alpha_composite_rule
84   {
85     java_awt_alpha_composite_CLEAR = 1,
86     java_awt_alpha_composite_SRC = 2,
87     java_awt_alpha_composite_SRC_OVER = 3,
88     java_awt_alpha_composite_DST_OVER = 4,
89     java_awt_alpha_composite_SRC_IN = 5,
90     java_awt_alpha_composite_DST_IN = 6,
91     java_awt_alpha_composite_SRC_OUT = 7,
92     java_awt_alpha_composite_DST_OUT = 8,
93     java_awt_alpha_composite_DST = 9,
94     java_awt_alpha_composite_SRC_ATOP = 10,
95     java_awt_alpha_composite_DST_ATOP = 11,
96     java_awt_alpha_composite_XOR = 12
97   };
98
99 enum java_awt_basic_stroke_join_rule
100   {
101     java_awt_basic_stroke_JOIN_MITER = 0,
102     java_awt_basic_stroke_JOIN_ROUND = 1,
103     java_awt_basic_stroke_JOIN_BEVEL = 2
104   };
105
106 enum java_awt_basic_stroke_cap_rule
107   {
108     java_awt_basic_stroke_CAP_BUTT = 0,
109     java_awt_basic_stroke_CAP_ROUND = 1,
110     java_awt_basic_stroke_CAP_SQUARE = 2
111   };
112
113 enum java_awt_geom_path_iterator_winding_rule
114   {
115     java_awt_geom_path_iterator_WIND_EVEN_ODD = 0,
116     java_awt_geom_path_iterator_WIND_NON_ZERO = 1
117   };
118
119 enum java_awt_rendering_hints_filter
120   {
121     java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0,    
122     java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1,
123     java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2,
124     java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3,
125     java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4
126  
127   };
128
129 static int
130 peer_is_disposed(JNIEnv *env, jobject obj)
131 {
132   static jfieldID fid = NULL;
133   jclass cls;
134   jobject peer;
135
136   return 0;
137
138   if (fid == NULL)
139     {
140       cls = (*env)->GetObjectClass(env, obj);
141       fid = (*env)->GetFieldID(env, cls, "component",
142                                "Lgnu/java/awt/peer/gtk/GtkComponentPeer;");
143     }
144   g_assert(fid != NULL);
145   peer = (*env)->GetObjectField(env, obj, fid);
146   if (peer == NULL || NSA_GET_PTR (env, peer) != NULL)
147     return 0;
148   else
149     {
150       return 1;
151     }
152 }
153
154
155 static void 
156 grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win)
157 {  
158   g_assert (widget != NULL);
159   g_assert (draw != NULL);
160   g_assert (win != NULL);
161
162   if (GTK_IS_WINDOW (widget))
163     {
164       *win = find_gtk_layout (widget)->bin_window;
165     }
166   else if (GTK_IS_LAYOUT (widget))
167     {
168       *win = GTK_LAYOUT (widget)->bin_window;
169     }
170   else
171     {
172       *win = widget->window;
173     }
174
175   *draw = *win;
176   gdk_window_get_internal_paint_info (*win, draw, 0, 0); 
177   g_object_ref (*draw);
178 }
179
180
181 static int
182 x_server_has_render_extension (void)
183 {
184   int ev = 0, err = 0; 
185   return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err);
186 }
187
188
189 static void
190 init_graphics2d_as_pixbuf (struct graphics2d *gr)
191 {
192   gint width, height;
193   gint bits_per_sample = 8;
194   gint total_channels = 4;
195   gboolean has_alpha = TRUE;
196   
197   g_assert (gr != NULL);
198   g_assert (gr->drawable != NULL);
199
200   if (gr->debug) printf ("initializing graphics2d as pixbuf\n");
201   gdk_drawable_get_size (gr->drawable, &width, &height);
202   gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 
203                                 has_alpha, bits_per_sample,
204                                 width, height);
205   g_assert (gr->drawbuf != NULL);
206   g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample);
207   g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels);
208   
209   gr->surface = cairo_surface_create_for_image (gdk_pixbuf_get_pixels (gr->drawbuf), 
210                                                 CAIRO_FORMAT_ARGB32, 
211                                                 gdk_pixbuf_get_width (gr->drawbuf), 
212                                                 gdk_pixbuf_get_height (gr->drawbuf), 
213                                                 gdk_pixbuf_get_rowstride (gr->drawbuf));      
214   g_assert (gr->surface != NULL);
215   g_assert (gr->cr != NULL);
216   cairo_set_target_surface (gr->cr, gr->surface);
217 }
218
219 static void
220 init_graphics2d_as_renderable (struct graphics2d *gr)
221 {
222   Drawable draw;
223   Display * dpy;
224   Visual * vis;
225   
226   g_assert (gr != NULL);
227   g_assert (gr->drawable != NULL);
228
229   gr->drawbuf = NULL;
230   
231   if (gr->debug) printf ("initializing graphics2d as renderable\n");
232   draw = gdk_x11_drawable_get_xid (gr->drawable);
233   
234   dpy = gdk_x11_drawable_get_xdisplay (gr->drawable);
235   g_assert (dpy != NULL);
236   
237   vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable));
238   g_assert (vis != NULL);
239   
240   gr->surface = cairo_xlib_surface_create (dpy, draw, vis, 
241                                            CAIRO_FORMAT_ARGB32,
242                                            DefaultColormap (dpy, DefaultScreen (dpy)));
243   g_assert (gr->surface != NULL);
244   g_assert (gr->cr != NULL);
245   cairo_set_target_surface (gr->cr, gr->surface);
246 }
247
248 static void
249 begin_drawing_operation (struct graphics2d * gr)
250 {  
251   g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS);
252   if (gr->drawbuf)
253     {
254
255       gint drawable_width, drawable_height;
256       gint pixbuf_width, pixbuf_height;
257       gint width, height;
258       
259       gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
260       pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
261       pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
262       width = min (drawable_width, pixbuf_width);
263       height = min (drawable_height, pixbuf_height);
264
265       gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */
266                                     gr->drawable, 
267                                     NULL, /* colormap */
268                                     0, 0, 0, 0,
269                                     width, height); 
270       
271       if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n",
272                              width, height);      
273     }
274 }
275
276 static void
277 end_drawing_operation (struct graphics2d * gr)
278 {
279   g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS);
280   if (gr->drawbuf)
281     { 
282       gint drawable_width, drawable_height;
283       gint pixbuf_width, pixbuf_height;
284       gint width, height;
285       
286       gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
287       pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
288       pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
289       width = min (drawable_width, pixbuf_width);
290       height = min (drawable_height, pixbuf_height);
291
292       gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf,
293                        0, 0, 0, 0, 
294                        width, height, 
295                        GDK_RGB_DITHER_NORMAL, 0, 0);
296
297       if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n",
298                              width, height);
299     }
300 }
301
302
303 static void 
304 update_pattern_transform (struct graphics2d *gr)
305 {
306   double a, b, c, d, tx, ty;
307   cairo_matrix_t *mat = NULL;
308
309   g_assert (gr != NULL);
310   if (gr->pattern == NULL)
311     return;
312
313   return;
314   /* temporarily disabled: ambiguous behavior */
315   /*   cairo_get_matrix (gr->cr, &a, &b, &c, &d, &tx, &ty); */
316   mat = cairo_matrix_create ();
317   g_assert (mat != NULL);
318   cairo_matrix_set_affine (mat, a, b, c, d, tx, ty);
319   cairo_pattern_set_matrix (gr->pattern, mat);
320   cairo_matrix_destroy (mat);
321 }
322
323 static void
324 check_for_debug (struct graphics2d *gr)
325 {
326   gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL);
327 }
328
329 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState
330   (JNIEnv *env, jobject obj, jobject old)
331 {
332   struct graphics2d *g = NULL, *g_old = NULL;
333
334   gdk_threads_enter();
335   g = (struct graphics2d *) malloc (sizeof (struct graphics2d));
336   g_assert (g != NULL);
337   memset (g, 0, sizeof(struct graphics2d));
338
339   g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old);
340   g_assert (g_old != NULL);
341
342   if (g_old->debug) printf ("copying state from existing graphics2d\n");
343
344   g->drawable = g_old->drawable;
345   g->debug = g_old->debug; 
346
347   g_object_ref (g->drawable);
348   
349   g->cr = cairo_create();
350   g_assert (g->cr != NULL);
351
352   if (x_server_has_render_extension ())
353     init_graphics2d_as_renderable (g);
354   else
355     init_graphics2d_as_pixbuf (g);
356
357   cairo_surface_set_filter (g->surface, CAIRO_FILTER_FAST);
358
359   NSA_SET_G2D_PTR (env, obj, g);
360   gdk_threads_leave();
361 }
362
363
364 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II
365   (JNIEnv *env, jobject obj, jint width, jint height)
366 {
367   struct graphics2d *gr;
368   
369   gdk_threads_enter();
370   gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
371   g_assert (gr != NULL);
372   memset (gr, 0, sizeof(struct graphics2d));
373
374   check_for_debug (gr);  
375
376   if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n",
377                          width, height);
378
379   gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height, 
380                                                  gdk_rgb_get_visual ()->depth);
381   g_assert (gr->drawable != NULL);
382
383   gr->cr = cairo_create();
384   g_assert (gr->cr != NULL);
385
386   if (x_server_has_render_extension ())
387     init_graphics2d_as_renderable (gr);
388   else
389     init_graphics2d_as_pixbuf (gr);
390
391   if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n",
392                          width, height);
393   NSA_SET_G2D_PTR (env, obj, gr);
394   gdk_threads_leave();
395 }
396
397 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
398   (JNIEnv *env, jobject self, jobject other, jint x, jint y)
399 {
400   struct graphics2d *src = NULL, *dst = NULL;
401   gint s_height, s_width, d_height, d_width, height, width;
402   cairo_matrix_t *matrix;
403   cairo_operator_t tmp_op;
404
405   gdk_threads_enter();
406   if (peer_is_disposed(env, self)) { gdk_threads_leave(); return; }
407   src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other);
408   dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, self);
409   g_assert (src != NULL);
410   g_assert (dst != NULL);  
411
412   if (src->debug) printf ("copying from offscreen drawable\n");
413
414   begin_drawing_operation(dst); 
415
416   gdk_flush();
417
418   gdk_drawable_get_size (src->drawable, &s_width, &s_height);
419   gdk_drawable_get_size (dst->drawable, &d_width, &d_height);
420   width = min (s_width, d_width);
421   height = min (s_height, d_height);
422
423   matrix = cairo_matrix_create ();
424   cairo_surface_get_matrix (src->surface, matrix);
425   cairo_matrix_translate (matrix, (double)-x, (double)-y);
426   cairo_surface_set_matrix (src->surface, matrix);
427
428   tmp_op = cairo_current_operator (dst->cr); 
429   cairo_set_operator(dst->cr, CAIRO_OPERATOR_SRC); 
430   cairo_show_surface (dst->cr, src->surface, width, height);
431   cairo_set_operator(dst->cr, tmp_op);
432
433   cairo_matrix_translate (matrix, (double)x, (double)y);
434   cairo_surface_set_matrix (src->surface, matrix);
435   cairo_matrix_destroy (matrix);
436
437   gdk_flush();
438
439   end_drawing_operation(dst);
440
441   if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height);
442   gdk_threads_leave();
443 }
444
445 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
446   (JNIEnv *env, jobject obj, jobject peer)
447 {
448   struct graphics2d *gr = NULL;
449   GtkWidget *widget = NULL;
450   void *ptr = NULL;
451
452   gdk_threads_enter();
453   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
454   ptr = NSA_GET_PTR (env, peer);
455   g_assert (ptr != NULL);
456
457   gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
458   g_assert (gr != NULL);
459   memset (gr, 0, sizeof(struct graphics2d));
460
461   check_for_debug (gr);
462
463   gr->cr = cairo_create();
464   g_assert (gr->cr != NULL);
465
466   widget = GTK_WIDGET (ptr);
467   g_assert (widget != NULL);
468
469   grab_current_drawable (widget, &(gr->drawable), &(gr->win));
470   g_assert (gr->drawable != NULL);
471
472   if (x_server_has_render_extension ())
473     init_graphics2d_as_renderable (gr);
474   else
475     init_graphics2d_as_pixbuf (gr);
476
477   NSA_SET_G2D_PTR (env, obj, gr);
478   gdk_threads_leave();
479 }
480
481 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
482   (JNIEnv *env, jobject obj)
483 {
484   struct graphics2d *gr = NULL;
485
486   gdk_threads_enter();
487   gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj);
488   if (gr == NULL) 
489     {
490       gdk_threads_leave();
491       return; /* dispose has been called more than once */
492     }
493
494   if (gr->surface)
495     cairo_surface_destroy (gr->surface);
496
497   cairo_destroy (gr->cr);
498
499   if (gr->drawbuf)
500     g_object_unref (gr->drawbuf); 
501
502   g_object_unref (gr->drawable);
503
504   if (gr->pattern)
505     cairo_pattern_destroy (gr->pattern);
506
507   if (gr->pattern_surface)
508     cairo_surface_destroy (gr->pattern_surface);
509
510   if (gr->pattern_pixels)
511     free (gr->pattern_pixels);
512
513   if (gr->debug) printf ("disposed of graphics2d\n");
514
515   free (gr);
516   gdk_threads_leave();
517 }
518
519
520 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient 
521   (JNIEnv *env, jobject obj, 
522    jdouble x1, jdouble y1, 
523    jdouble x2, jdouble y2,
524    jint r1, jint g1, jint b1, jint a1,
525    jint r2, jint g2, jint b2, jint a2,
526    jboolean cyclic)
527 {
528   struct graphics2d *gr = NULL;
529   cairo_surface_t *surf = NULL;
530   cairo_matrix_t *mat = NULL;
531   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
532   g_assert (gr != NULL);
533
534   gdk_threads_enter();
535   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
536   if (gr->debug) printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",
537                          x1, y1, 
538                          x2, y2, 
539                          r1, g1, b1, a1, 
540                          r2, g2, b2, a2);
541   
542   cairo_save (gr->cr);
543   
544   if (cyclic)
545     surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2);
546   else
547     surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2);      
548   g_assert (surf != NULL);
549
550   cairo_set_target_surface (gr->cr, surf);
551   
552   cairo_identity_matrix (gr->cr);
553
554   cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
555   cairo_set_alpha (gr->cr, a1 / 255.0);
556   cairo_rectangle (gr->cr, 0, 0, 1, 2);
557   cairo_fill (gr->cr);
558     
559   cairo_set_rgb_color (gr->cr, r2 / 255.0, g2 / 255.0, b2 / 255.0);
560   cairo_set_alpha (gr->cr, a2 / 255.0);
561   cairo_rectangle (gr->cr, 1, 0, 1, 2);
562   cairo_fill (gr->cr);
563
564   if (cyclic)
565     {
566       cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
567       cairo_set_alpha (gr->cr, a1 / 255.0);
568       cairo_rectangle (gr->cr, 2, 0, 1, 2);
569       cairo_fill (gr->cr);
570     }
571
572   mat = cairo_matrix_create ();
573   g_assert (mat != NULL);
574
575   /* 
576      consider the vector [x2 - x1, y2 - y1] = [p,q]
577
578      this is a line in space starting at an 'origin' x1, y1.
579
580      it can also be thought of as a "transformed" unit vector in either the
581      x or y directions. we have just *drawn* our gradient as a unit vector
582      (well, a 2-3x unit vector) in the x dimension. so what we want to know
583      is which transformation turns our existing unit vector into [p,q].
584
585      which means solving for M in 
586  
587      [p,q] = M[1,0]
588
589      [p,q] = |a b| [1,0]
590              |c d|      
591
592      [p,q] = [a,c], with b = d = 0.
593
594      what does this mean? it means that our gradient is 1-dimensional; as
595      you move through the x axis of our 2 or 3 pixel gradient from logical
596      x positions 0 to 1, the transformation of your x coordinate under the
597      matrix M causes you to accumulate both x and y values in fill
598      space. the y value of a gradient coordinate is ignored, since the
599      gradient is one dimensional. which is correct.
600
601      unfortunately we want the opposite transformation, it seems, because of
602      the way cairo is going to use this transformation. I'm a bit confused by
603      that, but it seems to work right, so we take reciprocals of values and
604      negate offsets. oh well.
605      
606    */
607   {
608     double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1));
609     double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1));
610     double dx = (x1 == 0.) ? 0. : 1. / x1;
611     double dy = (y1 == 0.) ? 0. : 1. / y1;
612     
613     cairo_matrix_set_affine (mat,
614                              a, 0.,
615                              c, 0.,
616                              dx, dy);
617     
618     cairo_surface_set_matrix (surf, mat);
619     cairo_matrix_destroy (mat);
620     cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
621   }
622
623   /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */
624   /*   cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */
625
626   if (gr->pattern)
627     cairo_pattern_destroy (gr->pattern);
628   
629   if (gr->pattern_surface)
630     cairo_surface_destroy (gr->pattern_surface);
631
632   if (gr->pattern_pixels)
633     free (gr->pattern_pixels);
634   
635   gr->pattern_pixels = NULL;  
636   gr->pattern_surface = surf;  
637   gr->pattern = cairo_pattern_create_for_surface(surf);
638
639   cairo_restore (gr->cr);    
640   cairo_set_pattern (gr->cr, gr->pattern);
641   gdk_threads_leave();
642 }
643
644 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels 
645   (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride)
646 {
647   struct graphics2d *gr = NULL;
648   jint *jpixels = NULL;
649
650   gdk_threads_enter();
651   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
652   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
653   g_assert (gr != NULL);
654
655   if (gr->debug) printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n",
656                          (*env)->GetArrayLength (env, jarr), w, h, stride);
657
658   if (gr->pattern)
659     cairo_pattern_destroy (gr->pattern);
660
661   if (gr->pattern_surface)
662     cairo_surface_destroy (gr->pattern_surface);
663
664   if (gr->pattern_pixels)
665     free (gr->pattern_pixels);
666
667   gr->pattern = NULL;
668   gr->pattern_surface = NULL;
669   gr->pattern_pixels = NULL;
670
671   gr->pattern_pixels = (char *) malloc (h * stride * 4);
672   g_assert (gr->pattern_pixels != NULL);
673
674   jpixels = (*env)->GetIntArrayElements (env, jarr, NULL);
675   g_assert (jpixels != NULL);
676   memcpy (gr->pattern_pixels, jpixels, h * stride * 4);
677   (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
678
679   gr->pattern_surface = cairo_surface_create_for_image (gr->pattern_pixels, 
680                                                         CAIRO_FORMAT_ARGB32, 
681                                                         w, h, stride * 4);
682   g_assert (gr->pattern_surface != NULL);
683   cairo_surface_set_repeat (gr->pattern_surface, 1);
684   gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface);
685   g_assert (gr->pattern != NULL);
686   cairo_set_pattern (gr->cr, gr->pattern);
687   gdk_threads_leave();
688 }
689
690 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels 
691   (JNIEnv *env, jobject obj, jintArray java_pixels, 
692    jint w, jint h, jint stride, jdoubleArray java_matrix)
693 {
694   struct graphics2d *gr = NULL;
695   jint *native_pixels = NULL;
696   jdouble *native_matrix = NULL;
697
698   gdk_threads_enter();
699   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
700
701   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
702   g_assert (gr != NULL);
703
704   if (gr->debug) printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n",
705                          (*env)->GetArrayLength (env, java_pixels), w, h, stride);
706
707   native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL);
708   native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
709   g_assert (native_pixels != NULL);
710   g_assert (native_matrix != NULL);
711   g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
712
713   begin_drawing_operation (gr);
714   
715  {
716    cairo_matrix_t *mat = NULL;
717    cairo_surface_t *surf = cairo_surface_create_for_image ((char *)native_pixels, 
718                                                            CAIRO_FORMAT_ARGB32, 
719                                                            w, h, stride * 4);   
720    mat = cairo_matrix_create ();
721    cairo_matrix_set_affine (mat, 
722                             native_matrix[0], native_matrix[1],
723                             native_matrix[2], native_matrix[3],
724                             native_matrix[4], native_matrix[5]);
725    cairo_surface_set_matrix (surf, mat);
726    cairo_surface_set_filter (surf, cairo_surface_get_filter(gr->surface));
727    cairo_show_surface (gr->cr, surf, w, h);
728    cairo_matrix_destroy (mat);
729    cairo_surface_destroy (surf);
730  }
731   
732  end_drawing_operation (gr);
733  
734  (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0);
735  (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
736  
737   gdk_threads_leave();
738 }
739
740 JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePixels 
741    (JNIEnv *env, jobject obj)
742 {
743   struct graphics2d *gr = NULL;
744   jintArray java_pixels;
745   jint* native_pixels;
746   GdkPixbuf *buf = NULL;
747   gint width, height;
748   gint bits_per_sample = 8;
749   gboolean has_alpha = TRUE;
750   gint total_channels = 4;
751   jint i, px;
752
753   gdk_threads_enter();
754   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return NULL; }
755
756   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
757   g_assert (gr != NULL);
758   
759   if (gr->debug) printf ("getImagePixels\n");
760   
761   gdk_drawable_get_size (gr->drawable, &width, &height);
762     
763   buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 
764                         bits_per_sample,
765                         width, height);
766   g_assert (buf != NULL);
767   g_assert (gdk_pixbuf_get_bits_per_sample (buf) == bits_per_sample);
768   g_assert (gdk_pixbuf_get_n_channels (buf) == total_channels);
769   
770       
771   /* copy pixels from drawable to pixbuf */
772   
773   gdk_pixbuf_get_from_drawable (buf, gr->drawable,
774                                 NULL, 
775                                 0, 0, 0, 0,
776                                 width, height);
777                                                                                                       
778   native_pixels= gdk_pixbuf_get_pixels (buf);
779   
780      
781   /* NOTE: The pixels we got in the pixbuf are stored 
782      in reversed order. i.e 0xBBGGRRAA. 
783      We need to convert them to  0xAARRGGBB. */
784    
785   for (i=0; i<width * height; i++) 
786     {        
787               
788         /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
789         
790         px = native_pixels[i];
791         px = ((px >> 24) & 0xff) | ((px << 8) & 0xffffff00); 
792         px = ((px >>  8) & 0x00ff00ff) | ((px <<  8) & 0xff00ff00); 
793         px = ((px >> 16) & 0x0000ffff) | ((px << 16) & 0xffff0000); 
794         native_pixels[i] = px;
795       
796     }
797
798    java_pixels = (*env) -> NewIntArray (env, width * height);   
799    
800    (*env)->SetIntArrayRegion(env, java_pixels, 
801                             (jsize)0, (jsize) width*height, 
802                             (jint*) native_pixels);
803    
804    gdk_threads_leave();
805    return java_pixels;
806 }
807
808 /* passthrough methods to cairo */
809
810 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave 
811    (JNIEnv *env, jobject obj)
812 {
813   struct graphics2d *gr = NULL;
814
815   gdk_threads_enter();
816   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
817
818   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
819   g_assert (gr != NULL);
820   if (gr->debug) printf ("cairo_save\n");
821   cairo_save (gr->cr);
822   gdk_threads_leave();
823 }
824
825 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore 
826    (JNIEnv *env, jobject obj)
827 {
828   struct graphics2d *gr = NULL;
829
830   gdk_threads_enter();
831   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
832
833   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
834   g_assert (gr != NULL);
835   if (gr->debug) printf ("cairo_restore\n");
836   cairo_restore (gr->cr);
837   update_pattern_transform (gr);
838   gdk_threads_leave();
839 }
840
841 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix 
842    (JNIEnv *env, jobject obj, jdoubleArray java_matrix)
843 {
844   struct graphics2d *gr = NULL;
845   jdouble *native_matrix = NULL;
846
847   gdk_threads_enter();
848   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
849
850   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
851   g_assert (gr != NULL);
852
853   native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);  
854   g_assert (native_matrix != NULL);
855   g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
856
857   if (gr->debug) printf ("cairo_set_matrix [ %f, %f, %f, %f, %f, %f ]\n",
858                          native_matrix[0], native_matrix[1],
859                          native_matrix[2], native_matrix[3],
860                          native_matrix[4], native_matrix[5]);
861
862   {
863     cairo_matrix_t * mat = cairo_matrix_create ();
864     cairo_matrix_set_affine (mat, 
865                              native_matrix[0], native_matrix[1],
866                              native_matrix[2], native_matrix[3],
867                              native_matrix[4], native_matrix[5]);
868     cairo_set_matrix (gr->cr, mat);
869     cairo_matrix_destroy (mat);
870   }
871
872   (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
873   update_pattern_transform (gr);
874   gdk_threads_leave();
875 }
876
877 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont 
878    (JNIEnv *env, jobject obj, jobject font)
879 {
880   struct graphics2d *gr = NULL;
881   struct peerfont *pfont = NULL;
882   cairo_font_t *ft = NULL;
883   FT_Face face = NULL;
884
885   gdk_threads_enter();
886   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
887
888   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
889   g_assert (gr != NULL);
890
891   pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
892   g_assert (pfont != NULL);
893
894   face = pango_ft2_font_get_face (pfont->font);
895   g_assert (face != NULL);
896
897   ft = cairo_ft_font_create_for_ft_face (face);
898   g_assert (ft != NULL);
899
900   if (gr->debug) printf ("cairo_set_font '%s'\n", face->family_name);
901   
902   cairo_set_font (gr->cr, ft);
903
904   cairo_scale_font (gr->cr, 
905                     pango_font_description_get_size (pfont->desc) / 
906                     (double)PANGO_SCALE);
907
908   cairo_font_destroy (ft);
909   gdk_threads_leave();
910 }
911
912 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs
913    (JNIEnv *env, jobject obj, jintArray java_codes, jfloatArray java_posns)
914 {
915   struct graphics2d *gr = NULL;
916   cairo_glyph_t *glyphs = NULL;
917   jfloat *native_posns = NULL;
918   jint *native_codes = NULL;
919   jint i;
920   jint ncodes, nposns;
921
922   gdk_threads_enter();
923   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
924
925   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
926   g_assert (gr != NULL);
927
928   native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL);  
929   native_posns = (*env)->GetFloatArrayElements (env, java_posns, NULL);  
930   g_assert (native_codes != NULL);
931   g_assert (native_posns != NULL);
932
933   ncodes = (*env)->GetArrayLength (env, java_codes);
934   nposns = (*env)->GetArrayLength (env, java_posns);
935   g_assert (2 * ncodes == nposns);
936
937   if (gr->debug) printf ("cairo_show_glyphs (%d glyphs)\n", ncodes);
938
939   glyphs = malloc (sizeof(cairo_glyph_t) * ncodes);
940   g_assert (glyphs);
941
942   for (i = 0; i < ncodes; ++i)
943     {
944       glyphs[i].index = native_codes[i];
945       glyphs[i].x = (double) native_posns[2*i];
946       glyphs[i].y = (double) native_posns[2*i + 1];
947       if (gr->debug) printf ("cairo_show_glyphs (glyph %d (code %d) : %f,%f)\n", 
948                              i, glyphs[i].index, glyphs[i].x, glyphs[i].y);
949     }
950
951   (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
952   (*env)->ReleaseFloatArrayElements (env, java_posns, native_posns, 0);
953
954   begin_drawing_operation (gr);
955   cairo_show_glyphs (gr->cr, glyphs, ncodes);
956   end_drawing_operation (gr);
957
958   free(glyphs);
959   gdk_threads_leave();
960 }
961
962 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator 
963    (JNIEnv *env, jobject obj, jint op)
964 {
965   struct graphics2d *gr = NULL;
966
967   gdk_threads_enter();
968   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
969
970   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
971   g_assert (gr != NULL);
972   if (gr->debug) printf ("cairo_set_operator %d\n", op);
973   switch ((enum java_awt_alpha_composite_rule) op)
974     {
975     case java_awt_alpha_composite_CLEAR: 
976       cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR);
977       break;
978       
979     case java_awt_alpha_composite_SRC: 
980       cairo_set_operator (gr->cr, CAIRO_OPERATOR_SRC);
981       break;
982       
983     case java_awt_alpha_composite_SRC_OVER: 
984       cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER);
985       break;
986
987     case java_awt_alpha_composite_DST_OVER: 
988       cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER_REVERSE);
989       break;
990
991     case java_awt_alpha_composite_SRC_IN: 
992       cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN);
993       break;
994
995     case java_awt_alpha_composite_DST_IN: 
996       cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN_REVERSE);
997       break;
998
999     case java_awt_alpha_composite_SRC_OUT: 
1000       cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT);
1001       break;
1002
1003     case java_awt_alpha_composite_DST_OUT: 
1004       cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT_REVERSE);
1005       break;
1006
1007     case java_awt_alpha_composite_DST: 
1008       cairo_set_operator (gr->cr, CAIRO_OPERATOR_DST);
1009       break;
1010
1011     case java_awt_alpha_composite_SRC_ATOP: 
1012       cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP);
1013       break;
1014
1015     case java_awt_alpha_composite_DST_ATOP: 
1016       cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP_REVERSE);
1017       break;
1018
1019     case java_awt_alpha_composite_XOR: 
1020       cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR);
1021       break;
1022     }
1023   gdk_threads_leave();
1024 }
1025
1026 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBColor 
1027    (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b)
1028 {
1029   struct graphics2d *gr = NULL;
1030
1031   gdk_threads_enter();
1032   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1033
1034   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1035   g_assert (gr != NULL);
1036
1037   /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider
1038      colors in opposite pixel order. I have no idea why.  thus when you
1039      draw to a PixBuf, you must exchange the R and B components of your
1040      color. */
1041
1042   if (gr->debug) printf ("cairo_set_rgb_color (%f, %f, %f)\n", r, g, b);
1043
1044   if (gr->drawbuf)
1045     cairo_set_rgb_color (gr->cr, b, g, r);
1046   else
1047     cairo_set_rgb_color (gr->cr, r, g, b);
1048
1049   gdk_threads_leave();
1050 }
1051
1052 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetAlpha 
1053    (JNIEnv *env, jobject obj, jdouble a)
1054 {
1055   struct graphics2d *gr = NULL;
1056
1057   gdk_threads_enter();
1058   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1059
1060   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1061   g_assert (gr != NULL);
1062   if (gr->debug) printf ("cairo_set_alpha %f\n", a);
1063   cairo_set_alpha (gr->cr, a);
1064   gdk_threads_leave();
1065 }
1066
1067 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule 
1068    (JNIEnv *env, jobject obj, jint rule)
1069 {
1070   struct graphics2d *gr = NULL;
1071
1072   gdk_threads_enter();
1073   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1074
1075   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1076   if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule);
1077   g_assert (gr != NULL);
1078   switch ((enum java_awt_geom_path_iterator_winding_rule) rule)
1079     {
1080     case java_awt_geom_path_iterator_WIND_NON_ZERO:
1081       cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING);
1082       break;
1083     case java_awt_geom_path_iterator_WIND_EVEN_ODD:
1084       cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD);
1085       break;
1086     }  
1087   gdk_threads_leave();
1088 }
1089
1090 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth 
1091    (JNIEnv *env, jobject obj, jdouble width)
1092 {
1093   struct graphics2d *gr = NULL;
1094
1095   gdk_threads_enter();
1096   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1097
1098   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1099   g_assert (gr != NULL);
1100   if (gr->debug) printf ("cairo_set_line_width %f\n", width);
1101   cairo_set_line_width (gr->cr, width);
1102   gdk_threads_leave();
1103 }
1104
1105 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap 
1106    (JNIEnv *env, jobject obj, jint cap)
1107 {
1108   struct graphics2d *gr = NULL;
1109
1110   gdk_threads_enter();
1111   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1112
1113   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1114   g_assert (gr != NULL);
1115   if (gr->debug) printf ("cairo_set_line_cap %d\n", cap);
1116   switch ((enum java_awt_basic_stroke_cap_rule) cap)
1117     {
1118     case java_awt_basic_stroke_CAP_BUTT: 
1119       cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT);
1120       break;
1121
1122     case java_awt_basic_stroke_CAP_ROUND: 
1123       cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND);
1124       break;
1125
1126     case java_awt_basic_stroke_CAP_SQUARE: 
1127       cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE);
1128       break;
1129     }
1130   gdk_threads_leave();
1131 }
1132
1133 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin 
1134    (JNIEnv *env, jobject obj, jint join)
1135 {
1136   struct graphics2d *gr = NULL;
1137
1138   gdk_threads_enter();
1139   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1140
1141   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1142   g_assert (gr != NULL);
1143   if (gr->debug) printf ("cairo_set_line_join %d\n", join);
1144   switch ((enum java_awt_basic_stroke_join_rule) join)
1145     {
1146     case java_awt_basic_stroke_JOIN_MITER:
1147       cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER);
1148       break;
1149
1150     case java_awt_basic_stroke_JOIN_ROUND:
1151       cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND);
1152       break;
1153
1154     case java_awt_basic_stroke_JOIN_BEVEL:
1155       cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL);
1156       break;
1157     }
1158   gdk_threads_leave();
1159 }
1160
1161 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash 
1162    (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset)
1163 {
1164   struct graphics2d *gr = NULL;
1165   jdouble *dasharr = NULL;
1166
1167   gdk_threads_enter();
1168   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1169
1170   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1171   g_assert (gr != NULL);
1172   if (gr->debug) printf ("cairo_set_dash\n");
1173   dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL);  
1174   g_assert (dasharr != NULL);
1175   cairo_set_dash (gr->cr, dasharr, ndash, offset);
1176   (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0);
1177   gdk_threads_leave();
1178 }
1179
1180 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit 
1181    (JNIEnv *env, jobject obj, jdouble miter)
1182 {
1183   struct graphics2d *gr = NULL;
1184
1185   gdk_threads_enter();
1186   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1187
1188   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1189   g_assert (gr != NULL);
1190   if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter);
1191   cairo_set_miter_limit (gr->cr, miter);
1192   gdk_threads_leave();
1193 }
1194
1195
1196 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath 
1197    (JNIEnv *env, jobject obj)
1198 {
1199   struct graphics2d *gr = NULL;
1200
1201   gdk_threads_enter();
1202   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1203
1204   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1205   g_assert (gr != NULL);
1206   if (gr->debug) printf ("cairo_new_path\n");
1207   cairo_new_path (gr->cr);
1208   gdk_threads_leave();
1209 }
1210
1211 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo 
1212    (JNIEnv *env, jobject obj, jdouble x, jdouble y)
1213 {
1214   struct graphics2d *gr = NULL;
1215
1216   gdk_threads_enter();
1217   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1218
1219   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1220   g_assert (gr != NULL);
1221   if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y);
1222   cairo_move_to (gr->cr, x, y);
1223   gdk_threads_leave();
1224 }
1225
1226 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo 
1227    (JNIEnv *env, jobject obj, jdouble x, jdouble y)
1228 {
1229   struct graphics2d *gr = NULL;
1230
1231   gdk_threads_enter();
1232   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1233
1234   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1235   g_assert (gr != NULL);
1236   if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y);
1237   cairo_line_to (gr->cr, x, y);
1238   gdk_threads_leave();
1239 }
1240
1241 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo 
1242    (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3)
1243 {
1244   struct graphics2d *gr = NULL;
1245
1246   gdk_threads_enter();
1247   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1248
1249   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1250   g_assert (gr != NULL);
1251   if (gr->debug) printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", x1, y1, x2, y2, x3, y3);
1252   cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3);
1253   gdk_threads_leave();
1254 }
1255
1256 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo 
1257    (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
1258 {
1259   struct graphics2d *gr = NULL;
1260
1261   gdk_threads_enter();
1262   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1263
1264   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1265   g_assert (gr != NULL);
1266   if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy);
1267   cairo_rel_move_to (gr->cr, dx, dy);
1268   gdk_threads_leave();
1269 }
1270
1271 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo 
1272    (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
1273 {
1274   struct graphics2d *gr = NULL;
1275
1276   gdk_threads_enter();
1277   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1278
1279   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1280   g_assert (gr != NULL);
1281   if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy);
1282   cairo_rel_line_to (gr->cr, dx, dy);
1283   gdk_threads_leave();
1284 }
1285
1286 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo 
1287    (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3)
1288 {
1289   struct graphics2d *gr = NULL;
1290
1291   gdk_threads_enter();
1292   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1293
1294   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1295   g_assert (gr != NULL);
1296   if (gr->debug) printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", dx1, dy1, dx2, dy2, dx3, dy3);
1297   cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3);
1298   gdk_threads_leave();
1299 }
1300
1301 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle 
1302    (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height)
1303 {
1304   struct graphics2d *gr = NULL;
1305
1306   gdk_threads_enter();
1307   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1308
1309   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1310   g_assert (gr != NULL);
1311   if (gr->debug) printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height);
1312   cairo_rectangle (gr->cr, x, y, width, height);
1313   gdk_threads_leave();
1314 }
1315
1316 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath 
1317    (JNIEnv *env, jobject obj)
1318 {
1319   struct graphics2d *gr = NULL;
1320
1321   gdk_threads_enter();
1322   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1323
1324   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1325   g_assert (gr != NULL);
1326   if (gr->debug) printf ("cairo_close_path\n");
1327   cairo_close_path (gr->cr);
1328   gdk_threads_leave();
1329 }
1330
1331 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke 
1332    (JNIEnv *env, jobject obj)
1333 {
1334   struct graphics2d *gr = NULL;
1335
1336   gdk_threads_enter();
1337   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1338
1339   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1340   g_assert (gr != NULL);
1341   if (gr->debug) printf ("cairo_stroke\n");
1342   begin_drawing_operation (gr);
1343   cairo_stroke (gr->cr);
1344   end_drawing_operation (gr);
1345   gdk_threads_leave();
1346 }
1347
1348 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill 
1349    (JNIEnv *env, jobject obj)
1350 {
1351   struct graphics2d *gr = NULL;
1352
1353   gdk_threads_enter();
1354   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1355
1356   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1357   g_assert (gr != NULL);
1358   if (gr->debug) printf ("cairo_fill\n");
1359   begin_drawing_operation (gr);
1360   cairo_fill (gr->cr);
1361   end_drawing_operation (gr);
1362   gdk_threads_leave();
1363 }
1364
1365 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip 
1366    (JNIEnv *env, jobject obj)
1367 {
1368   struct graphics2d *gr = NULL;
1369
1370   gdk_threads_enter();
1371   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1372
1373   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1374   g_assert (gr != NULL);
1375   if (gr->debug) printf ("cairo_clip\n");
1376   begin_drawing_operation (gr);
1377   cairo_init_clip (gr->cr);
1378   cairo_clip (gr->cr);
1379   end_drawing_operation (gr);
1380   gdk_threads_leave();
1381 }
1382
1383 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter
1384    (JNIEnv *env, jobject obj, jint filter)
1385 {
1386    struct graphics2d *gr = NULL;   
1387
1388    gdk_threads_enter();
1389   if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
1390
1391    gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1392    g_assert (gr != NULL);
1393    if (gr->debug) printf ("cairo_surface_set_filter %d\n", filter);   
1394    switch ((enum java_awt_rendering_hints_filter) filter)
1395      {
1396      case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR:
1397        cairo_surface_set_filter (gr->surface, CAIRO_FILTER_NEAREST);
1398        break;
1399      case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR:
1400        cairo_surface_set_filter (gr->surface, CAIRO_FILTER_BILINEAR);
1401        break; 
1402      case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED:
1403        cairo_surface_set_filter (gr->surface, CAIRO_FILTER_FAST);
1404        break;
1405      case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT:
1406        cairo_surface_set_filter (gr->surface, CAIRO_FILTER_NEAREST);
1407        break;
1408      case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY:
1409        cairo_surface_set_filter (gr->surface, CAIRO_FILTER_BEST);
1410        break;
1411      }
1412    gdk_threads_leave();
1413 }