2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GdkGraphics2D.c
blob3bc93af8143deb4f09bd17a61dacc4b07563e38c
1 /* gnu_java_awt_peer_gtk_GdkGraphics2d.c
2 Copyright (C) 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
38 #include "gtkpeer.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>
45 #include <gdk-pixbuf/gdk-pixbuf.h>
46 #include <gdk-pixbuf/gdk-pixdata.h>
48 #include <cairo.h>
50 #include <stdio.h>
51 #include <stdlib.h>
53 struct state_table *native_graphics2d_state_table;
55 #define NSA_G2D_INIT(env, clazz) \
56 native_graphics2d_state_table = init_state_table (env, clazz)
58 #define NSA_GET_G2D_PTR(env, obj) \
59 get_state (env, obj, native_graphics2d_state_table)
61 #define NSA_SET_G2D_PTR(env, obj, ptr) \
62 set_state (env, obj, native_graphics2d_state_table, (void *)ptr)
64 #define NSA_DEL_G2D_PTR(env, obj) \
65 remove_state_slot (env, obj, native_graphics2d_state_table)
67 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState
68 (JNIEnv *env, jclass clazz)
70 NSA_G2D_INIT (env, clazz);
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. */
77 #ifndef min
78 #define min(x,y) ((x) < (y) ? (x) : (y))
79 #endif
81 enum java_awt_alpha_composite_rule
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
97 enum java_awt_basic_stroke_join_rule
99 java_awt_basic_stroke_JOIN_MITER = 0,
100 java_awt_basic_stroke_JOIN_ROUND = 1,
101 java_awt_basic_stroke_JOIN_BEVEL = 2
104 enum java_awt_basic_stroke_cap_rule
106 java_awt_basic_stroke_CAP_BUTT = 0,
107 java_awt_basic_stroke_CAP_ROUND = 1,
108 java_awt_basic_stroke_CAP_SQUARE = 2
111 enum java_awt_geom_path_iterator_winding_rule
113 java_awt_geom_path_iterator_WIND_EVEN_ODD = 0,
114 java_awt_geom_path_iterator_WIND_NON_ZERO = 1
118 static void
119 grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win)
121 g_assert (widget != NULL);
122 g_assert (draw != NULL);
123 g_assert (win != NULL);
125 if (GTK_IS_WINDOW (widget))
127 *win = find_gtk_layout (widget)->bin_window;
129 else if (GTK_IS_LAYOUT (widget))
131 *win = GTK_LAYOUT (widget)->bin_window;
133 else
135 *win = widget->window;
138 *draw = *win;
139 gdk_window_get_internal_paint_info (*win, draw, 0, 0);
140 g_object_ref (*draw);
144 static int
145 x_server_has_render_extension (void)
147 int ev = 0, err = 0;
148 return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err);
152 static void
153 init_graphics2d_as_pixbuf (struct graphics2d *gr)
155 gint width, height;
156 gint bits_per_sample = 8;
157 gint total_channels = 4;
158 gboolean has_alpha = TRUE;
160 g_assert (gr != NULL);
161 g_assert (gr->drawable != NULL);
163 if (gr->debug) printf ("initializing graphics2d as pixbuf\n");
164 gdk_drawable_get_size (gr->drawable, &width, &height);
165 gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
166 has_alpha, bits_per_sample,
167 width, height);
168 g_assert (gr->drawbuf != NULL);
169 g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample);
170 g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels);
172 gr->surface = cairo_surface_create_for_image (gdk_pixbuf_get_pixels (gr->drawbuf),
173 CAIRO_FORMAT_ARGB32,
174 gdk_pixbuf_get_width (gr->drawbuf),
175 gdk_pixbuf_get_height (gr->drawbuf),
176 gdk_pixbuf_get_rowstride (gr->drawbuf));
177 g_assert (gr->surface != NULL);
178 g_assert (gr->cr != NULL);
179 cairo_set_target_surface (gr->cr, gr->surface);
182 static void
183 init_graphics2d_as_renderable (struct graphics2d *gr)
185 Drawable draw;
186 Display * dpy;
187 Visual * vis;
189 g_assert (gr != NULL);
190 g_assert (gr->drawable != NULL);
192 gr->drawbuf = NULL;
194 if (gr->debug) printf ("initializing graphics2d as renderable\n");
195 draw = gdk_x11_drawable_get_xid (gr->drawable);
197 dpy = gdk_x11_drawable_get_xdisplay (gr->drawable);
198 g_assert (dpy != NULL);
200 vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable));
201 g_assert (vis != NULL);
203 gr->surface = cairo_xlib_surface_create (dpy, draw, vis,
204 CAIRO_FORMAT_ARGB32,
205 DefaultColormap (dpy, DefaultScreen (dpy)));
206 g_assert (gr->surface != NULL);
207 g_assert (gr->cr != NULL);
208 cairo_set_target_surface (gr->cr, gr->surface);
211 static void
212 begin_drawing_operation (struct graphics2d * gr)
214 gdk_threads_enter ();
215 if (gr->drawbuf)
218 gint drawable_width, drawable_height;
219 gint pixbuf_width, pixbuf_height;
220 gint width, height;
222 gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
223 pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
224 pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
225 width = min (drawable_width, pixbuf_width);
226 height = min (drawable_height, pixbuf_height);
228 gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */
229 gr->drawable,
230 NULL, /* colormap */
231 0, 0, 0, 0,
232 width, height);
234 if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n",
235 width, height);
239 static void
240 end_drawing_operation (struct graphics2d * gr)
242 if (gr->drawbuf)
244 gint drawable_width, drawable_height;
245 gint pixbuf_width, pixbuf_height;
246 gint width, height;
248 gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height);
249 pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf);
250 pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf);
251 width = min (drawable_width, pixbuf_width);
252 height = min (drawable_height, pixbuf_height);
254 gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf,
255 0, 0, 0, 0,
256 width, height,
257 GDK_RGB_DITHER_NORMAL, 0, 0);
259 if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n",
260 width, height);
262 gdk_threads_leave ();
266 static void
267 update_pattern_transform (struct graphics2d *gr)
269 double a, b, c, d, tx, ty;
270 cairo_matrix_t *mat = NULL;
272 g_assert (gr != NULL);
273 if (gr->pattern == NULL)
274 return;
276 return;
277 /* temporarily disabled: ambiguous behavior */
278 /* cairo_get_matrix (gr->cr, &a, &b, &c, &d, &tx, &ty); */
279 mat = cairo_matrix_create ();
280 g_assert (mat != NULL);
281 cairo_matrix_set_affine (mat, a, b, c, d, tx, ty);
282 cairo_surface_set_matrix (gr->pattern, mat);
283 cairo_matrix_destroy (mat);
286 static void
287 check_for_debug (struct graphics2d *gr)
289 gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL);
292 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState
293 (JNIEnv *env, jobject obj, jobject old)
295 struct graphics2d *g = NULL, *g_old = NULL;
297 g = (struct graphics2d *) malloc (sizeof (struct graphics2d));
298 g_assert (g != NULL);
299 memset (g, 0, sizeof(struct graphics2d));
301 g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old);
302 g_assert (g_old != NULL);
304 if (g_old->debug) printf ("copying state from existing graphics2d\n");
306 g->drawable = g_old->drawable;
307 g->debug = g_old->debug;
309 gdk_threads_enter ();
310 g_object_ref (g->drawable);
312 g->cr = cairo_create();
313 g_assert (g->cr != NULL);
315 if (x_server_has_render_extension ())
316 init_graphics2d_as_renderable (g);
317 else
318 init_graphics2d_as_pixbuf (g);
320 cairo_surface_set_filter (g->surface, CAIRO_FILTER_FAST);
322 gdk_threads_leave ();
324 NSA_SET_G2D_PTR (env, obj, g);
328 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II
329 (JNIEnv *env, jobject obj, jint width, jint height)
331 struct graphics2d *gr;
333 gdk_threads_enter ();
335 gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
336 g_assert (gr != NULL);
337 memset (gr, 0, sizeof(struct graphics2d));
339 check_for_debug (gr);
341 if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n",
342 width, height);
344 gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height,
345 gdk_rgb_get_visual ()->depth);
346 g_assert (gr->drawable != NULL);
348 gr->cr = cairo_create();
349 g_assert (gr->cr != NULL);
351 if (x_server_has_render_extension ())
352 init_graphics2d_as_renderable (gr);
353 else
354 init_graphics2d_as_pixbuf (gr);
356 gdk_threads_leave ();
357 if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n",
358 width, height);
359 NSA_SET_G2D_PTR (env, obj, gr);
362 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
363 (JNIEnv *env, jobject self, jobject other, jint x, jint y)
365 struct graphics2d *src = NULL, *dst = NULL;
366 gint s_height, s_width, d_height, d_width, height, width;
367 GdkGC *gc;
369 src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other);
370 dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, self);
371 g_assert (src != NULL);
372 g_assert (dst != NULL);
374 if (src->debug) printf ("copying from offscreen drawable\n");
376 gdk_threads_enter ();
377 gdk_drawable_get_size (src->drawable, &s_width, &s_height);
378 gdk_drawable_get_size (dst->drawable, &d_width, &d_height);
379 width = min (s_width, d_width);
380 height = min (s_width, d_height);
382 gc = gdk_gc_new (dst->drawable);
383 g_assert (gc != NULL);
385 gdk_draw_drawable(dst->drawable, gc, src->drawable,
386 0, 0, x, y, width, height);
387 gdk_flush ();
389 g_object_unref (gc);
391 if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height);
392 gdk_threads_leave ();
395 static jintArray
396 current_colors_of_widget (GtkWidget *widget, JNIEnv *env)
398 GdkColor color;
399 jintArray array;
400 jint *rgb;
402 g_assert (widget != NULL);
403 g_assert (env != NULL);
405 color = widget->style->fg[GTK_STATE_NORMAL];
406 array = (*env)->NewIntArray (env, 6);
408 rgb = (*env)->GetIntArrayElements (env, array, NULL);
409 rgb[0] = color.red >> 8;
410 rgb[1] = color.green >> 8;
411 rgb[2] = color.blue >> 8;
413 color = widget->style->bg[GTK_STATE_NORMAL];
414 rgb[3] = color.red >> 8;
415 rgb[4] = color.green >> 8;
416 rgb[5] = color.blue >> 8;
418 (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
420 return array;
423 JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
424 (JNIEnv *env, jobject obj, jobject peer)
426 struct graphics2d *gr = NULL;
427 GtkWidget *widget = NULL;
428 void *ptr = NULL;
429 jintArray color;
431 ptr = NSA_GET_PTR (env, peer);
432 g_assert (ptr != NULL);
433 gdk_threads_enter ();
435 gr = (struct graphics2d *) malloc (sizeof (struct graphics2d));
436 g_assert (gr != NULL);
437 memset (gr, 0, sizeof(struct graphics2d));
439 check_for_debug (gr);
441 gr->cr = cairo_create();
442 g_assert (gr->cr != NULL);
444 widget = GTK_WIDGET (ptr);
445 g_assert (widget != NULL);
447 grab_current_drawable (widget, &(gr->drawable), &(gr->win));
448 g_assert (gr->drawable != NULL);
450 if (x_server_has_render_extension ())
451 init_graphics2d_as_renderable (gr);
452 else
453 init_graphics2d_as_pixbuf (gr);
455 color = current_colors_of_widget (widget, env);
457 gdk_threads_leave ();
458 NSA_SET_G2D_PTR (env, obj, gr);
459 return color;
462 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
463 (JNIEnv *env, jobject obj)
465 struct graphics2d *gr = NULL;
467 gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj);
468 if (gr == NULL)
469 return; /* dispose has been called more than once */
471 gdk_threads_enter ();
473 if (gr->surface)
474 cairo_surface_destroy (gr->surface);
476 cairo_destroy (gr->cr);
478 if (gr->drawbuf)
479 g_object_unref (gr->drawbuf);
481 g_object_unref (gr->drawable);
483 if (gr->pattern)
484 cairo_surface_destroy (gr->pattern);
486 if (gr->pattern_pixels)
487 free (gr->pattern_pixels);
489 if (gr->debug) printf ("disposed of graphics2d\n");
490 free (gr);
492 gdk_threads_leave ();
496 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient
497 (JNIEnv *env, jobject obj,
498 jdouble x1, jdouble y1,
499 jdouble x2, jdouble y2,
500 jint r1, jint g1, jint b1, jint a1,
501 jint r2, jint g2, jint b2, jint a2,
502 jboolean cyclic)
504 struct graphics2d *gr = NULL;
505 cairo_surface_t *surf = NULL;
506 cairo_matrix_t *mat = NULL;
507 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
508 g_assert (gr != NULL);
510 if (gr->debug) printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",
511 x1, y1,
512 x2, y2,
513 r1, g1, b1, a1,
514 r2, g2, b2, a2);
516 cairo_save (gr->cr);
518 if (cyclic)
519 surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2);
520 else
521 surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2);
522 g_assert (surf != NULL);
524 cairo_set_target_surface (gr->cr, surf);
526 cairo_identity_matrix (gr->cr);
528 cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
529 cairo_set_alpha (gr->cr, a1 / 255.0);
530 cairo_rectangle (gr->cr, 0, 0, 1, 2);
531 cairo_fill (gr->cr);
533 cairo_set_rgb_color (gr->cr, r2 / 255.0, g2 / 255.0, b2 / 255.0);
534 cairo_set_alpha (gr->cr, a2 / 255.0);
535 cairo_rectangle (gr->cr, 1, 0, 1, 2);
536 cairo_fill (gr->cr);
538 if (cyclic)
540 cairo_set_rgb_color (gr->cr, r1 / 255.0, g1 / 255.0, b1 / 255.0);
541 cairo_set_alpha (gr->cr, a1 / 255.0);
542 cairo_rectangle (gr->cr, 2, 0, 1, 2);
543 cairo_fill (gr->cr);
546 mat = cairo_matrix_create ();
547 g_assert (mat != NULL);
550 consider the vector [x2 - x1, y2 - y1] = [p,q]
552 this is a line in space starting at an 'origin' x1, y1.
554 it can also be thought of as a "transformed" unit vector in either the
555 x or y directions. we have just *drawn* our gradient as a unit vector
556 (well, a 2-3x unit vector) in the x dimension. so what we want to know
557 is which transformation turns our existing unit vector into [p,q].
559 which means solving for M in
561 [p,q] = M[1,0]
563 [p,q] = |a b| [1,0]
564 |c d|
566 [p,q] = [a,c], with b = d = 0.
568 what does this mean? it means that our gradient is 1-dimensional; as
569 you move through the x axis of our 2 or 3 pixel gradient from logical
570 x positions 0 to 1, the transformation of your x coordinate under the
571 matrix M causes you to accumulate both x and y values in fill
572 space. the y value of a gradient coordinate is ignored, since the
573 gradient is one dimensional. which is correct.
575 unfortunately we want the opposite transformation, it seems, because of
576 the way cairo is going to use this transformation. I'm a bit confused by
577 that, but it seems to work right, so we take reciprocals of values and
578 negate offsets. oh well.
582 double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1));
583 double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1));
584 double dx = (x1 == 0.) ? 0. : 1. / x1;
585 double dy = (y1 == 0.) ? 0. : 1. / y1;
587 cairo_matrix_set_affine (mat,
588 a, 0.,
589 c, 0.,
590 dx, dy);
592 cairo_surface_set_matrix (surf, mat);
593 cairo_matrix_destroy (mat);
594 cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
596 /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */
597 /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */
599 if (gr->pattern)
600 cairo_surface_destroy (gr->pattern);
602 if (gr->pattern_pixels)
604 free (gr->pattern_pixels);
605 gr->pattern_pixels = NULL;
608 gr->pattern = surf;
610 cairo_restore (gr->cr);
611 cairo_set_pattern (gr->cr, gr->pattern);
615 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels
616 (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride)
618 struct graphics2d *gr = NULL;
619 jint *jpixels = NULL;
621 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
622 g_assert (gr != NULL);
624 if (gr->debug) printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n",
625 (*env)->GetArrayLength (env, jarr), w, h, stride);
627 if (gr->pattern)
628 cairo_surface_destroy (gr->pattern);
630 if (gr->pattern_pixels)
631 free (gr->pattern_pixels);
633 gr->pattern = NULL;
634 gr->pattern_pixels = NULL;
636 gr->pattern_pixels = (char *) malloc (h * stride * 4);
637 g_assert (gr->pattern_pixels != NULL);
639 jpixels = (*env)->GetIntArrayElements (env, jarr, NULL);
640 g_assert (jpixels != NULL);
641 memcpy (gr->pattern_pixels, jpixels, h * stride * 4);
642 (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
644 gr->pattern = cairo_surface_create_for_image (gr->pattern_pixels,
645 CAIRO_FORMAT_ARGB32,
646 w, h, stride * 4);
647 g_assert (gr->pattern != NULL);
648 cairo_surface_set_repeat (gr->pattern, 1);
649 cairo_set_pattern (gr->cr, gr->pattern);
653 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels
654 (JNIEnv *env, jobject obj, jintArray java_pixels,
655 jint w, jint h, jint stride, jdoubleArray java_matrix)
657 struct graphics2d *gr = NULL;
658 jint *native_pixels = NULL;
659 jdouble *native_matrix = NULL;
661 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
662 g_assert (gr != NULL);
664 if (gr->debug) printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n",
665 (*env)->GetArrayLength (env, java_pixels), w, h, stride);
667 native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL);
668 native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
669 g_assert (native_pixels != NULL);
670 g_assert (native_matrix != NULL);
671 g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
673 begin_drawing_operation (gr);
676 cairo_matrix_t *mat = NULL;
677 cairo_surface_t *surf = cairo_surface_create_for_image ((char *)native_pixels,
678 CAIRO_FORMAT_ARGB32,
679 w, h, stride * 4);
680 mat = cairo_matrix_create ();
681 cairo_matrix_set_affine (mat,
682 native_matrix[0], native_matrix[1],
683 native_matrix[2], native_matrix[3],
684 native_matrix[4], native_matrix[5]);
685 cairo_surface_set_matrix (surf, mat);
686 if (native_matrix[0] != 1.
687 || native_matrix[1] != 0.
688 || native_matrix[2] != 0.
689 || native_matrix[3] != 1.)
691 cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
692 cairo_surface_set_filter (gr->surface, CAIRO_FILTER_BILINEAR);
694 else
696 cairo_surface_set_filter (surf, CAIRO_FILTER_FAST);
697 cairo_surface_set_filter (gr->surface, CAIRO_FILTER_FAST);
699 cairo_show_surface (gr->cr, surf, w, h);
700 cairo_surface_set_filter (gr->surface, CAIRO_FILTER_FAST);
701 cairo_matrix_destroy (mat);
702 cairo_surface_destroy (surf);
705 end_drawing_operation (gr);
707 (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0);
708 (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
712 /* passthrough methods to cairo */
714 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave
715 (JNIEnv *env, jobject obj)
717 struct graphics2d *gr = NULL;
718 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
719 g_assert (gr != NULL);
720 if (gr->debug) printf ("cairo_save\n");
721 cairo_save (gr->cr);
724 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore
725 (JNIEnv *env, jobject obj)
727 struct graphics2d *gr = NULL;
728 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
729 g_assert (gr != NULL);
730 if (gr->debug) printf ("cairo_restore\n");
731 cairo_restore (gr->cr);
732 update_pattern_transform (gr);
735 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix
736 (JNIEnv *env, jobject obj, jdoubleArray java_matrix)
738 struct graphics2d *gr = NULL;
739 jdouble *native_matrix = NULL;
741 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
742 g_assert (gr != NULL);
744 native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
745 g_assert (native_matrix != NULL);
746 g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
748 if (gr->debug) printf ("cairo_set_matrix [ %f, %f, %f, %f, %f, %f ]\n",
749 native_matrix[0], native_matrix[1],
750 native_matrix[2], native_matrix[3],
751 native_matrix[4], native_matrix[5]);
754 cairo_matrix_t * mat = cairo_matrix_create ();
755 cairo_matrix_set_affine (mat,
756 native_matrix[0], native_matrix[1],
757 native_matrix[2], native_matrix[3],
758 native_matrix[4], native_matrix[5]);
759 cairo_set_matrix (gr->cr, mat);
760 cairo_matrix_destroy (mat);
763 (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
764 update_pattern_transform (gr);
767 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont
768 (JNIEnv *env, jobject obj, jobject font)
770 struct graphics2d *gr = NULL;
771 struct peerfont *pfont = NULL;
772 cairo_font_t *ft = NULL;
773 FT_Face face = NULL;
775 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
776 g_assert (gr != NULL);
778 pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
779 g_assert (pfont != NULL);
781 gdk_threads_enter ();
783 face = pango_ft2_font_get_face (pfont->font);
784 g_assert (face != NULL);
786 ft = cairo_ft_font_create_for_ft_face (face);
787 g_assert (ft != NULL);
789 if (gr->debug) printf ("cairo_set_font '%s'\n", face->family_name);
791 cairo_set_font (gr->cr, ft);
793 cairo_scale_font (gr->cr,
794 pango_font_description_get_size (pfont->desc) /
795 (double)PANGO_SCALE);
797 cairo_font_destroy (ft);
799 gdk_threads_leave ();
802 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs
803 (JNIEnv *env, jobject obj, jintArray java_codes, jfloatArray java_posns)
805 struct graphics2d *gr = NULL;
806 cairo_glyph_t *glyphs = NULL;
807 jfloat *native_posns = NULL;
808 jint *native_codes = NULL;
809 jint i;
810 jint ncodes, nposns;
812 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
813 g_assert (gr != NULL);
815 native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL);
816 native_posns = (*env)->GetFloatArrayElements (env, java_posns, NULL);
817 g_assert (native_codes != NULL);
818 g_assert (native_posns != NULL);
820 ncodes = (*env)->GetArrayLength (env, java_codes);
821 nposns = (*env)->GetArrayLength (env, java_posns);
822 g_assert (2 * ncodes == nposns);
824 if (gr->debug) printf ("cairo_show_glyphs (%d glyphs)\n", ncodes);
826 glyphs = malloc (sizeof(cairo_glyph_t) * ncodes);
827 g_assert (glyphs);
829 for (i = 0; i < ncodes; ++i)
831 glyphs[i].index = native_codes[i];
832 glyphs[i].x = (double) native_posns[2*i];
833 glyphs[i].y = (double) native_posns[2*i + 1];
834 if (gr->debug) printf ("cairo_show_glyphs (glyph %d (code %d) : %f,%f)\n",
835 i, glyphs[i].index, glyphs[i].x, glyphs[i].y);
838 (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
839 (*env)->ReleaseFloatArrayElements (env, java_posns, native_posns, 0);
841 begin_drawing_operation (gr);
842 cairo_show_glyphs (gr->cr, glyphs, ncodes);
843 end_drawing_operation (gr);
845 free(glyphs);
848 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator
849 (JNIEnv *env, jobject obj, jint op)
851 struct graphics2d *gr = NULL;
852 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
853 g_assert (gr != NULL);
854 if (gr->debug) printf ("cairo_set_operator %d\n", op);
855 switch ((enum java_awt_alpha_composite_rule) op)
857 case java_awt_alpha_composite_CLEAR:
858 cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR);
859 break;
861 case java_awt_alpha_composite_SRC:
862 cairo_set_operator (gr->cr, CAIRO_OPERATOR_SRC);
863 break;
865 case java_awt_alpha_composite_SRC_OVER:
866 cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER);
867 break;
869 case java_awt_alpha_composite_DST_OVER:
870 cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER_REVERSE);
871 break;
873 case java_awt_alpha_composite_SRC_IN:
874 cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN);
875 break;
877 case java_awt_alpha_composite_DST_IN:
878 cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN_REVERSE);
879 break;
881 case java_awt_alpha_composite_SRC_OUT:
882 cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT);
883 break;
885 case java_awt_alpha_composite_DST_OUT:
886 cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT_REVERSE);
887 break;
889 case java_awt_alpha_composite_DST:
890 cairo_set_operator (gr->cr, CAIRO_OPERATOR_DST);
891 break;
893 case java_awt_alpha_composite_SRC_ATOP:
894 cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP);
895 break;
897 case java_awt_alpha_composite_DST_ATOP:
898 cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP_REVERSE);
899 break;
901 case java_awt_alpha_composite_XOR:
902 cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR);
903 break;
907 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBColor
908 (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b)
910 struct graphics2d *gr = NULL;
911 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
912 g_assert (gr != NULL);
914 /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider
915 colors in opposite pixel order. I have no idea why. thus when you
916 draw to a PixBuf, you must exchange the R and B components of your
917 color. */
919 if (gr->debug) printf ("cairo_set_rgb_color (%f, %f, %f)\n", r, g, b);
921 if (gr->drawbuf)
922 cairo_set_rgb_color (gr->cr, b, g, r);
923 else
924 cairo_set_rgb_color (gr->cr, r, g, b);
927 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetAlpha
928 (JNIEnv *env, jobject obj, jdouble a)
930 struct graphics2d *gr = NULL;
931 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
932 g_assert (gr != NULL);
933 if (gr->debug) printf ("cairo_set_alpha %f\n", a);
934 cairo_set_alpha (gr->cr, a);
937 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule
938 (JNIEnv *env, jobject obj, jint rule)
940 struct graphics2d *gr = NULL;
941 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
942 if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule);
943 g_assert (gr != NULL);
944 switch ((enum java_awt_geom_path_iterator_winding_rule) rule)
946 case java_awt_geom_path_iterator_WIND_NON_ZERO:
947 cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING);
948 break;
949 case java_awt_geom_path_iterator_WIND_EVEN_ODD:
950 cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD);
951 break;
955 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth
956 (JNIEnv *env, jobject obj, jdouble width)
958 struct graphics2d *gr = NULL;
959 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
960 g_assert (gr != NULL);
961 if (gr->debug) printf ("cairo_set_line_width %f\n", width);
962 cairo_set_line_width (gr->cr, width);
965 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap
966 (JNIEnv *env, jobject obj, jint cap)
968 struct graphics2d *gr = NULL;
969 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
970 g_assert (gr != NULL);
971 if (gr->debug) printf ("cairo_set_line_cap %d\n", cap);
972 switch ((enum java_awt_basic_stroke_cap_rule) cap)
974 case java_awt_basic_stroke_CAP_BUTT:
975 cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT);
976 break;
978 case java_awt_basic_stroke_CAP_ROUND:
979 cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND);
980 break;
982 case java_awt_basic_stroke_CAP_SQUARE:
983 cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE);
984 break;
988 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin
989 (JNIEnv *env, jobject obj, jint join)
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_line_join %d\n", join);
995 switch ((enum java_awt_basic_stroke_join_rule) join)
997 case java_awt_basic_stroke_JOIN_MITER:
998 cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER);
999 break;
1001 case java_awt_basic_stroke_JOIN_ROUND:
1002 cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND);
1003 break;
1005 case java_awt_basic_stroke_JOIN_BEVEL:
1006 cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL);
1007 break;
1011 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash
1012 (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset)
1014 struct graphics2d *gr = NULL;
1015 jdouble *dasharr = NULL;
1016 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1017 g_assert (gr != NULL);
1018 if (gr->debug) printf ("cairo_set_dash\n");
1019 dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL);
1020 g_assert (dasharr != NULL);
1021 cairo_set_dash (gr->cr, dasharr, ndash, offset);
1022 (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0);
1025 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit
1026 (JNIEnv *env, jobject obj, jdouble miter)
1028 struct graphics2d *gr = NULL;
1029 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1030 g_assert (gr != NULL);
1031 if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter);
1032 cairo_set_miter_limit (gr->cr, miter);
1036 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath
1037 (JNIEnv *env, jobject obj)
1039 struct graphics2d *gr = NULL;
1040 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1041 g_assert (gr != NULL);
1042 if (gr->debug) printf ("cairo_new_path\n");
1043 cairo_new_path (gr->cr);
1046 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo
1047 (JNIEnv *env, jobject obj, jdouble x, jdouble y)
1049 struct graphics2d *gr = NULL;
1050 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1051 g_assert (gr != NULL);
1052 if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y);
1053 cairo_move_to (gr->cr, x, y);
1056 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo
1057 (JNIEnv *env, jobject obj, jdouble x, jdouble y)
1059 struct graphics2d *gr = NULL;
1060 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1061 g_assert (gr != NULL);
1062 if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y);
1063 cairo_line_to (gr->cr, x, y);
1066 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo
1067 (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3)
1069 struct graphics2d *gr = NULL;
1070 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1071 g_assert (gr != NULL);
1072 if (gr->debug) printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", x1, y1, x2, y2, x3, y3);
1073 cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3);
1076 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo
1077 (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
1079 struct graphics2d *gr = NULL;
1080 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1081 g_assert (gr != NULL);
1082 if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy);
1083 cairo_rel_move_to (gr->cr, dx, dy);
1086 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo
1087 (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
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_rel_line_to (%f, %f)\n", dx, dy);
1093 cairo_rel_line_to (gr->cr, dx, dy);
1096 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo
1097 (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3)
1099 struct graphics2d *gr = NULL;
1100 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1101 g_assert (gr != NULL);
1102 if (gr->debug) printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", dx1, dy1, dx2, dy2, dx3, dy3);
1103 cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3);
1106 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle
1107 (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height)
1109 struct graphics2d *gr = NULL;
1110 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1111 g_assert (gr != NULL);
1112 if (gr->debug) printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height);
1113 cairo_rectangle (gr->cr, x, y, width, height);
1116 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath
1117 (JNIEnv *env, jobject obj)
1119 struct graphics2d *gr = NULL;
1120 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1121 g_assert (gr != NULL);
1122 if (gr->debug) printf ("cairo_close_path\n");
1123 cairo_close_path (gr->cr);
1126 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke
1127 (JNIEnv *env, jobject obj)
1129 struct graphics2d *gr = NULL;
1130 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1131 g_assert (gr != NULL);
1132 if (gr->debug) printf ("cairo_stroke\n");
1133 begin_drawing_operation (gr);
1134 cairo_stroke (gr->cr);
1135 end_drawing_operation (gr);
1138 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill
1139 (JNIEnv *env, jobject obj)
1141 struct graphics2d *gr = NULL;
1142 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1143 g_assert (gr != NULL);
1144 if (gr->debug) printf ("cairo_fill\n");
1145 begin_drawing_operation (gr);
1146 cairo_fill (gr->cr);
1147 end_drawing_operation (gr);
1150 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip
1151 (JNIEnv *env, jobject obj)
1153 struct graphics2d *gr = NULL;
1154 gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
1155 g_assert (gr != NULL);
1156 if (gr->debug) printf ("cairo_clip\n");
1157 cairo_clip (gr->cr);