OSDN Git Service

2006-08-14 Mark Wielaard <mark@klomp.org>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_ComponentGraphics.c
1 /* gnu_java_awt_peer_gtk_ComponentGraphics.c
2    Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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 "jcl.h"
39 #include "gtkpeer.h"
40 #include <cairo-xlib.h>
41 #include <gdk/gdktypes.h>
42 #include <gdk/gdkprivate.h>
43 #include <gdk/gdkx.h>
44 #include <X11/extensions/Xrender.h>
45
46 #include <gdk-pixbuf/gdk-pixbuf.h>
47 #include <gdk-pixbuf/gdk-pixdata.h>
48
49 #include <cairo-ft.h>
50 #include <cairo-xlib.h>
51
52 #include <stdio.h>
53 #include <stdlib.h>
54
55 #include "gnu_java_awt_peer_gtk_ComponentGraphics.h"
56
57 #include "cairographics2d.h"
58
59 static short flush_scheduled = 0;
60
61 static gboolean flush (gpointer data __attribute__((unused)))
62 {
63   gdk_threads_enter ();
64
65   XFlush (GDK_DISPLAY ());
66   flush_scheduled = 0;
67
68   gdk_threads_leave ();
69
70   return FALSE;
71 }
72
73 /* The minimum time period between calls to XFlush, in
74    milliseconds. */
75 #define MINIMUM_FLUSH_PERIOD 20
76
77 /* schedule_flush must be called with the GDK lock held. */
78 static void
79 schedule_flush ()
80 {
81   if (!flush_scheduled)
82     {
83       g_timeout_add (MINIMUM_FLUSH_PERIOD, flush, NULL);
84       flush_scheduled = 1;
85     }
86 }
87
88 void cp_gtk_grab_current_drawable(GtkWidget *widget, GdkDrawable **draw,
89                                   GdkWindow **win)
90 {
91   g_assert (widget != NULL);
92   g_assert (draw != NULL);
93   g_assert (win != NULL);
94
95   *win = widget->window;
96
97   *draw = *win;
98   gdk_window_get_internal_paint_info (*win, draw, 0, 0); 
99 }
100
101 /**
102  * Returns whether the XRender extension is supported
103  */
104 JNIEXPORT jboolean JNICALL 
105 Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender
106   (JNIEnv *env __attribute__ ((unused)), jclass cls __attribute__ ((unused)))
107 {
108 #if HAVE_XRENDER
109   int ev = 0, err = 0; 
110   if( XRenderQueryExtension (GDK_DISPLAY (), &ev, &err) )
111     return JNI_TRUE;
112 #endif
113   return JNI_FALSE;
114 }
115
116
117 JNIEXPORT jlong JNICALL 
118 Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState
119   (JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer)
120 {
121   Drawable draw;
122   Display * dpy;
123   Visual * vis;
124   GdkDrawable *drawable;
125   cairo_surface_t *surface;
126   GdkWindow *win;
127   GtkWidget *widget = NULL;
128   void *ptr = NULL;
129   int width, height;
130   cairo_t *cr;
131
132   gdk_threads_enter();
133
134   ptr = NSA_GET_PTR (env, peer);
135   g_assert (ptr != NULL);
136
137   widget = GTK_WIDGET (ptr);
138   g_assert (widget != NULL);
139
140   cp_gtk_grab_current_drawable (widget, &drawable, &win);
141   g_assert (drawable != NULL);
142
143   width = widget->allocation.width;
144   height = widget->allocation.height;
145
146   g_assert (drawable != NULL);
147
148   draw = gdk_x11_drawable_get_xid(drawable);
149   g_assert (draw != (XID) 0);
150   
151   dpy = gdk_x11_drawable_get_xdisplay(drawable);
152   g_assert (dpy != NULL);
153   
154   vis = gdk_x11_visual_get_xvisual(gdk_drawable_get_visual(drawable));
155   g_assert (vis != NULL);
156   
157   surface = cairo_xlib_surface_create (dpy, draw, vis, width, height);
158   g_assert (surface != NULL);
159
160   cr = cairo_create (surface);
161   g_assert(cr != NULL);
162
163   gdk_threads_leave();
164
165   return PTR_TO_JLONG(cr);
166 }
167
168 /**
169  * Disposes of the surface
170  */
171 JNIEXPORT void JNICALL
172 Java_gnu_java_awt_peer_gtk_ComponentGraphics_disposeSurface
173   (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
174    jlong value)
175 {
176   struct cairographics2d *gr;
177   cairo_surface_t *surface;
178
179   gr = JLONG_TO_PTR(struct cairographics2d, value);
180
181   if (gr == NULL)
182     return;
183
184   if (gr->cr == NULL)
185     return;
186
187   surface = cairo_get_target (gr->cr);
188   if (surface != NULL)
189     {
190       gdk_threads_enter();
191       cairo_surface_destroy (surface);
192       gdk_threads_leave();
193     }
194 }
195
196 JNIEXPORT jlong JNICALL 
197 Java_gnu_java_awt_peer_gtk_ComponentGraphics_initFromVolatile
198   (JNIEnv *env  __attribute__ ((unused)), jobject obj __attribute__ ((unused)),
199    jlong ptr, jint width, jint height)
200 {
201   Drawable draw;
202   Display * dpy;
203   Visual * vis;
204   GdkDrawable *drawable;
205   cairo_surface_t *surface;
206   cairo_t *cr;
207
208   gdk_threads_enter();
209
210   drawable = JLONG_TO_PTR(GdkDrawable, ptr);
211   g_assert (drawable != NULL);
212
213   draw = gdk_x11_drawable_get_xid(drawable);
214   g_assert (draw != (XID) 0);
215   
216   dpy = gdk_x11_drawable_get_xdisplay(drawable);
217   g_assert (dpy != NULL);
218   
219   vis = gdk_x11_visual_get_xvisual(gdk_drawable_get_visual(drawable));
220   g_assert (vis != NULL);
221   
222   surface = cairo_xlib_surface_create (dpy, draw, vis, width, height);
223   g_assert (surface != NULL);
224
225   cr = cairo_create (surface);
226   g_assert(cr != NULL);
227
228   gdk_threads_leave();
229
230   return PTR_TO_JLONG(cr);
231 }
232
233 JNIEXPORT void JNICALL 
234 Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing
235   (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)))
236 {
237   gdk_threads_enter();
238 }
239
240 JNIEXPORT void JNICALL 
241 Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing
242   (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)))
243 {
244   schedule_flush ();
245   gdk_threads_leave();
246 }
247
248 JNIEXPORT void JNICALL 
249 Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative
250   (JNIEnv *env, jobject obj __attribute__((unused)), jobject peer,
251    jint x, jint y, jint w, jint h, jint dx, jint dy)
252 {
253   GdkPixbuf *pixbuf;
254   GdkDrawable *drawable;
255   GdkWindow *win;
256   GtkWidget *widget = NULL;
257   void *ptr = NULL;
258
259   gdk_threads_enter();
260
261   ptr = NSA_GET_PTR (env, peer);
262   g_assert (ptr != NULL);
263
264   widget = GTK_WIDGET (ptr);
265   g_assert (widget != NULL);
266
267   cp_gtk_grab_current_drawable (widget, &drawable, &win);
268   g_assert (drawable != NULL);
269
270   pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h );
271   gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, x, y, 0, 0, w, h );
272   gdk_draw_pixbuf (drawable, NULL, pixbuf,
273                    0, 0, x + dx, y + dy, 
274                    w, h, 
275                    GDK_RGB_DITHER_NORMAL, 0, 0);
276   gdk_threads_leave();
277 }
278
279 JNIEXPORT jobject JNICALL 
280 Java_gnu_java_awt_peer_gtk_ComponentGraphics_nativeGrab
281 (JNIEnv *env, jclass cls __attribute__((unused)), jobject peer )
282 {
283   GdkPixbuf *pixbuf;
284   GdkDrawable *drawable;
285   GdkWindow *win;
286   gint w,h;
287   GtkWidget *widget = NULL;
288   void *ptr = NULL;
289   
290   gdk_threads_enter();
291
292   ptr = NSA_GET_PTR (env, peer);
293   g_assert (ptr != NULL);
294
295   widget = GTK_WIDGET (ptr);
296   g_assert (widget != NULL);
297
298   cp_gtk_grab_current_drawable (widget, &drawable, &win);
299   g_assert (drawable != NULL);
300
301   gdk_drawable_get_size ( drawable, &w, &h );
302
303   pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h );
304   gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, 0, 0, 0, 0, w, h );
305   g_object_ref( pixbuf );
306   gdk_draw_pixbuf (drawable, NULL, pixbuf,
307                    0, 0, 0, 0, 
308                    w, h, 
309                    GDK_RGB_DITHER_NORMAL, 0, 0);
310   gdk_threads_leave();
311
312   return JCL_NewRawDataObject (env, pixbuf);
313 }
314
315 JNIEXPORT void JNICALL 
316 Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile
317 (JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer, 
318  jlong img, jint x, jint y, jint w, jint h, jint cx, jint cy, jint cw, jint ch)
319 {
320   GdkPixmap *pixmap;
321   GtkWidget *widget = NULL;
322   void *ptr = NULL;
323   GdkGC *gc;
324   GdkRectangle clip;
325
326   gdk_threads_enter();
327   ptr = NSA_GET_PTR (env, peer);
328   g_assert (ptr != NULL);
329
330   widget = GTK_WIDGET (ptr);
331   g_assert (widget != NULL);
332
333   pixmap = JLONG_TO_PTR(GdkPixmap, img);
334  
335   gc = gdk_gc_new(widget->window);
336
337   clip.x = cx;
338   clip.y = cy;
339   clip.width = cw;
340   clip.height = ch;
341   gdk_gc_set_clip_rectangle(gc, &clip);
342
343   gdk_draw_drawable(widget->window,
344                     gc,
345                     pixmap,
346                     0, 0,
347                     x, y,
348                     w, h);
349
350   g_object_unref( gc );
351
352   schedule_flush ();
353
354   gdk_threads_leave();
355 }