OSDN Git Service

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