Merge from mainline
[official-gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GdkGraphics.c
blobf6e0e6bda15b43ca416179ad988173a3916a3ee6
1 /* gdkgraphics.c
2 Copyright (C) 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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_GdkGraphics.h"
41 #include <gdk/gdkprivate.h>
42 #include <gdk/gdkx.h>
44 static jmethodID initComponentGraphicsUnlockedID;
46 void
47 cp_gtk_graphics_init_jni (void)
49 jclass gdkgraphics;
51 gdkgraphics = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
52 "gnu/java/awt/peer/gtk/GdkGraphics");
54 initComponentGraphicsUnlockedID =
55 (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gdkgraphics,
56 "initComponentGraphicsUnlocked",
57 "()V");
60 struct state_table *cp_gtk_native_graphics_state_table;
62 static struct state_table *native_graphics_global_ref_table;
64 #define NSA_GLOBAL_G_INIT(env, clazz) \
65 native_graphics_global_ref_table = cp_gtk_init_state_table (env, clazz)
67 #define NSA_GET_GLOBAL_G_REF(env, obj) \
68 cp_gtk_get_state (env, obj, native_graphics_global_ref_table)
70 #define NSA_SET_GLOBAL_G_REF(env, obj) \
71 do {jobject *globRefPtr; \
72 globRefPtr = (jobject *) malloc (sizeof (jobject)); \
73 *globRefPtr = (*env)->NewGlobalRef (env, obj); \
74 cp_gtk_set_state (env, obj, native_graphics_global_ref_table, (void *)globRefPtr);} while (0)
76 #define NSA_DEL_GLOBAL_G_REF(env, obj) \
77 do {jobject *globRefPtr = cp_gtk_get_state (env, obj, native_graphics_global_ref_table); \
78 cp_gtk_remove_state_slot (env, obj, native_graphics_global_ref_table); \
79 (*env)->DeleteGlobalRef (env, *globRefPtr); \
80 free (globRefPtr);} while (0)
82 JNIEXPORT void JNICALL
83 Java_gnu_java_awt_peer_gtk_GdkGraphics_initStaticState
84 (JNIEnv *env, jclass clazz)
86 gdk_threads_enter();
88 NSA_G_INIT (env, clazz);
89 NSA_GLOBAL_G_INIT (env, clazz);
91 gdk_threads_leave();
94 #define GDK_STABLE_IS_PIXMAP(d) (GDK_IS_PIXMAP(d))
96 static GdkPoint *translate_points (JNIEnv *env, jintArray xpoints,
97 jintArray ypoints, jint npoints,
98 jint x_offset, jint y_offset);
99 static void realize_cb (GtkWidget *widget, jobject jgraphics);
101 JNIEXPORT void JNICALL
102 Java_gnu_java_awt_peer_gtk_GdkGraphics_nativeCopyState
103 (JNIEnv *env, jobject obj, jobject old)
105 struct graphics *g = NULL;
106 struct graphics *g_old = NULL;
108 gdk_threads_enter ();
110 g = (struct graphics *) g_malloc (sizeof (struct graphics));
111 g_old = (struct graphics *) NSA_GET_G_PTR (env, old);
113 *g = *g_old;
115 g->gc = gdk_gc_new (g->drawable);
116 gdk_gc_copy (g->gc, g_old->gc);
118 if (GDK_STABLE_IS_PIXMAP (g->drawable))
119 g_object_ref (g->drawable);
120 else /* GDK_IS_WINDOW (g->drawable) */
121 g_object_ref (g->drawable);
123 g_object_ref (g->cm);
125 NSA_SET_G_PTR (env, obj, g);
127 gdk_threads_leave ();
130 JNIEXPORT void JNICALL
131 Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__II
132 (JNIEnv *env, jobject obj, jint width, jint height)
134 struct graphics *g = NULL;
136 gdk_threads_enter ();
138 g = (struct graphics *) g_malloc (sizeof (struct graphics));
139 g->x_offset = g->y_offset = 0;
141 g->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height,
142 gdk_rgb_get_visual ()->depth);
143 g->cm = gdk_rgb_get_colormap ();
144 g_object_ref (g->cm);
145 g->gc = gdk_gc_new (g->drawable);
147 NSA_SET_G_PTR (env, obj, g);
149 gdk_threads_leave ();
152 JNIEXPORT void JNICALL
153 Java_gnu_java_awt_peer_gtk_GdkGraphics_initFromImage
154 (JNIEnv *env, jobject obj, jobject source)
156 struct graphics *g = NULL;
157 GdkPixmap *pixmap = NULL;
159 gdk_threads_enter ();
161 pixmap = cp_gtk_image_get_pixmap (env, source);
162 g_assert(pixmap != NULL);
163 g_object_ref (pixmap);
165 g = (struct graphics *) g_malloc (sizeof (struct graphics));
166 g->x_offset = g->y_offset = 0;
168 g->drawable = (GdkDrawable *)pixmap;
170 g->cm = gdk_drawable_get_colormap (g->drawable);
171 g_object_ref (g->cm);
172 g->gc = gdk_gc_new (g->drawable);
174 NSA_SET_G_PTR (env, obj, g);
176 gdk_threads_leave ();
179 JNIEXPORT void JNICALL
180 Java_gnu_java_awt_peer_gtk_GdkGraphics_initStateUnlocked
181 (JNIEnv *env, jobject obj, jobject peer)
183 struct graphics *g = NULL;
184 void *ptr = NULL;
185 GtkWidget *widget = NULL;
186 GdkColor color;
188 g = (struct graphics *) g_malloc (sizeof (struct graphics));
189 ptr = NSA_GET_PTR (env, peer);
190 g->x_offset = 0;
191 g->y_offset = 0;
193 widget = GTK_WIDGET (ptr);
194 g->drawable = (GdkDrawable *) widget->window;
196 g_object_ref (g->drawable);
197 g->cm = gtk_widget_get_colormap (widget);
198 g_object_ref (g->cm);
199 g->gc = gdk_gc_new (g->drawable);
200 gdk_gc_copy (g->gc, widget->style->fg_gc[GTK_STATE_NORMAL]);
201 color = widget->style->fg[GTK_STATE_NORMAL];
203 NSA_SET_G_PTR (env, obj, g);
206 /* copy the native state of the peer (GtkWidget *) to the native state
207 of the graphics object */
208 JNIEXPORT void JNICALL
209 Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
210 (JNIEnv *env, jobject obj, jobject peer)
212 gdk_threads_enter ();
213 Java_gnu_java_awt_peer_gtk_GdkGraphics_initStateUnlocked
214 (env, obj, peer);
215 gdk_threads_leave ();
218 JNIEXPORT void JNICALL
219 Java_gnu_java_awt_peer_gtk_GdkGraphics_connectSignals
220 (JNIEnv *env, jobject obj, jobject peer)
222 void *ptr = NULL;
223 jobject *gref = NULL;
225 gdk_threads_enter ();
227 NSA_SET_GLOBAL_G_REF (env, obj);
228 gref = NSA_GET_GLOBAL_G_REF (env, obj);
230 ptr = NSA_GET_PTR (env, peer);
232 g_signal_connect_after (G_OBJECT (ptr), "realize",
233 G_CALLBACK (realize_cb), *gref);
235 gdk_threads_leave ();
238 JNIEXPORT void JNICALL
239 Java_gnu_java_awt_peer_gtk_GdkGraphics_nativeDispose
240 (JNIEnv *env, jobject obj)
242 struct graphics *g = NULL;
244 gdk_threads_enter ();
246 g = (struct graphics *) NSA_DEL_G_PTR (env, obj);
248 /* check if dispose has been called already */
249 if (!g)
251 gdk_threads_leave ();
252 return;
255 XFlush (GDK_DISPLAY ());
257 g_object_unref (g->gc);
259 if (GDK_STABLE_IS_PIXMAP (g->drawable))
260 g_object_unref (g->drawable);
261 else /* GDK_IS_WINDOW (g->drawable) */
262 g_object_unref (g->drawable);
264 g_object_unref (g->cm);
266 g_free (g);
268 gdk_threads_leave ();
271 JNIEXPORT void JNICALL
272 Java_gnu_java_awt_peer_gtk_GdkGraphics_translateNative
273 (JNIEnv *env, jobject obj, jint x, jint y)
275 struct graphics *g = NULL;
277 gdk_threads_enter ();
279 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
281 g->x_offset += x;
282 g->y_offset += y;
284 gdk_threads_leave ();
287 JNIEXPORT void JNICALL
288 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawString
289 (JNIEnv *env, jobject obj, jobject font, jstring str, jint x, jint y)
291 struct peerfont *pfont = NULL;
292 struct graphics *g = NULL;
293 const char *cstr = NULL;
294 const char *sTmp = NULL;
295 char *tmp = NULL;
296 char *p = NULL;
297 int count = 0;
298 int charSize = 0;
299 int baseline_y = 0;
300 PangoLayoutIter *iter = NULL;
302 gdk_threads_enter ();
304 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
305 g_assert (g != NULL);
307 pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
308 g_assert (pfont != NULL);
310 cstr = (*env)->GetStringUTFChars (env, str, NULL);
311 g_assert (cstr != NULL);
313 charSize = sizeof(char);
314 p = malloc((strlen(cstr) + 1) * charSize);
315 g_assert (p != NULL);
317 tmp = p;
318 sTmp = cstr;
319 for (; *sTmp != '\0'; sTmp++)
320 if (((unsigned char) *sTmp) >= ' ')
322 *p = *sTmp;
323 count++;
324 p++;
326 *p = '\0';
328 p = realloc(tmp, (count + 1) * charSize);
329 g_assert (p != NULL);
330 pango_layout_set_text (pfont->layout, p, -1);
331 free(p);
333 pango_layout_set_font_description (pfont->layout, pfont->desc);
334 iter = pango_layout_get_iter (pfont->layout);
336 baseline_y = pango_layout_iter_get_baseline (iter);
338 gdk_draw_layout (g->drawable, g->gc,
339 x + g->x_offset,
340 y + g->y_offset - PANGO_PIXELS (baseline_y),
341 pfont->layout);
343 pango_layout_iter_free (iter);
344 pango_layout_set_text (pfont->layout, "", -1);
346 gdk_flush ();
348 (*env)->ReleaseStringUTFChars (env, str, cstr);
350 gdk_threads_leave ();
353 JNIEXPORT void JNICALL
354 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawLine
355 (JNIEnv *env, jobject obj, jint x, jint y, jint x2, jint y2)
357 struct graphics *g = NULL;
359 gdk_threads_enter ();
361 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
363 gdk_draw_line (g->drawable, g->gc,
364 x + g->x_offset, y + g->y_offset,
365 x2 + g->x_offset, y2 + g->y_offset);
366 gdk_flush ();
368 gdk_threads_leave ();
371 JNIEXPORT void JNICALL
372 Java_gnu_java_awt_peer_gtk_GdkGraphics_fillRect
373 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
375 struct graphics *g = NULL;
377 gdk_threads_enter ();
379 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
381 gdk_draw_rectangle (g->drawable, g->gc, TRUE,
382 x + g->x_offset, y + g->y_offset, width, height);
383 gdk_flush ();
385 gdk_threads_leave ();
388 JNIEXPORT void JNICALL
389 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawRect
390 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
392 struct graphics *g = NULL;
394 gdk_threads_enter ();
396 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
398 gdk_draw_rectangle (g->drawable, g->gc, FALSE,
399 x + g->x_offset, y + g->y_offset, width, height);
400 gdk_flush ();
402 gdk_threads_leave ();
405 JNIEXPORT void JNICALL
406 Java_gnu_java_awt_peer_gtk_GdkGraphics_copyArea
407 (JNIEnv *env, jobject obj, jint x, jint y,
408 jint width, jint height, jint dx, jint dy)
410 struct graphics *g = NULL;
412 gdk_threads_enter ();
414 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
416 gdk_draw_drawable ((GdkWindow *)g->drawable,
417 g->gc,
418 (GdkWindow *)g->drawable,
419 x + g->x_offset, y + g->y_offset,
420 x + g->x_offset + dx, y + g->y_offset + dy,
421 width, height);
422 gdk_flush ();
424 gdk_threads_leave ();
427 JNIEXPORT void JNICALL
428 Java_gnu_java_awt_peer_gtk_GdkGraphics_clearRect
429 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
431 struct graphics *g = NULL;
432 GdkGCValues saved;
433 GtkWidget *widget = NULL;
434 union widget_union w;
436 gdk_threads_enter ();
438 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
440 if (!g)
442 gdk_threads_leave ();
443 return;
446 if (GDK_IS_WINDOW (g->drawable))
448 w.widget = &widget;
449 gdk_window_get_user_data (GDK_WINDOW (g->drawable), w.void_widget);
450 if (widget == NULL || !GTK_IS_EVENT_BOX (widget))
451 gdk_window_clear_area ((GdkWindow *) g->drawable,
452 x + g->x_offset, y + g->y_offset,
453 width, height);
455 else
457 gdk_gc_get_values (g->gc, &saved);
458 gdk_gc_set_foreground (g->gc, &(saved.background));
459 gdk_draw_rectangle (g->drawable, g->gc, TRUE,
460 x + g->x_offset, y + g->y_offset, width, height);
461 gdk_gc_set_foreground (g->gc, &(saved.foreground));
464 gdk_flush ();
466 gdk_threads_leave ();
469 JNIEXPORT void JNICALL
470 Java_gnu_java_awt_peer_gtk_GdkGraphics_setFunction
471 (JNIEnv *env, jobject obj, jint func)
473 struct graphics *g = NULL;
475 gdk_threads_enter ();
477 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
479 gdk_gc_set_function (g->gc, func);
481 gdk_threads_leave ();
485 JNIEXPORT void JNICALL
486 Java_gnu_java_awt_peer_gtk_GdkGraphics_setFGColor
487 (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
489 GdkColor color;
490 struct graphics *g = NULL;
492 gdk_threads_enter ();
494 color.red = red << 8;
495 color.green = green << 8;
496 color.blue = blue << 8;
498 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
500 gdk_colormap_alloc_color (g->cm, &color, TRUE, TRUE);
501 gdk_gc_set_foreground (g->gc, &color);
503 gdk_threads_leave ();
506 JNIEXPORT void JNICALL
507 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawArc
508 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height,
509 jint angle1, jint angle2)
511 struct graphics *g = NULL;
513 gdk_threads_enter ();
515 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
517 gdk_draw_arc (g->drawable, g->gc, FALSE,
518 x + g->x_offset, y + g->y_offset,
519 width, height, angle1 << 6, angle2 << 6);
520 gdk_flush ();
522 gdk_threads_leave ();
525 static GdkPoint *
526 translate_points (JNIEnv *env, jintArray xpoints, jintArray ypoints,
527 jint npoints, jint x_offset, jint y_offset)
529 GdkPoint *points;
530 jint *x, *y;
531 int i;
533 /* allocate one more point than necessary, in case we need to tack
534 on an extra due to the semantics of Java polygons. */
535 points = g_malloc (sizeof (GdkPoint) * (npoints + 1));
537 x = (*env)->GetIntArrayElements (env, xpoints, NULL);
538 y = (*env)->GetIntArrayElements (env, ypoints, NULL);
540 for (i = 0; i < npoints; i++)
542 points[i].x = x[i] + x_offset;
543 points[i].y = y[i] + y_offset;
546 (*env)->ReleaseIntArrayElements (env, xpoints, x, JNI_ABORT);
547 (*env)->ReleaseIntArrayElements (env, ypoints, y, JNI_ABORT);
549 return points;
552 JNIEXPORT void JNICALL
553 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawPolyline
554 (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints,
555 jint npoints)
557 struct graphics *g = NULL;
558 GdkPoint *points = NULL;
560 gdk_threads_enter ();
562 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
563 points = translate_points (env, xpoints, ypoints, npoints,
564 g->x_offset, g->y_offset);
566 gdk_draw_lines (g->drawable, g->gc, points, npoints);
567 gdk_flush ();
569 g_free (points);
571 gdk_threads_leave ();
574 JNIEXPORT void JNICALL
575 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawPolygon
576 (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints,
577 jint npoints)
579 struct graphics *g = NULL;
580 GdkPoint *points = NULL;
582 gdk_threads_enter ();
584 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
585 points = translate_points (env, xpoints, ypoints, npoints,
586 g->x_offset, g->y_offset);
588 /* make sure the polygon is closed, per Java semantics.
589 if it's not, we close it. */
590 if (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y)
591 points[npoints++] = points[0];
593 gdk_draw_lines (g->drawable, g->gc, points, npoints);
594 gdk_flush ();
596 g_free (points);
598 gdk_threads_leave ();
601 JNIEXPORT void JNICALL
602 Java_gnu_java_awt_peer_gtk_GdkGraphics_fillPolygon
603 (JNIEnv *env, jobject obj, jintArray xpoints, jintArray ypoints,
604 jint npoints)
606 struct graphics *g = NULL;
607 GdkPoint *points = NULL;
609 gdk_threads_enter ();
611 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
612 points = translate_points (env, xpoints, ypoints, npoints,
613 g->x_offset, g->y_offset);
614 gdk_draw_polygon (g->drawable, g->gc, TRUE, points, npoints);
615 gdk_flush ();
617 g_free (points);
619 gdk_threads_leave ();
622 JNIEXPORT void JNICALL
623 Java_gnu_java_awt_peer_gtk_GdkGraphics_fillArc
624 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height,
625 jint angle1, jint angle2)
627 struct graphics *g = NULL;
629 gdk_threads_enter ();
631 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
633 gdk_draw_arc (g->drawable, g->gc, TRUE,
634 x + g->x_offset, y + g->y_offset,
635 width, height, angle1 << 6, angle2 << 6);
636 gdk_flush ();
638 gdk_threads_leave ();
641 JNIEXPORT void JNICALL
642 Java_gnu_java_awt_peer_gtk_GdkGraphics_drawOval
643 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
645 struct graphics *g = NULL;
647 gdk_threads_enter ();
649 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
651 gdk_draw_arc (g->drawable, g->gc, FALSE,
652 x + g->x_offset, y + g->y_offset,
653 width, height, 0, 23040);
654 gdk_flush ();
656 gdk_threads_leave ();
659 JNIEXPORT void JNICALL
660 Java_gnu_java_awt_peer_gtk_GdkGraphics_fillOval
661 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
663 struct graphics *g = NULL;
665 gdk_threads_enter ();
667 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
669 gdk_draw_arc (g->drawable, g->gc, TRUE,
670 x + g->x_offset, y + g->y_offset,
671 width, height, 0, 23040);
672 gdk_flush ();
674 gdk_threads_leave ();
677 JNIEXPORT void JNICALL
678 Java_gnu_java_awt_peer_gtk_GdkGraphics_setClipRectangle
679 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
681 struct graphics *g = NULL;
682 GdkRectangle rectangle;
684 gdk_threads_enter ();
686 g = (struct graphics *) NSA_GET_G_PTR (env, obj);
688 rectangle.x = x + g->x_offset;
689 rectangle.y = y + g->y_offset;
690 rectangle.width = width;
691 rectangle.height = height;
693 gdk_gc_set_clip_rectangle (g->gc, &rectangle);
695 gdk_threads_leave ();
698 static void
699 realize_cb (GtkWidget *widget __attribute__ ((unused)), jobject jgraphics)
701 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(),
702 jgraphics,
703 initComponentGraphicsUnlockedID);
705 NSA_DEL_GLOBAL_G_REF (cp_gtk_gdk_env(), jgraphics);