1 /* gnu_java_awt_peer_gtk_ComponentGraphics.c
2    Copyright (C) 2006, 2007 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 <gdk/gdktypes.h>
41 #include <gdk/gdkprivate.h>
42 
43 #include <gdk-pixbuf/gdk-pixbuf.h>
44 #include <gdk-pixbuf/gdk-pixdata.h>
45 
46 #include <cairo-ft.h>
47 
48 #include <stdio.h>
49 #include <stdlib.h>
50 
51 #if HAVE_XRENDER
52 #include <gdk/gdkx.h>
53 #include <X11/extensions/Xrender.h>
54 #endif
55 
56 #include "gnu_java_awt_peer_gtk_ComponentGraphics.h"
57 
58 #include "cairographics2d.h"
59 
60 static short flush_scheduled = 0;
61 
flush(gpointer data)62 static gboolean flush (gpointer data __attribute__((unused)))
63 {
64   gdk_threads_enter ();
65 
66   gdk_display_flush (gdk_display_get_default ());
67   flush_scheduled = 0;
68 
69   gdk_threads_leave ();
70 
71   return FALSE;
72 }
73 
74 /* The minimum time period between calls to XFlush, in
75    milliseconds. */
76 #define MINIMUM_FLUSH_PERIOD 20
77 
78 /* schedule_flush must be called with the GDK lock held. */
79 static void
schedule_flush()80 schedule_flush ()
81 {
82   if (!flush_scheduled)
83     {
84       g_timeout_add (MINIMUM_FLUSH_PERIOD, flush, NULL);
85       flush_scheduled = 1;
86     }
87 }
88 
cp_gtk_grab_current_drawable(GtkWidget * widget,GdkDrawable ** draw,GdkWindow ** win)89 void cp_gtk_grab_current_drawable(GtkWidget *widget, GdkDrawable **draw,
90 				  GdkWindow **win)
91 {
92   g_assert (widget != NULL);
93   g_assert (draw != NULL);
94   g_assert (win != NULL);
95 
96   *win = widget->window;
97 
98   *draw = *win;
99   gdk_window_get_internal_paint_info (*win, draw, 0, 0);
100 }
101 
102 /**
103  * Returns whether the XRender extension is supported
104  */
105 JNIEXPORT jboolean JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender(JNIEnv * env,jclass cls)106 Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender
107   (JNIEnv *env __attribute__ ((unused)), jclass cls __attribute__ ((unused)))
108 {
109 #if HAVE_XRENDER
110   int ev = 0, err = 0;
111   if( XRenderQueryExtension (GDK_DISPLAY(), &ev, &err) )
112     return JNI_TRUE;
113 #endif
114   return JNI_FALSE;
115 }
116 
117 
118 JNIEXPORT jlong JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState(JNIEnv * env,jobject obj,jobject peer)119 Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState
120   (JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer)
121 {
122   GdkDrawable *drawable;
123   GtkWidget *widget;
124   cairo_t *cr;
125   void *ptr;
126 
127   gdk_threads_enter();
128 
129   ptr = gtkpeer_get_widget (env, peer);
130   g_assert (ptr != NULL);
131 
132   widget = GTK_WIDGET (ptr);
133   g_assert (widget != NULL);
134 
135   drawable = widget->window;
136   g_assert (drawable != NULL);
137 
138   cr = gdk_cairo_create(drawable);
139 
140   g_assert(cr != NULL);
141 
142   gdk_threads_leave();
143 
144   return PTR_TO_JLONG(cr);
145 }
146 
147 JNIEXPORT jlong JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_initFromVolatile(JNIEnv * env,jobject obj,jlong ptr)148 Java_gnu_java_awt_peer_gtk_ComponentGraphics_initFromVolatile
149   (JNIEnv *env  __attribute__ ((unused)), jobject obj __attribute__ ((unused)),
150    jlong ptr)
151 {
152   GdkDrawable *drawable;
153   cairo_t *cr;
154 
155   gdk_threads_enter();
156 
157   drawable = JLONG_TO_PTR(GdkDrawable, ptr);
158   g_assert (drawable != NULL);
159 
160   cr = gdk_cairo_create (drawable);
161   g_assert(cr != NULL);
162 
163   gdk_threads_leave();
164 
165   return PTR_TO_JLONG(cr);
166 }
167 
168 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing(JNIEnv * env,jobject obj)169 Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing
170   (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)))
171 {
172   gdk_threads_enter();
173 }
174 
175 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing(JNIEnv * env,jobject obj)176 Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing
177   (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)))
178 {
179   schedule_flush ();
180   gdk_threads_leave();
181 }
182 
183 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative(JNIEnv * env,jobject obj,jobject peer,jint x,jint y,jint w,jint h,jint dx,jint dy)184 Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative
185   (JNIEnv *env, jobject obj __attribute__((unused)), jobject peer,
186    jint x, jint y, jint w, jint h, jint dx, jint dy)
187 {
188   GdkPixbuf *pixbuf;
189   GdkDrawable *drawable;
190   GdkWindow *win;
191   GtkWidget *widget = NULL;
192   void *ptr = NULL;
193 
194   gdk_threads_enter();
195 
196   ptr = gtkpeer_get_widget (env, peer);
197   g_assert (ptr != NULL);
198 
199   widget = GTK_WIDGET (ptr);
200   g_assert (widget != NULL);
201 
202   cp_gtk_grab_current_drawable (widget, &drawable, &win);
203   g_assert (drawable != NULL);
204 
205   pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h );
206   gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, x, y, 0, 0, w, h );
207   gdk_draw_pixbuf (drawable, NULL, pixbuf,
208 		   0, 0, x + dx, y + dy,
209 		   w, h,
210 		   GDK_RGB_DITHER_NORMAL, 0, 0);
211   gdk_threads_leave();
212 }
213 
214 JNIEXPORT jobject JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_nativeGrab(JNIEnv * env,jclass cls,jobject peer)215 Java_gnu_java_awt_peer_gtk_ComponentGraphics_nativeGrab
216 (JNIEnv *env, jclass cls __attribute__((unused)), jobject peer )
217 {
218   GdkPixbuf *pixbuf;
219   GdkDrawable *drawable;
220   GdkWindow *win;
221   gint w,h;
222   GtkWidget *widget = NULL;
223   void *ptr = NULL;
224 
225   gdk_threads_enter();
226 
227   ptr = gtkpeer_get_widget (env, peer);
228   g_assert (ptr != NULL);
229 
230   widget = GTK_WIDGET (ptr);
231   g_assert (widget != NULL);
232 
233   cp_gtk_grab_current_drawable (widget, &drawable, &win);
234   g_assert (drawable != NULL);
235 
236   gdk_drawable_get_size ( drawable, &w, &h );
237 
238   pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h );
239   gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, 0, 0, 0, 0, w, h );
240   g_object_ref( pixbuf );
241   gdk_draw_pixbuf (drawable, NULL, pixbuf,
242 		   0, 0, 0, 0,
243 		   w, h,
244 		   GDK_RGB_DITHER_NORMAL, 0, 0);
245   gdk_threads_leave();
246 
247   return JCL_NewRawDataObject (env, pixbuf);
248 }
249 
250 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile(JNIEnv * env,jobject obj,jobject peer,jlong img,jint x,jint y,jint w,jint h,jint cx,jint cy,jint cw,jint ch)251 Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile
252 (JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer,
253  jlong img, jint x, jint y, jint w, jint h, jint cx, jint cy, jint cw, jint ch)
254 {
255   GdkPixmap *pixmap;
256   GtkWidget *widget = NULL;
257   GdkGC *gc;
258   GdkRectangle clip;
259   void *ptr;
260 
261   gdk_threads_enter();
262 
263   ptr = gtkpeer_get_widget (env, peer);
264   g_assert (ptr != NULL);
265 
266   widget = GTK_WIDGET (ptr);
267   g_assert (widget != NULL);
268 
269   pixmap = JLONG_TO_PTR(GdkPixmap, img);
270 
271   gc = gdk_gc_new(widget->window);
272 
273   clip.x = cx;
274   clip.y = cy;
275   clip.width = cw;
276   clip.height = ch;
277   gdk_gc_set_clip_rectangle(gc, &clip);
278 
279   gdk_draw_drawable(widget->window,
280 		    gc,
281 		    pixmap,
282 		    0, 0,
283 		    x, y,
284 		    w, h);
285 
286   g_object_unref( gc );
287 
288   schedule_flush ();
289 
290   gdk_threads_leave();
291 }
292