diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-06-11 18:23:15 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-06-11 18:23:15 +0000 |
commit | 35d18ccf396a6cfdcbe5bbdf38df7d01852250bc (patch) | |
tree | 562e6d161a8957db8a46900b46f661c5e52e1a34 /native | |
parent | c5877847749d21bdf84e33929ffa52a56e5c6ca0 (diff) | |
download | classpath-35d18ccf396a6cfdcbe5bbdf38df7d01852250bc.tar.gz |
2006-06-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of HEAD-->generics between
2006/05/29 and 2006/06/11.
Diffstat (limited to 'native')
28 files changed, 3820 insertions, 2638 deletions
diff --git a/native/fdlibm/dtoa.c b/native/fdlibm/dtoa.c index 6d5ad3b42..5fb6aae2c 100644 --- a/native/fdlibm/dtoa.c +++ b/native/fdlibm/dtoa.c @@ -2,7 +2,7 @@ * * The author of this software is David M. Gay. * - * Copyright (c) 1991 by AT&T. + * Copyright (c) 1991, 2006 by AT&T. * * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice @@ -897,10 +897,23 @@ _DEFUN (_dtoa, { struct _Jv_reent reent; char *p; + int i; + memset (&reent, 0, sizeof reent); p = _dtoa_r (&reent, _d, mode, ndigits, decpt, sign, rve, float_type); strcpy (buf, p); - return; + for (i = 0; i < reent._result_k; ++i) + { + struct _Jv_Bigint *l = reent._freelist[i]; + while (l) + { + struct _Jv_Bigint *next = l->_next; + free (l); + l = next; + } + } + if (reent._freelist) + free (reent._freelist); } diff --git a/native/fdlibm/mprec.c b/native/fdlibm/mprec.c index 0badf60c4..e53722f7b 100644 --- a/native/fdlibm/mprec.c +++ b/native/fdlibm/mprec.c @@ -80,72 +80,112 @@ * down depends on the machine and the number being converted. */ +/*#include <_ansi.h>*/ #include <assert.h> #include <stdlib.h> #include <string.h> +/* #include <reent.h> */ #include "mprec.h" /* reent.c knows this value */ -#define _Kmax 15 -#include <stdio.h> +/* #define _Kmax 15 */ -_Jv_Bigint * -_DEFUN (Balloc, (ptr, k), struct _Jv_reent *ptr _AND int k) -{ - _Jv_Bigint *rv = NULL; +#define _reent _Jv_reent +#define _Bigint _Jv_Bigint - int i = 0; - int j = 1; +#define _REENT_CHECK_MP(x) +#define _REENT_MP_FREELIST(x) ((x)->_freelist) +#define _REENT_MP_P5S(x) ((x)->_p5s) - /* FIXME - assert disabled because of PR classpath/23863 - * assert ((1 << k) < MAX_BIGNUM_WDS); - */ +typedef unsigned long __ULong; +typedef long __Long; - while ((ptr->_allocation_map & j) && i < MAX_BIGNUMS) - i++, j <<= 1; +static void * +_calloc_r (void *ignore, size_t x1, size_t x2) +{ + char *result = (char *) malloc (x1 * x2); + memset (result, 0, x1 * x2); + return result; +} - assert (i < MAX_BIGNUMS); +_Bigint * +_DEFUN (Balloc, (ptr, k), struct _reent *ptr _AND int k) +{ + int x; + _Bigint *rv ; + int new_k = k + 1; + + _REENT_CHECK_MP(ptr); + if (_REENT_MP_FREELIST(ptr) == NULL) + { + /* Allocate a list of pointers to the mprec objects */ + _REENT_MP_FREELIST(ptr) = (struct _Bigint **) _calloc_r (ptr, + sizeof (struct _Bigint *), + new_k); + if (_REENT_MP_FREELIST(ptr) == NULL) + { + return NULL; + } + ptr->_max_k = new_k; + } + else if (new_k > ptr->_max_k) + { + struct _Bigint **new_list + = (struct _Bigint **) realloc (ptr->_freelist, + new_k * sizeof (struct _Bigint *)); + memset (&new_list[ptr->_max_k], 0, + (new_k - ptr->_max_k) * sizeof (struct _Bigint *)); + ptr->_freelist = new_list; + ptr->_max_k = new_k; - if (i >= MAX_BIGNUMS) - return NULL; + } - ptr->_allocation_map |= j; - rv = &ptr->_freelist[i]; - - rv->_k = k; - rv->_maxwds = 32; + assert (k <= ptr->_max_k); + if ((rv = _REENT_MP_FREELIST(ptr)[k]) != 0) + { + _REENT_MP_FREELIST(ptr)[k] = rv->_next; + } + else + { + x = 1 << k; + /* Allocate an mprec Bigint and stick in in the freelist */ + rv = (_Bigint *) _calloc_r (ptr, + 1, + sizeof (_Bigint) + + (x-1) * sizeof(rv->_x)); + if (rv == NULL) return NULL; + rv->_k = k; + rv->_maxwds = x; + } + rv->_sign = rv->_wds = 0; return rv; } - void -_DEFUN (Bfree, (ptr, v), struct _Jv_reent *ptr _AND _Jv_Bigint * v) +_DEFUN (Bfree, (ptr, v), struct _reent *ptr _AND _Bigint * v) { - long i; - - i = v - ptr->_freelist; - - assert (i >= 0 && i < MAX_BIGNUMS); - - if (i >= 0 && i < MAX_BIGNUMS) - ptr->_allocation_map &= ~ (1 << i); + _REENT_CHECK_MP(ptr); + if (v) + { + v->_next = _REENT_MP_FREELIST(ptr)[v->_k]; + _REENT_MP_FREELIST(ptr)[v->_k] = v; + } } - -_Jv_Bigint * +_Bigint * _DEFUN (multadd, (ptr, b, m, a), - struct _Jv_reent *ptr _AND - _Jv_Bigint * b _AND + struct _reent *ptr _AND + _Bigint * b _AND int m _AND int a) { int i, wds; - unsigned long *x, y; + __ULong *x, y; #ifdef Pack_32 - unsigned long xi, z; + __ULong xi, z; #endif - _Jv_Bigint *b1; + _Bigint *b1; wds = b->_wds; x = b->_x; @@ -180,17 +220,17 @@ _DEFUN (multadd, (ptr, b, m, a), return b; } -_Jv_Bigint * +_Bigint * _DEFUN (s2b, (ptr, s, nd0, nd, y9), - struct _Jv_reent * ptr _AND + struct _reent * ptr _AND _CONST char *s _AND int nd0 _AND int nd _AND - unsigned long y9) + __ULong y9) { - _Jv_Bigint *b; + _Bigint *b; int i, k; - long x, y; + __Long x, y; x = (nd + 8) / 9; for (k = 0, y = 1; x > y; y <<= 1, k++); @@ -222,7 +262,7 @@ _DEFUN (s2b, (ptr, s, nd0, nd, y9), int _DEFUN (hi0bits, - (x), register unsigned long x) + (x), register __ULong x) { register int k = 0; @@ -256,10 +296,10 @@ _DEFUN (hi0bits, } int -_DEFUN (lo0bits, (y), unsigned long *y) +_DEFUN (lo0bits, (y), __ULong *y) { register int k; - register unsigned long x = *y; + register __ULong x = *y; if (x & 7) { @@ -298,17 +338,17 @@ _DEFUN (lo0bits, (y), unsigned long *y) { k++; x >>= 1; - if (!(x & 1)) + if (!x & 1) return 32; } *y = x; return k; } -_Jv_Bigint * -_DEFUN (i2b, (ptr, i), struct _Jv_reent * ptr _AND int i) +_Bigint * +_DEFUN (i2b, (ptr, i), struct _reent * ptr _AND int i) { - _Jv_Bigint *b; + _Bigint *b; b = Balloc (ptr, 1); b->_x[0] = i; @@ -316,15 +356,15 @@ _DEFUN (i2b, (ptr, i), struct _Jv_reent * ptr _AND int i) return b; } -_Jv_Bigint * -_DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_Bigint * b) +_Bigint * +_DEFUN (mult, (ptr, a, b), struct _reent * ptr _AND _Bigint * a _AND _Bigint * b) { - _Jv_Bigint *c; + _Bigint *c; int k, wa, wb, wc; - unsigned long carry, y, z; - unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + __ULong carry, y, z; + __ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; #ifdef Pack_32 - unsigned long z2; + __ULong z2; #endif if (a->_wds < b->_wds) @@ -350,7 +390,7 @@ _DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_B #ifdef Pack_32 for (; xb < xbe; xb++, xc0++) { - if ((y = *xb & 0xffff)) + if ((y = *xb & 0xffff) != 0) { x = xa; xc = xc0; @@ -366,7 +406,7 @@ _DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_B while (x < xae); *xc = carry; } - if ((y = *xb >> 16)) + if ((y = *xb >> 16) != 0) { x = xa; xc = xc0; @@ -387,7 +427,7 @@ _DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_B #else for (; xb < xbe; xc0++) { - if ((y = *xb++)) + if (y = *xb++) { x = xa; xc = xc0; @@ -408,23 +448,24 @@ _DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_B return c; } -_Jv_Bigint * +_Bigint * _DEFUN (pow5mult, - (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k) + (ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k) { - _Jv_Bigint *b1, *p5, *p51; + _Bigint *b1, *p5, *p51; int i; static _CONST int p05[3] = {5, 25, 125}; - if ((i = k & 3)) + if ((i = k & 3) != 0) b = multadd (ptr, b, p05[i - 1], 0); if (!(k >>= 2)) return b; - if (!(p5 = ptr->_p5s)) + _REENT_CHECK_MP(ptr); + if (!(p5 = _REENT_MP_P5S(ptr))) { /* first time */ - p5 = ptr->_p5s = i2b (ptr, 625); + p5 = _REENT_MP_P5S(ptr) = i2b (ptr, 625); p5->_next = 0; } for (;;) @@ -447,12 +488,12 @@ _DEFUN (pow5mult, return b; } -_Jv_Bigint * -_DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k) +_Bigint * +_DEFUN (lshift, (ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k) { int i, k1, n, n1; - _Jv_Bigint *b1; - unsigned long *x, *x1, *xe, z; + _Bigint *b1; + __ULong *x, *x1, *xe, z; #ifdef Pack_32 n = k >> 5; @@ -480,7 +521,7 @@ _DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int z = *x++ >> k1; } while (x < xe); - if ((*x1 = z)) + if ((*x1 = z) != 0) ++n1; } #else @@ -490,11 +531,11 @@ _DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int z = 0; do { - *x1++ = (*x << k & 0xffff) | z; + *x1++ = *x << k & 0xffff | z; z = *x++ >> k1; } while (x < xe); - if ((*x1 = z)) + if (*x1 = z) ++n1; } #endif @@ -508,9 +549,9 @@ _DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int } int -_DEFUN (cmp, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b) +_DEFUN (cmp, (a, b), _Bigint * a _AND _Bigint * b) { - unsigned long *xa, *xa0, *xb, *xb0; + __ULong *xa, *xa0, *xb, *xb0; int i, j; i = a->_wds; @@ -537,16 +578,16 @@ _DEFUN (cmp, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b) return 0; } -_Jv_Bigint * -_DEFUN (diff, (ptr, a, b), struct _Jv_reent * ptr _AND - _Jv_Bigint * a _AND _Jv_Bigint * b) +_Bigint * +_DEFUN (diff, (ptr, a, b), struct _reent * ptr _AND + _Bigint * a _AND _Bigint * b) { - _Jv_Bigint *c; + _Bigint *c; int i, wa, wb; - long borrow, y; /* We need signed shifts here. */ - unsigned long *xa, *xae, *xb, *xbe, *xc; + __Long borrow, y; /* We need signed shifts here. */ + __ULong *xa, *xae, *xb, *xbe, *xc; #ifdef Pack_32 - long z; + __Long z; #endif i = cmp (a, b); @@ -625,7 +666,7 @@ double _DEFUN (ulp, (_x), double _x) { union double_union x, a; - register long L; + register __Long L; x.d = _x; @@ -659,7 +700,7 @@ _DEFUN (ulp, (_x), double _x) word0 (a) = 0; L -= Exp_shift; #ifndef _DOUBLE_IS_32BITS - word1 (a) = L >= 31 ? 1 : 1 << (31 - L); + word1 (a) = L >= 31 ? 1 : 1 << (31 - L); #endif } } @@ -669,13 +710,13 @@ _DEFUN (ulp, (_x), double _x) double _DEFUN (b2d, (a, e), - _Jv_Bigint * a _AND int *e) + _Bigint * a _AND int *e) { - unsigned long *xa, *xa0, w, y, z; + __ULong *xa, *xa0, w, y, z; int k; union double_union d; #ifdef VAX - unsigned long d0, d1; + __ULong d0, d1; #else #define d0 word0(d) #define d1 word1(d) @@ -696,7 +737,7 @@ _DEFUN (b2d, (a, e), d0 = Exp_1 | y >> (Ebits - k); w = xa > xa0 ? *--xa : 0; #ifndef _DOUBLE_IS_32BITS - d1 = y << (32 - Ebits + k) | w >> (Ebits - k); + d1 = y << ((32 - Ebits) + k) | w >> (Ebits - k); #endif goto ret_d; } @@ -720,18 +761,18 @@ _DEFUN (b2d, (a, e), if (k < Ebits + 16) { z = xa > xa0 ? *--xa : 0; - d0 = Exp_1 | y << (k - Ebits) | z >> (Ebits + 16 - k); + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; w = xa > xa0 ? *--xa : 0; y = xa > xa0 ? *--xa : 0; - d1 = z << (k + 16 - Ebits) | w << (k - Ebits) | y >> (16 + Ebits - k); + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; goto ret_d; } z = xa > xa0 ? *--xa : 0; w = xa > xa0 ? *--xa : 0; k -= Ebits + 16; - d0 = Exp_1 | y << (k + 16) | z << k | w >> (16 - k); + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; y = xa > xa0 ? *--xa : 0; - d1 = w << (k + 16) | y << k; + d1 = w << k + 16 | y << k; #endif ret_d: #ifdef VAX @@ -744,22 +785,24 @@ ret_d: return d.d; } -_Jv_Bigint * +_Bigint * _DEFUN (d2b, (ptr, _d, e, bits), - struct _Jv_reent * ptr _AND + struct _reent * ptr _AND double _d _AND int *e _AND int *bits) { union double_union d; - _Jv_Bigint *b; + _Bigint *b; int de, i, k; - unsigned long *x, y, z; + __ULong *x, y, z; #ifdef VAX - unsigned long d0, d1; + __ULong d0, d1; +#endif d.d = _d; +#ifdef VAX d0 = word0 (d) >> 16 | word0 (d) << 16; d1 = word1 (d) >> 16 | word1 (d) << 16; #else @@ -783,16 +826,18 @@ _DEFUN (d2b, z |= Exp_msk11; #endif #else - if ((de = (int) (d0 >> Exp_shift))) + if ((de = (int) (d0 >> Exp_shift)) != 0) z |= Exp_msk1; #endif #ifdef Pack_32 #ifndef _DOUBLE_IS_32BITS - if ((y = d1)) + if (d1) { - if ((k = lo0bits (&y))) + y = d1; + k = lo0bits (&y); + if (k) { - x[0] = y | z << (32 - k); + x[0] = y | z << (32 - k); z >>= k; } else @@ -814,22 +859,24 @@ _DEFUN (d2b, #endif } #else - if ((y = d1)) + if (d1) { - if ((k = lo0bits (&y))) + y = d1; + k = lo0bits (&y); + if (k) if (k >= 16) { - x[0] = y | (z << (32 - k) & 0xffff); - x[1] = z >> (k - 16) & 0xffff; + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; x[2] = z >> k; i = 2; } else { x[0] = y & 0xffff; - x[1] = (y >> 16 | z << (16 - k)) & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; x[2] = z >> k & 0xffff; - x[3] = z >> (k + 16); + x[3] = z >> k + 16; i = 3; } else @@ -894,7 +941,7 @@ _DEFUN (d2b, #undef d1 double -_DEFUN (ratio, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b) +_DEFUN (ratio, (a, b), _Bigint * a _AND _Bigint * b) { union double_union da, db; @@ -958,3 +1005,17 @@ _CONST double tinytens[] = #endif +double +_DEFUN (_mprec_log10, (dig), + int dig) +{ + double v = 1.0; + if (dig < 24) + return tens[dig]; + while (dig > 0) + { + v *= 10; + dig--; + } + return v; +} diff --git a/native/fdlibm/mprec.h b/native/fdlibm/mprec.h index cd8f928a8..7c7471bc8 100644 --- a/native/fdlibm/mprec.h +++ b/native/fdlibm/mprec.h @@ -282,7 +282,7 @@ struct _Jv_Bigint { struct _Jv_Bigint *_next; int _k, _maxwds, _sign, _wds; - unsigned long _x[MAX_BIGNUM_WDS]; + unsigned long _x[1]; }; @@ -310,10 +310,8 @@ struct _Jv_reent int _result_k; struct _Jv_Bigint *_p5s; - struct _Jv_Bigint _freelist[MAX_BIGNUMS]; - int _allocation_map; - - int num; + struct _Jv_Bigint **_freelist; + int _max_k; }; diff --git a/native/jawt/Makefile.am b/native/jawt/Makefile.am index 30e5a345b..01abf3bb9 100644 --- a/native/jawt/Makefile.am +++ b/native/jawt/Makefile.am @@ -3,7 +3,7 @@ nativeexeclib_LTLIBRARIES = libjawt.la libjawt_la_SOURCES = jawt.c libjawt_la_LIBADD = $(top_builddir)/native/jni/gtk-peer/libgtkpeer.la -AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @PANGOFT2_LIBS@ @X_LIBS@ -lXtst +AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @PANGOFT2_LIBS@ @X_LIBS@ @XTEST_LIBS@ AM_CPPFLAGS = @CLASSPATH_INCLUDES@ # Just the WARNING_CFLAGS. We cannot use the strict flags since the gtk diff --git a/native/jni/classpath/jcl.h b/native/jni/classpath/jcl.h index 514b78262..d358aeb9c 100644 --- a/native/jni/classpath/jcl.h +++ b/native/jni/classpath/jcl.h @@ -1,5 +1,5 @@ /* jcl.h - Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 1998, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -50,6 +50,10 @@ typedef jlong jpointer; #error "Unknown pointer size" #endif +/* Helper macros for going between pointers and jlongs. */ +#define JLONG_TO_PTR(T,P) ((T *)(long)P) +#define PTR_TO_JLONG(P) ((jlong)(long)P) + JNIEXPORT jclass JNICALL JCL_FindClass (JNIEnv * env, const char *className); JNIEXPORT void JNICALL JCL_ThrowException (JNIEnv * env, const char *className, diff --git a/native/jni/gtk-peer/Makefile.am b/native/jni/gtk-peer/Makefile.am index 4b113c978..8a39f34fe 100644 --- a/native/jni/gtk-peer/Makefile.am +++ b/native/jni/gtk-peer/Makefile.am @@ -1,12 +1,17 @@ nativeexeclib_LTLIBRARIES = libgtkpeer.la # GTK JNI sources. -libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ +libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \ + gnu_java_awt_peer_gtk_CairoGraphics2D.c \ + gnu_java_awt_peer_gtk_ComponentGraphics.c \ + gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c \ + gnu_java_awt_peer_gtk_FreetypeGlyphVector.c \ + gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ gnu_java_awt_peer_gtk_GdkFontPeer.c \ - gnu_java_awt_peer_gtk_GdkGraphics2D.c \ gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \ gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \ gnu_java_awt_peer_gtk_GdkRobotPeer.c \ + gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c \ gnu_java_awt_peer_gtk_GdkTextLayout.c \ gnu_java_awt_peer_gtk_GtkButtonPeer.c \ gnu_java_awt_peer_gtk_GtkCanvasPeer.c \ @@ -36,7 +41,10 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \ gnu_java_awt_peer_gtk_GtkTextFieldPeer.c \ gnu_java_awt_peer_gtk_GtkToolkit.c \ gnu_java_awt_peer_gtk_GtkWindowPeer.c \ + gnu_java_awt_peer_gtk_GtkVolatileImage.c \ + cairographics2d.h \ gthread-jni.c \ + gdkdisplay.h \ gdkfont.h \ gthread-jni.h \ gtk_jawt.c \ @@ -46,7 +54,7 @@ libgtkpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/native_state.lo \ $(top_builddir)/native/jni/classpath/jcl.lo AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @FREETYPE2_LIBS@ \ - @PANGOFT2_LIBS@ @X_PRE_LIBS@ @X_LIBS@ @X_EXTRA_LIBS@ -lX11 -lXtst + @PANGOFT2_LIBS@ @X_PRE_LIBS@ @X_LIBS@ @X_EXTRA_LIBS@ @XTEST_LIBS@ AM_CPPFLAGS = @CLASSPATH_INCLUDES@ # Just the WARNING_CFLAGS. We cannot use the strict flags since the gtk diff --git a/native/jni/gtk-peer/cairographics2d.h b/native/jni/gtk-peer/cairographics2d.h new file mode 100644 index 000000000..675bc0b17 --- /dev/null +++ b/native/jni/gtk-peer/cairographics2d.h @@ -0,0 +1,116 @@ +/* cairographics2d.h -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#ifndef CAIROGRAPHICS2D_H +#define CAIROGRAPHICS2D_H + + +#include <cairo.h> +#include <gtk/gtk.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <config.h> +#include "native_state.h" +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <jni.h> + +/* + * These public final constants are part of the java2d public API, so we + * write them explicitly here to save fetching them from the constant pool + * all the time. + */ +enum java_awt_alpha_composite_rule + { + java_awt_alpha_composite_CLEAR = 1, + java_awt_alpha_composite_SRC = 2, + java_awt_alpha_composite_SRC_OVER = 3, + java_awt_alpha_composite_DST_OVER = 4, + java_awt_alpha_composite_SRC_IN = 5, + java_awt_alpha_composite_DST_IN = 6, + java_awt_alpha_composite_SRC_OUT = 7, + java_awt_alpha_composite_DST_OUT = 8, + java_awt_alpha_composite_DST = 9, + java_awt_alpha_composite_SRC_ATOP = 10, + java_awt_alpha_composite_DST_ATOP = 11, + java_awt_alpha_composite_XOR = 12 + }; + +enum java_awt_basic_stroke_join_rule + { + java_awt_basic_stroke_JOIN_MITER = 0, + java_awt_basic_stroke_JOIN_ROUND = 1, + java_awt_basic_stroke_JOIN_BEVEL = 2 + }; + +enum java_awt_basic_stroke_cap_rule + { + java_awt_basic_stroke_CAP_BUTT = 0, + java_awt_basic_stroke_CAP_ROUND = 1, + java_awt_basic_stroke_CAP_SQUARE = 2 + }; + +enum java_awt_geom_path_iterator_winding_rule + { + java_awt_geom_path_iterator_WIND_EVEN_ODD = 0, + java_awt_geom_path_iterator_WIND_NON_ZERO = 1 + }; + +enum java_awt_rendering_hints_filter + { + java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0, + java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3, + java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4 + + }; + +/** + * A structure which basically contains the cairo_t pointer. + * The rest is for gradient and texture fills. + */ +struct cairographics2d +{ + cairo_t *cr; + cairo_surface_t *pattern_surface; + cairo_pattern_t *pattern; + char *pattern_pixels; +}; + +#endif diff --git a/native/jni/gtk-peer/gdkdisplay.h b/native/jni/gtk-peer/gdkdisplay.h new file mode 100644 index 000000000..238ff9e26 --- /dev/null +++ b/native/jni/gtk-peer/gdkdisplay.h @@ -0,0 +1,67 @@ +#ifndef __GDKDISPLAY_H__ +#define __GDKDISPLAY_H__ + +/* gdkdisplay.h -- Some global stuff related to displays & screens + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + +#include "gtkpeer.h" + +/* Allows storing GdkDisplay pointers in GdkGraphicsEnvironment instances. */ +extern struct state_table *cp_gtk_native_display_state_table; + +/* Allows storing GdkScreen pointers in GdkScreenGraphicsDevice instances. */ +extern struct state_table *cp_gtk_native_screen_state_table; + +#define NSA_DISPLAY_INIT(env, clazz) \ + cp_gtk_native_display_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_DISPLAY_PTR(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_display_state_table) + +#define NSA_SET_DISPLAY_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, cp_gtk_native_display_state_table, (void *)ptr) + +#define NSA_SCREEN_INIT(env, clazz) \ + cp_gtk_native_screen_state_table = cp_gtk_init_state_table (env, clazz) + +#define NSA_GET_SCREEN_PTR(env, obj) \ + cp_gtk_get_state (env, obj, cp_gtk_native_screen_state_table) + +#define NSA_SET_SCREEN_PTR(env, obj, ptr) \ + cp_gtk_set_state (env, obj, cp_gtk_native_screen_state_table, (void *)ptr) + +#endif /* __GDKDISPLAY_H__ */ diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c new file mode 100644 index 000000000..8ac89cffe --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c @@ -0,0 +1,706 @@ +/* gnu_java_awt_peer_gtk_CairoGraphics2d.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "jcl.h" +#include "gdkfont.h" +#include "cairographics2d.h" +#include "gnu_java_awt_peer_gtk_CairoGraphics2D.h" +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +static void install_font_peer(cairo_t *cr, struct peerfont *pfont); +static void update_pattern_transform (struct cairographics2d *gr); + +/** + * Allocates the cairographics2d structure. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_init + (JNIEnv *env __attribute__ ((unused)), + jobject obj __attribute__ ((unused)), + jlong cairo_t_pointer) +{ + struct cairographics2d *g = NULL; + cairo_t *cr = JLONG_TO_PTR(cairo_t, cairo_t_pointer); + g_assert(cr != NULL); + + g = (struct cairographics2d *) g_malloc (sizeof (struct cairographics2d)); + + g_assert (g != NULL); + memset (g, 0, sizeof(struct cairographics2d)); + g->cr = cr; + + return PTR_TO_JLONG(g); +} + +/** + * Disposes of the cairographics2d structure. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_disposeNative + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + + if (gr == NULL) + return; + + if (gr->cr) + cairo_destroy (gr->cr); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + gr->pattern = NULL; + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + gr->pattern_surface = NULL; + + if (gr->pattern_pixels) + g_free(gr->pattern_pixels); + gr->pattern_pixels = NULL; + + g_free( gr ); +} + +/** + * Set the gradient. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, + jdouble x1, jdouble y1, + jdouble x2, jdouble y2, + jint r1, jint g1, jint b1, jint a1, + jint r2, jint g2, jint b2, jint a2, + jboolean cyclic) +{ + struct cairographics2d *gr = NULL; + cairo_pattern_t* pattern; + cairo_extend_t extend; + + gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert( gr != NULL ); + + pattern = cairo_pattern_create_linear(x1, y1, x2, y2); + g_assert( pattern != NULL ); + + cairo_pattern_add_color_stop_rgba(pattern, 0.0, r1 / 255.0, g1 / 255.0, + b1 / 255.0, a1 / 255.0); + + cairo_pattern_add_color_stop_rgba(pattern, 1.0, r2 / 255.0, g2 / 255.0, + b2 / 255.0, a2 / 255.0); + + extend = (cyclic == JNI_TRUE) ? CAIRO_EXTEND_REFLECT : CAIRO_EXTEND_NONE; + + cairo_pattern_set_extend( pattern, extend ); + + gr->pattern = pattern; + cairo_set_source(gr->cr, gr->pattern); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setTexturePixels + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jintArray jarr, jint w, jint h, jint stride) +{ + struct cairographics2d *gr = NULL; + jint *jpixels = NULL; + + gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + if (gr->pattern) + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); + + if (gr->pattern_pixels) + g_free (gr->pattern_pixels); + + gr->pattern = NULL; + gr->pattern_surface = NULL; + gr->pattern_pixels = NULL; + + gr->pattern_pixels = (char *) g_malloc (h * stride * 4); + g_assert (gr->pattern_pixels != NULL); + + jpixels = (*env)->GetIntArrayElements (env, jarr, NULL); + g_assert (jpixels != NULL); + memcpy (gr->pattern_pixels, jpixels, h * stride * 4); + (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); + + gr->pattern_surface = cairo_image_surface_create_for_data ((unsigned char *)gr->pattern_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + g_assert (gr->pattern_surface != NULL); + gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); + g_assert (gr->pattern != NULL); + cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source (gr->cr, gr->pattern); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_drawPixels +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jintArray java_pixels, + jint w, jint h, jint stride, jdoubleArray java_matrix) +{ + jint *native_pixels = NULL; + jdouble *native_matrix = NULL; + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL); + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_pixels != NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + cairo_pattern_t *p; + cairo_surface_t *surf = cairo_image_surface_create_for_data ((unsigned char *)native_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + p = cairo_pattern_create_for_surface (surf); + cairo_pattern_set_matrix (p, &mat); + if (gr->pattern) + cairo_pattern_set_filter (p, cairo_pattern_get_filter (gr->pattern)); + cairo_set_source (gr->cr, p); + cairo_paint (gr->cr); + cairo_pattern_destroy (p); + cairo_surface_destroy (surf); + } + + (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdoubleArray java_matrix) +{ + jdouble *native_matrix = NULL; + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (obj != NULL); + g_assert (gr != NULL); + + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + g_assert (gr != NULL); + cairo_set_matrix (gr->cr, &mat); + } + + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); + update_pattern_transform (gr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector +(JNIEnv *env, jobject obj, jlong pointer, + jobject font, + jfloat x, jfloat y, jint n, + jintArray java_codes, + jfloatArray java_positions) +{ + + struct cairographics2d *gr = NULL; + struct peerfont *pfont = NULL; + cairo_glyph_t *glyphs = NULL; + int *native_codes; + float *native_positions; + jint i = 0; + + g_assert (obj != NULL); + g_assert (java_codes != NULL); + g_assert (java_positions != NULL); + + gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert (pfont != NULL); + + install_font_peer(gr->cr, pfont); + + glyphs = g_malloc( sizeof(cairo_glyph_t) * n); + g_assert (glyphs != NULL); + + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); + + for (i = 0; i < n; ++i) + { + glyphs[i].index = native_codes[i]; + glyphs[i].x = x + native_positions[ 2*i ]; + glyphs[i].y = y + native_positions[ 2*i + 1]; + } + + (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + + cairo_show_glyphs (gr->cr, glyphs, n); + + g_free(glyphs); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jint op) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + switch ((enum java_awt_alpha_composite_rule) op) + { + case java_awt_alpha_composite_CLEAR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR); + break; + + case java_awt_alpha_composite_SRC: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_SOURCE); + break; + + case java_awt_alpha_composite_SRC_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER); + break; + + case java_awt_alpha_composite_DST_OVER: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OVER); + break; + + case java_awt_alpha_composite_SRC_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN); + break; + + case java_awt_alpha_composite_DST_IN: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_IN); + break; + + case java_awt_alpha_composite_SRC_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT); + break; + + case java_awt_alpha_composite_DST_OUT: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OUT); + break; + + case java_awt_alpha_composite_DST: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST); + break; + + case java_awt_alpha_composite_SRC_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP); + break; + + case java_awt_alpha_composite_DST_ATOP: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_ATOP); + break; + + case java_awt_alpha_composite_XOR: + cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); + break; + } +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetRGBAColor +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble r, jdouble g, jdouble b, jdouble a) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_set_source_rgba (gr->cr, r, g, b, a); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetFillRule +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jint rule) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + switch ((enum java_awt_geom_path_iterator_winding_rule) rule) + { + case java_awt_geom_path_iterator_WIND_NON_ZERO: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING); + break; + case java_awt_geom_path_iterator_WIND_EVEN_ODD: + cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); + break; + } +} + +/** + * Set the line style, except for dashes. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetLine +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble width, int cap, int join, double miterLimit) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + /* set width */ + cairo_set_line_width (gr->cr, width); + + /* set cap */ + switch ((enum java_awt_basic_stroke_cap_rule) cap) + { + case java_awt_basic_stroke_CAP_BUTT: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT); + break; + + case java_awt_basic_stroke_CAP_ROUND: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND); + break; + + case java_awt_basic_stroke_CAP_SQUARE: + cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); + break; + } + + /* set join */ + switch ((enum java_awt_basic_stroke_join_rule) join) + { + case java_awt_basic_stroke_JOIN_MITER: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER); + break; + + case java_awt_basic_stroke_JOIN_ROUND: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND); + break; + + case java_awt_basic_stroke_JOIN_BEVEL: + cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); + break; + } + + /* set miter */ + cairo_set_miter_limit (gr->cr, miterLimit); +} + +/** + * Set the line dashes + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetDash +(JNIEnv *env, jobject obj __attribute__((unused)), + jlong pointer, jdoubleArray dashes, jint ndash, jdouble offset) +{ + jdouble *dasharr = NULL; + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL); + g_assert (dasharr != NULL); + + cairo_set_dash (gr->cr, dasharr, ndash, offset); + + (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoNewPath +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_new_path (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoMoveTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble x, jdouble y) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_move_to (gr->cr, x, y); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoLineTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble x, jdouble y) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_line_to (gr->cr, x, y); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoCurveTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble x1, jdouble y1, + jdouble x2, jdouble y2, jdouble x3, jdouble y3) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelMoveTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble dx, jdouble dy) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_rel_move_to (gr->cr, dx, dy); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelLineTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble dx, jdouble dy) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_rel_line_to (gr->cr, dx, dy); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelCurveTo +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRectangle +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jdouble x, jdouble y, jdouble width, jdouble height) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + + cairo_rectangle (gr->cr, x, y, width, height); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClosePath +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_close_path (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoStroke +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_stroke (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoFill +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_fill (gr->cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClip +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert( gr != NULL ); + + cairo_clip( gr->cr ); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoResetClip +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_reset_clip( gr->cr ); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoPreserveClip +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + cairo_clip_preserve( gr->cr ); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSurfaceSetFilter +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong pointer, jint filter) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + if (gr->pattern == NULL) + return; + + switch ((enum java_awt_rendering_hints_filter) filter) + { + case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BILINEAR); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_FAST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); + break; + case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY: + cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BEST); + break; + } +} + +/************************** FONT STUFF ****************************/ +static void +install_font_peer(cairo_t *cr, + struct peerfont *pfont) +{ + cairo_font_face_t *ft; + FT_Face face = NULL; + + g_assert(cr != NULL); + g_assert(pfont != NULL); + + if (pfont->graphics_resource == NULL) + { + face = pango_ft2_font_get_face (pfont->font); + g_assert (face != NULL); + + ft = cairo_ft_font_face_create_for_ft_face (face, 0); + g_assert (ft != NULL); + + cairo_set_font_face (cr, ft); + cairo_font_face_destroy (ft); + cairo_set_font_size (cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + ft = cairo_get_font_face (cr); + pfont->graphics_resource = ft; + } + else + { + ft = (cairo_font_face_t *) pfont->graphics_resource; + cairo_set_font_face (cr, ft); + cairo_set_font_size (cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + } +} + +static void +update_pattern_transform (struct cairographics2d *gr) +{ + cairo_matrix_t mat; + + g_assert (gr != NULL); + if (gr->pattern == NULL) + return; + + cairo_get_matrix (gr->cr, &mat); + cairo_pattern_set_matrix (gr->pattern, &mat); +} + + diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c new file mode 100644 index 000000000..3efa60d62 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c @@ -0,0 +1,302 @@ +/* gnu_java_awt_peer_gtk_CairoSurface.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <cairo-xlib.h> +#include <gdk/gdkx.h> + +#include "gnu_java_awt_peer_gtk_CairoSurface.h" +#include "cairographics2d.h" + +/** + * Field names in CairoSurface.java + */ +#define SURFACE "surfacePointer" +#define BUFFER "bufferPointer" + +/* prototypes */ +static void setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer ); + +/** + * Creates a cairo surface, ARGB32, native ordering, premultiplied alpha. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_create (JNIEnv *env, jobject obj, jint width, jint height, jint stride) +{ + cairo_surface_t* surface; + void *data = g_malloc(stride * height * 4); + memset(data, 0, stride * height * 4); + setNativeObject(env, obj, data, BUFFER); + + surface = cairo_image_surface_create_for_data + (data, CAIRO_FORMAT_ARGB32, width, height, stride); + + setNativeObject(env, obj, surface, SURFACE); +} + +/** + * Destroy the surface + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_destroy +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong surfacePointer, jlong bufferPointer) +{ + void *buffer; + cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer); + if( surface != NULL ) + cairo_surface_destroy(surface); + + buffer = JLONG_TO_PTR(void, bufferPointer); + if( buffer != NULL ) + g_free(buffer); +} + +/** + * Gets a pixel + */ +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetElem +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong bufferPointer, jint i) +{ + jint *pixeldata = JLONG_TO_PTR(void, bufferPointer); + + if( pixeldata == NULL ) + return 0; + + return pixeldata[i]; +} + +/** + * Sets a pixel + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetElem +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong bufferPointer, jint i, jint val) +{ + jint *pixeldata = JLONG_TO_PTR(void, bufferPointer); + + if( pixeldata == NULL ) + return; + + pixeldata[i] = val; +} + +/** + * Gets all pixels in an array + */ +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetPixels +(JNIEnv *env __attribute((unused)), jobject obj __attribute((unused)), + jlong bufferPointer, int size) +{ + jint *pixeldata, *jpixdata; + jintArray jpixels; + + pixeldata = JLONG_TO_PTR(void, bufferPointer); + g_assert(pixeldata != NULL); + + jpixels = (*env)->NewIntArray (env, size); + jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL); + memcpy (jpixdata, pixeldata, size * sizeof( jint )); + + (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0); + return jpixels; +} + +/** + * Sets all pixels by an array. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetPixels +(JNIEnv *env, jobject obj, jlong bufferPointer, jintArray jpixels) +{ + jint *pixeldata, *jpixdata; + int size; + int width, height; + jclass cls; + jfieldID field; + + if( jpixels == NULL ) + return; + + cls = (*env)->GetObjectClass (env, obj); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + width = (*env)->GetIntField (env, obj, field); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + height = (*env)->GetIntField (env, obj, field); + + pixeldata = JLONG_TO_PTR(void, bufferPointer); + g_assert(pixeldata != NULL); + + jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL); + size = (*env)->GetArrayLength( env, jpixels ); + if( size > width * height ) size = width * height; /* stop overflows. */ + + memcpy (pixeldata, jpixdata, size * sizeof( jint )); + + (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeDrawSurface +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong surfacePointer, jlong context, jdoubleArray java_matrix) +{ + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, context); + cairo_t *cr = gr->cr; + jdouble *native_matrix = NULL; + cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer); + g_assert(surface != NULL); + g_assert(cr != NULL); + + native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); + g_assert (native_matrix != NULL); + g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); + + { + cairo_matrix_t mat; + cairo_pattern_t *p; + cairo_matrix_init_identity (&mat); + cairo_matrix_init (&mat, + native_matrix[0], native_matrix[1], + native_matrix[2], native_matrix[3], + native_matrix[4], native_matrix[5]); + + p = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_matrix (p, &mat); + + cairo_set_source(cr, p); + cairo_paint(cr); + cairo_pattern_destroy(p); + } + + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); +} + +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong bufferPointer, jint size) +{ + jint *dst; + jint *src = JLONG_TO_PTR(void, bufferPointer); + int i; + int t; + + g_assert( src != NULL ); + dst = g_malloc( size * sizeof( jint ) ); + + for(i = 0; i < size; i++ ) + { + t = (src[i] & 0x0000FF) << 16; + dst[i] = (src[i] & 0x00FF0000) >> 16; + dst[i] |= (src[i] & 0xFF00FF00); + dst[i] |= t; + } + + return PTR_TO_JLONG(dst); +} + +/** + * Create and return a cairo context for drawing to the surface. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_nativeNewCairoContext +(JNIEnv *env __attribute((unused)), jobject obj __attribute((unused)), + jlong surfacePointer) +{ + cairo_surface_t* surface = JLONG_TO_PTR(cairo_surface_t, surfacePointer); + cairo_t *ptr; + g_assert(surface != NULL); + ptr = cairo_create(surface); + g_assert(ptr != NULL); + + return PTR_TO_JLONG(ptr); +} + +/** + * copyArea. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative2 +(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong bufferPointer, + jint x, jint y, jint w, jint h, jint dx, jint dy, jint stride) +{ + int row; + int srcOffset, dstOffset; + jint *temp; + jint *pixeldata = JLONG_TO_PTR(jint, bufferPointer); + g_assert( pixeldata != NULL ); + + temp = g_malloc( h * w * 4 ); + g_assert( temp != NULL ); + + srcOffset = x + (y * stride); + dstOffset = (x + dx) + ((y + dy) * stride); + + for( row = 0; row < h; row++ ) + memcpy( temp + (w * row), pixeldata + srcOffset + (stride * row), w * 4 ); + + for( row = 0; row < h; row++ ) + memcpy( pixeldata + dstOffset + (stride * row), temp + (w * row), w * 4 ); + + g_free( temp ); +} + +/* + * Sets the native object field. + */ +static void +setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer ) +{ + jclass cls; + jlong value; + jfieldID nofid; + cls = (*env)->GetObjectClass( env, obj ); + value = PTR_TO_JLONG(ptr); + nofid = (*env)->GetFieldID( env, cls, pointer, "J" ); + (*env)->SetLongField( env, obj, nofid, value ); + (*env)->DeleteLocalRef( env, cls ); +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c new file mode 100644 index 000000000..d85ba326f --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c @@ -0,0 +1,311 @@ +/* gnu_java_awt_peer_gtk_ComponentGraphics.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <cairo-xlib.h> +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <X11/extensions/Xrender.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixdata.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "gnu_java_awt_peer_gtk_ComponentGraphics.h" + +#include "cairographics2d.h" + +static short flush_scheduled = 0; + +static gboolean flush (gpointer data __attribute__((unused))) +{ + gdk_threads_enter (); + + XFlush (GDK_DISPLAY ()); + flush_scheduled = 0; + + gdk_threads_leave (); + + return FALSE; +} + +/* The minimum time period between calls to XFlush, in + milliseconds. */ +#define MINIMUM_FLUSH_PERIOD 20 + +/* schedule_flush must be called with the GDK lock held. */ +static void +schedule_flush () +{ + if (!flush_scheduled) + { + g_timeout_add (MINIMUM_FLUSH_PERIOD, flush, NULL); + flush_scheduled = 1; + } +} + +void cp_gtk_grab_current_drawable(GtkWidget *widget, GdkDrawable **draw, + GdkWindow **win) +{ + g_assert (widget != NULL); + g_assert (draw != NULL); + g_assert (win != NULL); + + *win = widget->window; + + *draw = *win; + gdk_window_get_internal_paint_info (*win, draw, 0, 0); +} + +/** + * Returns whether the XRender extension is supported + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender + (JNIEnv *env __attribute__ ((unused)), jclass cls __attribute__ ((unused))) +{ +#if HAVE_XRENDER + int ev = 0, err = 0; + if( XRenderQueryExtension (GDK_DISPLAY (), &ev, &err) ) + return JNI_TRUE; +#endif + return JNI_FALSE; +} + + +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_initState + (JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer) +{ + Drawable draw; + Display * dpy; + Visual * vis; + GdkDrawable *drawable; + cairo_surface_t *surface; + GdkWindow *win; + GtkWidget *widget = NULL; + void *ptr = NULL; + int width, height; + cairo_t *cr; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + cp_gtk_grab_current_drawable (widget, &drawable, &win); + g_assert (drawable != NULL); + + width = widget->allocation.width; + height = widget->allocation.height; + + g_assert (drawable != NULL); + + draw = gdk_x11_drawable_get_xid(drawable); + g_assert (draw != (XID) 0); + + dpy = gdk_x11_drawable_get_xdisplay(drawable); + g_assert (dpy != NULL); + + vis = gdk_x11_visual_get_xvisual(gdk_drawable_get_visual(drawable)); + g_assert (vis != NULL); + + surface = cairo_xlib_surface_create (dpy, draw, vis, width, height); + g_assert (surface != NULL); + + cr = cairo_create (surface); + g_assert(cr != NULL); + + gdk_threads_leave(); + + return PTR_TO_JLONG(cr); +} + +/** + * Disposes of the surface + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_disposeSurface + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), + jlong value) +{ + struct cairographics2d *gr; + cairo_surface_t *surface; + + gr = JLONG_TO_PTR(struct cairographics2d, value); + + if (gr == NULL) + return; + + if (gr->cr == NULL) + return; + + surface = cairo_get_target (gr->cr); + if (surface != NULL) + { + gdk_threads_enter(); + cairo_surface_destroy (surface); + gdk_threads_leave(); + } +} + +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_initFromVolatile + (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)), + jlong ptr, jint width, jint height) +{ + Drawable draw; + Display * dpy; + Visual * vis; + GdkDrawable *drawable; + cairo_surface_t *surface; + cairo_t *cr; + + gdk_threads_enter(); + + drawable = JLONG_TO_PTR(GdkDrawable, ptr); + g_assert (drawable != NULL); + + draw = gdk_x11_drawable_get_xid(drawable); + g_assert (draw != (XID) 0); + + dpy = gdk_x11_drawable_get_xdisplay(drawable); + g_assert (dpy != NULL); + + vis = gdk_x11_visual_get_xvisual(gdk_drawable_get_visual(drawable)); + g_assert (vis != NULL); + + surface = cairo_xlib_surface_create (dpy, draw, vis, width, height); + g_assert (surface != NULL); + + cr = cairo_create (surface); + g_assert(cr != NULL); + + gdk_threads_leave(); + + return PTR_TO_JLONG(cr); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing + (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused))) +{ + gdk_threads_enter(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing + (JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused))) +{ + schedule_flush (); + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative + (JNIEnv *env, jobject obj __attribute__((unused)), jobject peer, + jint x, jint y, jint w, jint h, jint dx, jint dy) +{ + GdkPixbuf *pixbuf; + GdkDrawable *drawable; + GdkWindow *win; + GtkWidget *widget = NULL; + void *ptr = NULL; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + cp_gtk_grab_current_drawable (widget, &drawable, &win); + g_assert (drawable != NULL); + + pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h ); + gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, x, y, 0, 0, w, h ); + gdk_draw_pixbuf (drawable, NULL, pixbuf, + 0, 0, x + dx, y + dy, + w, h, + GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile +(JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer, + jlong img, jint x, jint y, jint w, jint h) +{ + GdkPixmap *pixmap; + GtkWidget *widget = NULL; + void *ptr = NULL; + GdkGC *gc; + + gdk_threads_enter(); + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + pixmap = JLONG_TO_PTR(GdkPixmap, img); + + gc = gdk_gc_new(widget->window); + gdk_draw_drawable(widget->window, + gc, + pixmap, + 0, 0, + x, y, + w, h); + + g_object_unref( gc ); + + schedule_flush (); + + gdk_threads_leave(); +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c new file mode 100644 index 000000000..76caa5d0c --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c @@ -0,0 +1,132 @@ +/* gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <cairo-xlib.h> +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixdata.h> + +#include <cairo-ft.h> +#include <cairo-xlib.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "gnu_java_awt_peer_gtk_ComponentGraphicsCopy.h" + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphicsCopy_getPixbuf + (JNIEnv *env, jobject obj __attribute__((unused)), + jobject peer, jobject image) +{ + gint width, height; + GdkPixbuf *pixbuf; + GdkDrawable *drawable; + GdkWindow *win; + GtkWidget *widget = NULL; + void *ptr = NULL; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + cp_gtk_grab_current_drawable (widget, &drawable, &win); + g_assert (drawable != NULL); + + pixbuf = cp_gtk_image_get_pixbuf( env, image ); + g_assert( pixbuf != NULL); + + width = gdk_pixbuf_get_width( pixbuf ); + height = gdk_pixbuf_get_height( pixbuf ); + + gdk_pixbuf_get_from_drawable( pixbuf, /* destination pixbuf */ + drawable, + NULL, /* colormap */ + 0, 0, 0, 0, + width, height ); + gdk_threads_leave(); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_ComponentGraphicsCopy_copyPixbuf + (JNIEnv *env, jobject obj __attribute__((unused)), + jobject peer, jobject image, + int x __attribute__((unused)), int y __attribute__((unused)), + int width __attribute__((unused)), int height __attribute__((unused))) +{ + gint pwidth, pheight; + GdkPixbuf *pixbuf; + GdkDrawable *drawable; + GdkWindow *win; + GtkWidget *widget = NULL; + void *ptr = NULL; + + gdk_threads_enter(); + + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + + cp_gtk_grab_current_drawable (widget, &drawable, &win); + g_assert (drawable != NULL); + + pixbuf = cp_gtk_image_get_pixbuf( env, image ); + g_assert( pixbuf != NULL); + + pwidth = gdk_pixbuf_get_width( pixbuf ); + pheight = gdk_pixbuf_get_height( pixbuf ); + + gdk_draw_pixbuf (drawable, NULL, pixbuf, + 0, 0, 0, 0, + pwidth, pheight, + GDK_RGB_DITHER_NORMAL, 0, 0); + + gdk_threads_leave(); +} + diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c new file mode 100644 index 000000000..c8b74d207 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c @@ -0,0 +1,348 @@ +/* gnu_java_awt_FreetypeGlyphVector.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <jni.h> +#include <gtk/gtk.h> +#include <string.h> +#include <pango/pango.h> +#include <pango/pangoft2.h> +#include <pango/pangofc-font.h> +#include <freetype/ftglyph.h> +#include <freetype/ftoutln.h> +#include "native_state.h" +#include "gdkfont.h" +#include "gnu_java_awt_peer_gtk_FreetypeGlyphVector.h" +#include "cairographics2d.h" + +typedef struct gp +{ + JNIEnv *env; + jobject obj; + double px; + double py; + double sx; + double sy; +} generalpath ; + +static PangoFcFont * +getFont(JNIEnv *env, jobject obj) +{ + jfieldID fid; + jobject data; + jclass cls; + struct peerfont *pfont; + + cls = (*env)->GetObjectClass (env, obj); + fid = (*env)->GetFieldID (env, cls, "peer", + "Lgnu/java/awt/peer/gtk/GdkFontPeer;"); + g_assert (fid != 0); + + data = (*env)->GetObjectField (env, obj, fid); + g_assert (data != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, data); + g_assert (pfont != NULL); + g_assert (pfont->font != NULL); + + return (PangoFcFont *)pfont->font; +} + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs + (JNIEnv *env, jobject obj, jintArray codepoints) +{ + FT_Face ft_face; + jintArray retArray; + PangoFcFont *font; + jint *values, *cpvals; + jint length; + int i; + + font = getFont(env, obj); + + ft_face = pango_fc_font_lock_face( font ); + g_assert (ft_face != NULL); + + length = (*env)->GetArrayLength (env, codepoints); + cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL); + + retArray = (*env)->NewIntArray (env, length); + values = (*env)->GetIntArrayElements (env, retArray, NULL); + + for( i = 0; i < length; i++ ) + values[i] = FT_Get_Char_Index( ft_face, cpvals[i] ); + + (*env)->ReleaseIntArrayElements (env, retArray, values, 0); + (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0); + + pango_fc_font_unlock_face (font); + + return retArray; +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning +(JNIEnv *env, jobject obj, jint rightGlyph, jint leftGlyph) +{ + FT_Face ft_face; + FT_Vector kern; + jclass cls; + jmethodID method; + jvalue values[2]; + PangoFcFont *font; + + font = getFont(env, obj); + ft_face = pango_fc_font_lock_face( font ); + g_assert (ft_face != NULL); + FT_Get_Kerning( ft_face, rightGlyph, leftGlyph, FT_KERNING_DEFAULT, &kern ); + + pango_fc_font_unlock_face( font ); + + values[0].d = (jdouble)kern.x/64.0; + values[1].d = (jdouble)kern.y/64.0; + + cls = (*env)->FindClass (env, "java/awt/geom/Point2D$Double"); + method = (*env)->GetMethodID (env, cls, "<init>", "(DD)V"); + return (*env)->NewObjectA(env, cls, method, values); +} + +JNIEXPORT jdoubleArray JNICALL +Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative +(JNIEnv *env, jobject obj, jint glyphIndex ) +{ + FT_Face ft_face; + jdouble *values; + jdoubleArray retArray = NULL; + PangoFcFont *font; + + font = getFont(env, obj); + ft_face = pango_fc_font_lock_face( font ); + + g_assert (ft_face != NULL); + + FT_Set_Transform( ft_face, NULL, NULL ); + + if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 ) + { + pango_fc_font_unlock_face( font ); + printf("Couldn't load glyph %i\n", glyphIndex); + return NULL; + } + + retArray = (*env)->NewDoubleArray (env, 8); + values = (*env)->GetDoubleArrayElements (env, retArray, NULL); + + values[0] = 0; + values[1] = (jdouble)ft_face->glyph->advance.x/64.0; + values[2] = (jdouble)ft_face->glyph->advance.y/64.0; + values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0; + values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0; + values[5] = (jdouble)ft_face->glyph->metrics.width/64.0; + values[6] = (jdouble)ft_face->glyph->metrics.height/64.0; + values[7] = 0; + + (*env)->ReleaseDoubleArrayElements (env, retArray, values, 0); + pango_fc_font_unlock_face( font ); + + return retArray; +} + +/* GetOutline code follows ****************************/ +/********* Freetype callback functions *****************************/ + +static int _moveTo( const FT_Vector* to, + void *p) +{ + JNIEnv *env; + jobject obj; + jclass cls; + jmethodID method; + jvalue values[2]; + generalpath *path = (generalpath *) p; + + env = path->env; + obj = path->obj; + + values[0].f = (jfloat)(to->x * path->sx + path->px); + values[1].f = (jfloat)(to->y * path->sy + path->py); + + cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); + method = (*env)->GetMethodID (env, cls, "moveTo", "(FF)V"); + (*env)->CallVoidMethodA(env, obj, method, values ); + + return 0; +} + +static int _lineTo( const FT_Vector* to, + void *p) +{ + JNIEnv *env; + jobject obj; + jclass cls; + jmethodID method; + jvalue values[2]; + generalpath *path = (generalpath *) p; + + env = path->env; + obj = path->obj; + values[0].f = (jfloat)(to->x * path->sx + path->px); + values[1].f = (jfloat)(to->y * path->sy + path->py); + + cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); + method = (*env)->GetMethodID (env, cls, "lineTo", "(FF)V"); + (*env)->CallVoidMethodA(env, obj, method, values ); + + return 0; +} + +static int _quadTo( const FT_Vector* cp, + const FT_Vector* to, + void *p) +{ + JNIEnv *env; + jobject obj; + jclass cls; + jmethodID method; + jvalue values[4]; + generalpath *path = (generalpath *) p; + + env = path->env; + obj = path->obj; + values[0].f = (jfloat)(cp->x * path->sx + path->px); + values[1].f = (jfloat)(cp->y * path->sy + path->py); + values[2].f = (jfloat)(to->x * path->sx + path->px); + values[3].f = (jfloat)(to->y * path->sy + path->py); + + cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); + method = (*env)->GetMethodID (env, cls, "quadTo", "(FFFF)V"); + (*env)->CallVoidMethodA(env, obj, method, values ); + + return 0; +} + +static int _curveTo( const FT_Vector* cp1, + const FT_Vector* cp2, + const FT_Vector* to, + void *p) +{ + JNIEnv *env; + jobject obj; + jclass cls; + jmethodID method; + jvalue values[6]; + generalpath *path = (generalpath *) p; + + env = path->env; + obj = path->obj; + values[0].f = (jfloat)(cp1->x * path->sx + path->px); + values[1].f = (jfloat)(cp1->y * path->sy + path->py); + values[2].f = (jfloat)(cp2->x * path->sx + path->px); + values[3].f = (jfloat)(cp2->y * path->sy + path->py); + values[4].f = (jfloat)(to->x * path->sx + path->px); + values[5].f = (jfloat)(to->y * path->sy + path->py); + + cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); + method = (*env)->GetMethodID (env, cls, "curveTo", "(FFFFFF)V"); + (*env)->CallVoidMethodA(env, obj, method, values ); + + return 0; +} + + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative + (JNIEnv *env, jobject obj, jint glyphIndex) +{ + generalpath *path; + jobject gp; + FT_Outline_Funcs ftCallbacks = + { + (FT_Outline_MoveToFunc) _moveTo, + (FT_Outline_LineToFunc) _lineTo, + (FT_Outline_ConicToFunc) _quadTo, + (FT_Outline_CubicToFunc) _curveTo, + 0, + 0 + }; + PangoFcFont *font; + FT_Face ft_face; + FT_Glyph glyph; + + font = getFont(env, obj); + ft_face = pango_fc_font_lock_face( font ); + + g_assert (ft_face != NULL); + + path = g_malloc0 (sizeof (generalpath)); + g_assert(path != NULL); + path->env = env; + + path->px = path->py = 0.0; + path->sx = 1.0/64.0; + path->sy = -1.0/64.0; + + { /* create a GeneralPath instance */ + jclass cls; + jmethodID method; + + cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath"); + method = (*env)->GetMethodID (env, cls, "<init>", "()V"); + gp = path->obj = (*env)->NewObject (env, cls, method); + } + + if(FT_Load_Glyph(ft_face, + (FT_UInt)(glyphIndex), + FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0) + { + pango_fc_font_unlock_face( font ); + g_free(path); + return NULL; + } + + FT_Get_Glyph( ft_face->glyph, &glyph ); + FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline), + &ftCallbacks, path); + FT_Done_Glyph( glyph ); + + pango_fc_font_unlock_face( font ); + + g_free(path); + + return gp; +} + + diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c index c0f776b20..ddaece1b2 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c @@ -59,25 +59,11 @@ enum java_awt_font_baseline { java_awt_font_HANGING_BASELINE = 2 }; -static jmethodID glyphVector_ctor; -static jclass glyphVector_class; -static PangoAttrList *attrs = NULL; - JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState (JNIEnv *env, jclass clazz) { NSA_FONT_INIT (env, clazz); - - glyphVector_class = (*env)->FindClass - (env, "gnu/java/awt/peer/gtk/GdkGlyphVector"); - - glyphVector_class = (*env)->NewGlobalRef - (env, glyphVector_class); - - glyphVector_ctor = (*env)->GetMethodID - (env, glyphVector_class, "<init>", - "([D[ILjava/awt/Font;Ljava/awt/font/FontRenderContext;)V"); } JNIEXPORT void JNICALL @@ -121,124 +107,26 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose } -JNIEXPORT jobject JNICALL -Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector - (JNIEnv *env, jobject self, - jstring chars, - jobject font, - jobject fontRenderContext) +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource + (JNIEnv *env, jobject java_font) { struct peerfont *pfont = NULL; - GList *items = NULL; - GList *i = NULL; - gchar *str = NULL; - int len = 0; - int j = 0; - double *native_extents = NULL; - int *native_codes = NULL; - jintArray java_codes = NULL; - jdoubleArray java_extents = NULL; - gdk_threads_enter (); + gdk_threads_enter(); - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); + pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); g_assert (pfont != NULL); - - len = (*cp_gtk_gdk_env())->GetStringUTFLength (env, chars); - str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL); - g_assert (str != NULL); - - if (attrs == NULL) - attrs = pango_attr_list_new (); - - if (len > 0 && str[len-1] == '\0') - len--; - - items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL); - - i = g_list_first (items); - - if (i == NULL) + if (pfont->graphics_resource != NULL) { - java_extents = (*env)->NewDoubleArray (env, 0); - java_codes = (*env)->NewIntArray (env, 0); - } - else - { - PangoGlyphString *glyphs; - PangoItem *item = (PangoItem *)i->data; - - pango_context_set_font_description (pfont->ctx, pfont->desc); - pango_context_set_language (pfont->ctx, gtk_get_default_language()); - pango_context_load_font (pfont->ctx, pfont->desc); - - glyphs = pango_glyph_string_new (); - g_assert (glyphs != NULL); - - pango_shape (str + item->offset, item->length, - &(item->analysis), glyphs); - - if (glyphs->num_glyphs > 0) - { - int x = 0; - double scale = ((double) PANGO_SCALE); - - java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS); - java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs); - - native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL); - native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); - - for (j = 0; j < glyphs->num_glyphs; ++j) - { - PangoRectangle ink; - PangoRectangle logical; - PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry; - - pango_font_get_glyph_extents (pfont->font, - glyphs->glyphs[j].glyph, - &ink, &logical); - - native_codes[j] = glyphs->glyphs[j].glyph; - - native_extents[ GLYPH_LOG_X(j) ] = (logical.x) / scale; - native_extents[ GLYPH_LOG_Y(j) ] = (- logical.y) / scale; - native_extents[ GLYPH_LOG_WIDTH(j) ] = (logical.width) / scale; - native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale; - - native_extents[ GLYPH_INK_X(j) ] = (ink.x) / scale; - native_extents[ GLYPH_INK_Y(j) ] = (- ink.y) / scale; - native_extents[ GLYPH_INK_WIDTH(j) ] = (ink.width) / scale; - native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height) / scale; - - native_extents[ GLYPH_POS_X(j) ] = (x + geom->x_offset) / scale; - native_extents[ GLYPH_POS_Y(j) ] = ( - geom->y_offset) / scale; - - x += geom->width; - } - (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0); - (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); - } - - pango_glyph_string_free (glyphs); + cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); + pfont->graphics_resource = NULL; } - (*env)->ReleaseStringUTFChars (env, chars, str); - - for (i = g_list_first (items); i != NULL; i = g_list_next (i)) - pango_item_free(i->data); - - g_list_free (items); - - gdk_threads_leave (); - - return (*env)->NewObject (env, - glyphVector_class, - glyphVector_ctor, - java_extents, java_codes, - font, fontRenderContext); + gdk_threads_leave(); } + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics (JNIEnv *env, jobject java_font, jdoubleArray java_metrics) diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c deleted file mode 100644 index 56c13b6c1..000000000 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* gnu_java_awt_peer_gtk_GdkGraphics2d.c - Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -#include "jcl.h" -#include "gdkfont.h" -#include "gnu_java_awt_peer_gtk_GdkGraphics2D.h" -#include <gdk/gdktypes.h> -#include <gdk/gdkprivate.h> -#include <gdk/gdkx.h> -#include <X11/extensions/Xrender.h> - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk-pixbuf/gdk-pixdata.h> - -#include <cairo-ft.h> -#include <cairo-xlib.h> - -#include <stdio.h> -#include <stdlib.h> - -struct state_table *cp_gtk_native_graphics2d_state_table; - -/* - * AWT applications may call Graphics methods from threads other than - * the GDK main thread, so we must call XFlush after each batch of - * drawing operations, otherwise animations flicker. Flushing after - * every graphics operation is excessive and negatively affects - * performance (PR 26486). We set the maximum frequency to 50 times - * per second, or a minimum period of 20 milliseconds between calls to - * XFlush. See gnu.classpath.examples.awt.AnimationApplet for an - * example applet that requires these XFlush calls. - */ - -static short flush_scheduled = 0; - -static gboolean flush (gpointer data __attribute__((unused))) -{ - gdk_threads_enter (); - - XFlush (GDK_DISPLAY ()); - flush_scheduled = 0; - - gdk_threads_leave (); - - return FALSE; -} - -/* The minimum time period between calls to XFlush, in - milliseconds. */ -#define MINIMUM_FLUSH_PERIOD 20 - -/* schedule_flush must be called with the GDK lock held. */ -static void -schedule_flush () -{ - if (!flush_scheduled) - { - g_timeout_add (MINIMUM_FLUSH_PERIOD, flush, NULL); - flush_scheduled = 1; - } -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState - (JNIEnv *env, jclass clazz) -{ - gdk_threads_enter(); - - NSA_G2D_INIT (env, clazz); - - gdk_threads_leave(); -} - -/* these public final constants are part of the java2d public API, so we - write them explicitly here to save fetching them from the constant pool - all the time. */ - -#ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) -#endif - -enum java_awt_alpha_composite_rule - { - java_awt_alpha_composite_CLEAR = 1, - java_awt_alpha_composite_SRC = 2, - java_awt_alpha_composite_SRC_OVER = 3, - java_awt_alpha_composite_DST_OVER = 4, - java_awt_alpha_composite_SRC_IN = 5, - java_awt_alpha_composite_DST_IN = 6, - java_awt_alpha_composite_SRC_OUT = 7, - java_awt_alpha_composite_DST_OUT = 8, - java_awt_alpha_composite_DST = 9, - java_awt_alpha_composite_SRC_ATOP = 10, - java_awt_alpha_composite_DST_ATOP = 11, - java_awt_alpha_composite_XOR = 12 - }; - -enum java_awt_basic_stroke_join_rule - { - java_awt_basic_stroke_JOIN_MITER = 0, - java_awt_basic_stroke_JOIN_ROUND = 1, - java_awt_basic_stroke_JOIN_BEVEL = 2 - }; - -enum java_awt_basic_stroke_cap_rule - { - java_awt_basic_stroke_CAP_BUTT = 0, - java_awt_basic_stroke_CAP_ROUND = 1, - java_awt_basic_stroke_CAP_SQUARE = 2 - }; - -enum java_awt_geom_path_iterator_winding_rule - { - java_awt_geom_path_iterator_WIND_EVEN_ODD = 0, - java_awt_geom_path_iterator_WIND_NON_ZERO = 1 - }; - -enum java_awt_rendering_hints_filter - { - java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 0, - java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR = 1, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED = 2, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY = 3, - java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT = 4 - - }; - -static int -peer_is_disposed(JNIEnv *env, jobject obj) -{ - static jfieldID fid = NULL; - jclass cls; - jobject peer; - - if (fid == NULL) - { - cls = (*env)->GetObjectClass(env, obj); - fid = (*env)->GetFieldID(env, cls, "component", - "Lgnu/java/awt/peer/gtk/GtkComponentPeer;"); - } - g_assert(fid != NULL); - peer = (*env)->GetObjectField(env, obj, fid); - if (peer == NULL || NSA_GET_PTR (env, peer) != NULL) - return 0; - else - return 1; -} - -static void -grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win) -{ - g_assert (widget != NULL); - g_assert (draw != NULL); - g_assert (win != NULL); - - *win = widget->window; - - *draw = *win; - gdk_window_get_internal_paint_info (*win, draw, 0, 0); - g_object_ref (*draw); -} - - -static int -x_server_has_render_extension (void) -{ - int ev = 0, err = 0; - return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err); -} - -static void -init_graphics2d_as_pixbuf (struct graphics2d *gr) -{ - gint width, height; - gint bits_per_sample = 8; - gint total_channels = 4; - gboolean has_alpha = TRUE; - - g_assert (gr != NULL); - g_assert (gr->drawable != NULL); - - if (gr->debug) printf ("initializing graphics2d as pixbuf\n"); - gdk_drawable_get_size (gr->drawable, &width, &height); - gr->drawbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - has_alpha, bits_per_sample, - width, height); - g_assert (gr->drawbuf != NULL); - g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample); - g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels); - - gr->surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (gr->drawbuf), - CAIRO_FORMAT_ARGB32, - gdk_pixbuf_get_width (gr->drawbuf), - gdk_pixbuf_get_height (gr->drawbuf), - gdk_pixbuf_get_rowstride (gr->drawbuf)); - g_assert (gr->surface != NULL); - gr->mode = MODE_DRAWABLE_NO_RENDER; - if (gr->cr != NULL) - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); -} - -static void -init_graphics2d_as_renderable (struct graphics2d *gr) -{ - Drawable draw; - Display * dpy; - Visual * vis; - - g_assert (gr != NULL); - g_assert (gr->drawable != NULL); - - gr->drawbuf = NULL; - - if (gr->debug) printf ("initializing graphics2d as renderable\n"); - draw = gdk_x11_drawable_get_xid (gr->drawable); - - dpy = gdk_x11_drawable_get_xdisplay (gr->drawable); - g_assert (dpy != NULL); - - vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable)); - g_assert (vis != NULL); - - gr->surface = cairo_xlib_surface_create (dpy, draw, vis, gr->width, gr->height); - g_assert (gr->surface != NULL); - gr->mode = MODE_DRAWABLE_WITH_RENDER; - if (gr->cr != NULL) - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); -} - -static void -begin_drawing_operation (JNIEnv *env, struct graphics2d * gr) -{ - cairo_status_t cst = cairo_status (gr->cr); - if (cst != CAIRO_STATUS_SUCCESS) - { - const char *detail = cairo_status_to_string (cst); - JCL_ThrowException (env, "java/lang/InternalError", detail); - (*env)->ExceptionDescribe (env); - return; - } - - switch (gr->mode) - { - case MODE_DRAWABLE_WITH_RENDER: - break; - - case MODE_DRAWABLE_NO_RENDER: - { - - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; - - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */ - gr->drawable, - NULL, /* colormap */ - 0, 0, 0, 0, - width, height); - - if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n", - width, height); - } - break; - - case MODE_JAVA_ARRAY: - { - jboolean isCopy; - gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &isCopy); - gr->isCopy |= isCopy; - if (gr->isCopy) - { - /* Make sure that the pixel buffer copy is already initalized, - i.e. we already failed to get direct access in initState. */ - g_assert (gr->javabuf_copy != NULL); - memcpy (gr->javabuf_copy, gr->javabuf, gr->width * gr->height * 4); - } - } - break; - } -} - -static void -end_drawing_operation (JNIEnv *env, struct graphics2d * gr) -{ - cairo_status_t cst = cairo_status (gr->cr); - if (cst != CAIRO_STATUS_SUCCESS) - { - /* Report error. */ - const char *detail = cairo_status_to_string (cst); - JCL_ThrowException (env, "java/lang/InternalError", detail); - (*env)->ExceptionDescribe (env); - - /* Recreate cairo status. */ - cairo_destroy (gr->cr); - gr->cr = cairo_create (gr->surface); - return; - } - - switch (gr->mode) - { - case MODE_DRAWABLE_WITH_RENDER: - break; - - case MODE_DRAWABLE_NO_RENDER: - { - - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; - - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf, - 0, 0, 0, 0, - width, height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", - width, height); - } - break; - - case MODE_JAVA_ARRAY: - if (gr->isCopy) - memcpy (gr->javabuf, gr->javabuf_copy, gr->width * gr->height * 4); - (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); - } - - schedule_flush (); -} - - -static void -update_pattern_transform (struct graphics2d *gr) -{ - cairo_matrix_t mat; - - g_assert (gr != NULL); - if (gr->pattern == NULL) - return; - - cairo_get_matrix (gr->cr, &mat); - cairo_pattern_set_matrix (gr->pattern, &mat); -} - -static void -check_for_debug (struct graphics2d *gr) -{ - gr->debug = (gboolean)(getenv("DEBUGJ2D") != NULL); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState - (JNIEnv *env, jobject obj, jobject old) -{ - struct graphics2d *g = NULL, *g_old = NULL; - - gdk_threads_enter(); - - g = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (g != NULL); - memset (g, 0, sizeof(struct graphics2d)); - - g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old); - g_assert (g_old != NULL); - - if (g_old->debug) printf ("copying state from existing graphics2d\n"); - - g->debug = g_old->debug; - g->mode = g_old->mode; - - g->width = g_old->width; - g->height = g_old->height; - - if (g_old->mode == MODE_JAVA_ARRAY) - { - jint size = g->width * g->height * 4; - - g->jarray = (*env)->NewGlobalRef (env, g_old->jarray); - g->javabuf = (*env)->GetIntArrayElements (env, g->jarray, &g->isCopy); - g->isCopy = JNI_TRUE; - g->javabuf_copy = (jint *) g_malloc (size); - memcpy (g->javabuf_copy, g->javabuf, size); - g->surface = cairo_image_surface_create_for_data ((unsigned char *) g->javabuf, - CAIRO_FORMAT_ARGB32, - g->width, - g->height, - g->width * 4); - g_assert (g->surface != NULL); - g->cr = cairo_create (g->surface); - g_assert (g->cr != NULL); - (*env)->ReleaseIntArrayElements (env, g->jarray, g->javabuf, JNI_ABORT); - } - else - { - g->drawable = g_old->drawable; - g_object_ref (g->drawable); - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (g); - else - init_graphics2d_as_pixbuf (g); - } - - if (g->pattern) - cairo_pattern_set_filter (g->pattern, CAIRO_FILTER_FAST); - - NSA_SET_G2D_PTR (env, obj, g); - - gdk_threads_leave(); -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState___3III -(JNIEnv *env, jobject obj, jintArray jarr, jint width, jint height) -{ - struct graphics2d *gr = NULL; - jint *cairobuf = NULL; - - gdk_threads_enter(); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - if (gr->debug) printf ("constructing java-backed image of size (%d,%d)\n", - width, height); - - gr->width = width; - gr->height = height; - gr->jarray = (*env)->NewGlobalRef(env, jarr); - gr->javabuf = (*env)->GetPrimitiveArrayCritical (env, gr->jarray, &gr->isCopy); - if (gr->isCopy) - { - /* We didn't get direct access to the pixel buffer, so we'll have to - maintain a separate copy for Cairo. */ - jint size = gr->width * gr->height * 4; - gr->javabuf_copy = (jint *) g_malloc (size); - memcpy (gr->javabuf_copy, gr->javabuf, size); - cairobuf = gr->javabuf_copy; - } - else - { - /* Have Cairo write directly to the Java array. */ - cairobuf = gr->javabuf; - } - gr->surface = cairo_image_surface_create_for_data ((unsigned char *) cairobuf, - CAIRO_FORMAT_ARGB32, - gr->width, - gr->height, - gr->width * 4); - g_assert (gr->surface != NULL); - gr->cr = cairo_create (gr->surface); - g_assert (gr->cr != NULL); - (*env)->ReleasePrimitiveArrayCritical (env, gr->jarray, gr->javabuf, JNI_COMMIT); - - gr->mode = MODE_JAVA_ARRAY; - - if (gr->debug) printf ("constructed java-backed image of size (%d,%d)\n", - width, height); - - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II - (JNIEnv *env, jobject obj, jint width, jint height) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - if (gr->debug) printf ("constructing offscreen drawable of size (%d,%d)\n", - width, height); - - gr->drawable = (GdkDrawable *) gdk_pixmap_new (NULL, width, height, - gdk_rgb_get_visual ()->depth); - g_assert (gr->drawable != NULL); - - gr->width = width; - gr->height = height; - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (gr); - else - init_graphics2d_as_pixbuf (gr); - - if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n", - width, height); - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable - (JNIEnv *env, jobject obj, jobject other, jint x, jint y) -{ - struct graphics2d *src = NULL; - struct graphics2d *dst = NULL; - gint s_height; - gint s_width; - gint d_height; - gint d_width; - gint height; - gint width; - cairo_matrix_t matrix; - cairo_operator_t tmp_op; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other); - dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - g_assert (src != NULL); - g_assert (dst != NULL); - - if (src->debug) printf ("copying from offscreen drawable\n"); - - begin_drawing_operation(env, dst); - - /* gdk_flush(); */ - - if (!GDK_IS_DRAWABLE (src->drawable) || - !GDK_IS_DRAWABLE (dst->drawable)) - { - gdk_threads_leave (); - return; - } - - gdk_drawable_get_size (src->drawable, &s_width, &s_height); - gdk_drawable_get_size (dst->drawable, &d_width, &d_height); - width = min (s_width, d_width); - height = min (s_height, d_height); - - cairo_get_matrix (src->cr, &matrix); - cairo_matrix_translate (&matrix, (double)-x, (double)-y); - if (src->pattern) - cairo_pattern_set_matrix (src->pattern, &matrix); - tmp_op = cairo_get_operator (dst->cr); - cairo_set_operator(dst->cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_surface (dst->cr, src->surface, 0, 0); - cairo_paint (dst->cr); - cairo_set_operator(dst->cr, tmp_op); - - cairo_matrix_translate (&matrix, (double)x, (double)y); - if (src->pattern) - cairo_pattern_set_matrix (src->pattern, &matrix); - - end_drawing_operation(env, dst); - - if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2 - (JNIEnv *env, jobject obj, jobject peer) -{ - struct graphics2d *gr = NULL; - GtkWidget *widget = NULL; - void *ptr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - ptr = NSA_GET_PTR (env, peer); - g_assert (ptr != NULL); - - gr = (struct graphics2d *) g_malloc (sizeof (struct graphics2d)); - g_assert (gr != NULL); - memset (gr, 0, sizeof(struct graphics2d)); - - check_for_debug (gr); - - widget = GTK_WIDGET (ptr); - g_assert (widget != NULL); - - grab_current_drawable (widget, &(gr->drawable), &(gr->win)); - g_assert (gr->drawable != NULL); - - gr->width = widget->allocation.width; - gr->height = widget->allocation.height; - - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (gr); - else - init_graphics2d_as_pixbuf (gr); - - NSA_SET_G2D_PTR (env, obj, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj); - - /* dispose has been called more than once */ - if (gr == NULL) - return; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->surface) - cairo_surface_destroy (gr->surface); - gr->surface = NULL; - - cairo_destroy (gr->cr); - gr->cr = NULL; - - if (gr->drawbuf) - g_object_unref (gr->drawbuf); - gr->drawbuf = NULL; - - if (gr->drawable) - g_object_unref (gr->drawable); - gr->drawable = NULL; - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - gr->pattern = NULL; - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - gr->pattern_surface = NULL; - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - gr->pattern_pixels = NULL; - - if (gr->mode == MODE_JAVA_ARRAY) - { - (*env)->DeleteGlobalRef (env, gr->jarray); - if (gr->javabuf_copy) - g_free (gr->javabuf_copy); - gr->javabuf_copy = NULL; - } - - if (gr->debug) printf ("disposed of graphics2d\n"); - - g_free (gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient - (JNIEnv *env, jobject obj, - jdouble x1, jdouble y1, - jdouble x2, jdouble y2, - jint r1, jint g1, jint b1, jint a1, - jint r2, jint g2, jint b2, jint a2, - jboolean cyclic) -{ - struct graphics2d *gr = NULL; - cairo_surface_t *surf = NULL; - cairo_t *cr2 = NULL; - cairo_matrix_t mat; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) - printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n", - x1, y1, - x2, y2, - r1, g1, b1, a1, - r2, g2, b2, a2); - - if (cyclic) - surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 3, 2); - else - surf = cairo_surface_create_similar (gr->surface, CAIRO_FORMAT_ARGB32, 2, 2); - g_assert (surf != NULL); - - cr2 = cairo_create (surf); - - cairo_identity_matrix (cr2); - - cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); - cairo_rectangle (cr2, 0, 0, 1, 2); - cairo_fill (cr2); - - cairo_set_source_rgba (cr2, r2 / 255.0, g2 / 255.0, b2 / 255.0, a2 / 255.0); - cairo_rectangle (cr2, 1, 0, 1, 2); - cairo_fill (cr2); - - if (cyclic) - { - cairo_set_source_rgba (cr2, r1 / 255.0, g1 / 255.0, b1 / 255.0, a1 / 255.0); - cairo_rectangle (cr2, 2, 0, 1, 2); - cairo_fill (cr2); - } - - cairo_matrix_init_identity (&mat); - - /* - consider the vector [x2 - x1, y2 - y1] = [p,q] - - this is a line in space starting at an 'origin' x1, y1. - - it can also be thought of as a "transformed" unit vector in either the - x or y directions. we have just *drawn* our gradient as a unit vector - (well, a 2-3x unit vector) in the x dimension. so what we want to know - is which transformation turns our existing unit vector into [p,q]. - - which means solving for M in - - [p,q] = M[1,0] - - [p,q] = |a b| [1,0] - |c d| - - [p,q] = [a,c], with b = d = 0. - - what does this mean? it means that our gradient is 1-dimensional; as - you move through the x axis of our 2 or 3 pixel gradient from logical - x positions 0 to 1, the transformation of your x coordinate under the - matrix M causes you to accumulate both x and y values in fill - space. the y value of a gradient coordinate is ignored, since the - gradient is one dimensional. which is correct. - - unfortunately we want the opposite transformation, it seems, because of - the way cairo is going to use this transformation. I'm a bit confused by - that, but it seems to work right, so we take reciprocals of values and - negate offsets. oh well. - - */ - { - double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1)); - double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1)); - double dx = (x1 == 0.) ? 0. : 1. / x1; - double dy = (y1 == 0.) ? 0. : 1. / y1; - cairo_pattern_t *p; - - cairo_matrix_init (&mat, - a, 0., - c, 0., - dx, dy); - - p = cairo_pattern_create_for_surface (surf); - cairo_pattern_set_matrix (p, &mat); - cairo_pattern_set_filter (p, CAIRO_FILTER_BILINEAR); - } - - /* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */ - /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */ - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - - gr->pattern_pixels = NULL; - gr->pattern_surface = surf; - gr->pattern = cairo_pattern_create_for_surface(surf); - - cairo_set_source (gr->cr, gr->pattern); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels - (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride) -{ - struct graphics2d *gr = NULL; - jint *jpixels = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->debug) - printf ("setTexturePixels (%d pixels, %dx%d, stride: %d)\n", - (*env)->GetArrayLength (env, jarr), w, h, stride); - - if (gr->pattern) - cairo_pattern_destroy (gr->pattern); - - if (gr->pattern_surface) - cairo_surface_destroy (gr->pattern_surface); - - if (gr->pattern_pixels) - g_free (gr->pattern_pixels); - - gr->pattern = NULL; - gr->pattern_surface = NULL; - gr->pattern_pixels = NULL; - - gr->pattern_pixels = (char *) g_malloc (h * stride * 4); - g_assert (gr->pattern_pixels != NULL); - - jpixels = (*env)->GetIntArrayElements (env, jarr, NULL); - g_assert (jpixels != NULL); - memcpy (gr->pattern_pixels, jpixels, h * stride * 4); - (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); - - gr->pattern_surface = cairo_image_surface_create_for_data ((unsigned char *)gr->pattern_pixels, - CAIRO_FORMAT_ARGB32, - w, h, stride * 4); - g_assert (gr->pattern_surface != NULL); - gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); - g_assert (gr->pattern != NULL); - cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source (gr->cr, gr->pattern); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels - (JNIEnv *env, jobject obj, jintArray java_pixels, - jint w, jint h, jint stride, jdoubleArray java_matrix) -{ - struct graphics2d *gr = NULL; - jint *native_pixels = NULL; - jdouble *native_matrix = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->debug) - printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n", - (*env)->GetArrayLength (env, java_pixels), w, h, stride); - - native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL); - native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); - g_assert (native_pixels != NULL); - g_assert (native_matrix != NULL); - g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); - - begin_drawing_operation (env, gr); - - { - cairo_matrix_t mat; - cairo_pattern_t *p; - cairo_surface_t *surf = cairo_image_surface_create_for_data ((unsigned char *)native_pixels, - CAIRO_FORMAT_ARGB32, - w, h, stride * 4); - cairo_matrix_init_identity (&mat); - cairo_matrix_init (&mat, - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - - p = cairo_pattern_create_for_surface (surf); - cairo_pattern_set_matrix (p, &mat); - if (gr->pattern) - cairo_pattern_set_filter (p, cairo_pattern_get_filter (gr->pattern)); - cairo_set_source (gr->cr, p); - cairo_paint (gr->cr); - cairo_pattern_destroy (p); - cairo_surface_destroy (surf); - } - - end_drawing_operation (env, gr); - - (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); - (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); - - gdk_threads_leave(); -} - -/* passthrough methods to cairo */ - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_save\n"); - cairo_save (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_restore\n"); - cairo_restore (gr->cr); - update_pattern_transform (gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix - (JNIEnv *env, jobject obj, jdoubleArray java_matrix) -{ - struct graphics2d *gr = NULL; - jdouble *native_matrix = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL); - g_assert (native_matrix != NULL); - g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); - - if (gr->debug) - printf ("cairo_matrix_init [ %f, %f, %f, %f, %f, %f ]\n", - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - - { - cairo_matrix_t mat; - - cairo_matrix_init_identity (&mat); - cairo_matrix_init (&mat, - native_matrix[0], native_matrix[1], - native_matrix[2], native_matrix[3], - native_matrix[4], native_matrix[5]); - cairo_set_matrix (gr->cr, &mat); - } - - (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); - update_pattern_transform (gr); - - gdk_threads_leave(); -} - -static void -install_font_peer(cairo_t *cr, - struct peerfont *pfont, - int debug) -{ - cairo_font_face_t *ft; - FT_Face face = NULL; - - g_assert(cr != NULL); - g_assert(pfont != NULL); - - if (pfont->graphics_resource == NULL) - { - face = pango_ft2_font_get_face (pfont->font); - g_assert (face != NULL); - - ft = cairo_ft_font_face_create_for_ft_face (face, 0); - g_assert (ft != NULL); - - if (debug) printf ("install_font_peer made new cairo font for '%s' at %f\n", - face->family_name, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - - cairo_set_font_face (cr, ft); - cairo_font_face_destroy (ft); - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - ft = cairo_get_font_face (cr); - pfont->graphics_resource = ft; - } - else - { - if (debug) printf ("install_font_peer reused existing font resource" - " for '%s' at %f\n", - pango_font_description_get_family(pfont->desc), - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - ft = (cairo_font_face_t *) pfont->graphics_resource; - cairo_set_font_face (cr, ft); - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - } -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource - (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font) -{ - struct peerfont *pfont = NULL; - - gdk_threads_enter(); - - g_assert(java_font != NULL); - - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - if (pfont->graphics_resource != NULL) - { - cairo_font_face_destroy ((cairo_font_face_t *) pfont->graphics_resource); - pfont->graphics_resource = NULL; - } - - gdk_threads_leave(); -} - -static void -paint_glyph_run(JNIEnv *env, - struct graphics2d *gr, - cairo_glyph_t **glyphs, - gint *n_glyphs, - PangoLayoutRun *run) -{ - gint i = 0; - gint x = 0, y = 0; - - g_assert (gr != NULL); - g_assert (glyphs != NULL); - g_assert (n_glyphs != NULL); - g_assert (run != NULL); - - if (run->glyphs != NULL && run->glyphs->num_glyphs > 0) - { - if (*n_glyphs < run->glyphs->num_glyphs) - { - *glyphs = g_realloc(*glyphs, - (sizeof(cairo_glyph_t) - * run->glyphs->num_glyphs)); - *n_glyphs = run->glyphs->num_glyphs; - } - - g_assert (*glyphs != NULL); - - if (gr->debug) printf ("painting %d glyphs: ", run->glyphs->num_glyphs); - - for (i = 0; i < run->glyphs->num_glyphs; ++i) - { - (*glyphs)[i].index = run->glyphs->glyphs[i].glyph; - - (*glyphs)[i].x = - ((double) (x + run->glyphs->glyphs[i].geometry.x_offset)) - / ((double) PANGO_SCALE); - - (*glyphs)[i].y = - ((double) (y + run->glyphs->glyphs[i].geometry.y_offset)) - / ((double) PANGO_SCALE); - - if (gr->debug) printf(" (%ld @ %f,%f)", - (*glyphs)[i].index, - (*glyphs)[i].x, - (*glyphs)[i].y); - - x += run->glyphs->glyphs[i].geometry.width; - } - - if (gr->debug) printf("\n"); - begin_drawing_operation (env, gr); - cairo_show_glyphs (gr->cr, *glyphs, run->glyphs->num_glyphs); - end_drawing_operation (env, gr); - } -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGlyphVector - (JNIEnv *env, jobject obj, - jobject font, - jfloat x, jfloat y, jint n, - jintArray java_codes, - jfloatArray java_positions) -{ - - struct graphics2d *gr = NULL; - struct peerfont *pfont = NULL; - cairo_glyph_t *glyphs = NULL; - int *native_codes; - float *native_positions; - jint i = 0; - - gdk_threads_enter (); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - g_assert (obj != NULL); - g_assert (java_codes != NULL); - g_assert (java_positions != NULL); - - gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); - g_assert (pfont != NULL); - - install_font_peer(gr->cr, pfont, gr->debug); - - glyphs = g_malloc( sizeof(cairo_glyph_t) * n); - g_assert (glyphs != NULL); - - native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); - native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); - - for (i = 0; i < n; ++i) - { - glyphs[i].index = native_codes[i]; - glyphs[i].x = x + native_positions[ 2*i ]; - glyphs[i].y = y + native_positions[ 2*i + 1]; - } - - (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); - (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); - - begin_drawing_operation (env, gr); - cairo_show_glyphs (gr->cr, glyphs, n); - end_drawing_operation (env, gr); - - g_free(glyphs); - - gdk_threads_leave (); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout - (JNIEnv *env, jobject obj, jobject java_layout, jfloat x, jfloat y) -{ - /* - * FIXME: Some day we expect either cairo or pango will know how to make - * a pango layout paint to a cairo surface. that day is not yet here. - */ - - struct graphics2d *gr = NULL; - struct textlayout *tl = NULL; - PangoLayoutIter *i = NULL; - PangoLayoutRun *run = NULL; - cairo_glyph_t *glyphs = NULL; - gint n_glyphs = 0; - - g_assert (obj != NULL); - g_assert (java_layout != NULL); - - gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, obj); - tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, java_layout); - - g_assert (gr != NULL); - g_assert (tl != NULL); - g_assert (tl->pango_layout != NULL); - - if (gr->debug) printf ("painting pango layout\n"); - - gdk_threads_enter (); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - i = pango_layout_get_iter (tl->pango_layout); - g_assert (i != NULL); - - cairo_translate (gr->cr, x, y); - - do - { - run = pango_layout_iter_get_run (i); - if (run != NULL) - paint_glyph_run (env, gr, &glyphs, &n_glyphs, run); - } - while (pango_layout_iter_next_run (i)); - - if (glyphs != NULL) - g_free (glyphs); - - cairo_translate (gr->cr, -x, -y); - - pango_layout_iter_free (i); - - gdk_threads_leave (); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator - (JNIEnv *env, jobject obj, jint op) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_operator %d\n", op); - switch ((enum java_awt_alpha_composite_rule) op) - { - case java_awt_alpha_composite_CLEAR: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_CLEAR); - break; - - case java_awt_alpha_composite_SRC: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_SOURCE); - break; - - case java_awt_alpha_composite_SRC_OVER: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_OVER); - break; - - case java_awt_alpha_composite_DST_OVER: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OVER); - break; - - case java_awt_alpha_composite_SRC_IN: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_IN); - break; - - case java_awt_alpha_composite_DST_IN: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_IN); - break; - - case java_awt_alpha_composite_SRC_OUT: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_OUT); - break; - - case java_awt_alpha_composite_DST_OUT: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_OUT); - break; - - case java_awt_alpha_composite_DST: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST); - break; - - case java_awt_alpha_composite_SRC_ATOP: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_ATOP); - break; - - case java_awt_alpha_composite_DST_ATOP: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_DEST_ATOP); - break; - - case java_awt_alpha_composite_XOR: - cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBAColor - (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b, jdouble a) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - /* this is a very weird fact: GDK Pixbufs and RENDER drawables consider - colors in opposite pixel order. I have no idea why. thus when you - draw to a PixBuf, you must exchange the R and B components of your - color. */ - - if (gr->debug) - printf ("cairo_set_source_rgba (%f, %f, %f, %f)\n", r, g, b, a); - - if (gr->drawbuf) - cairo_set_source_rgba (gr->cr, b, g, r, a); - else - cairo_set_source_rgba (gr->cr, r, g, b, a); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule - (JNIEnv *env, jobject obj, jint rule) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule); - g_assert (gr != NULL); - switch ((enum java_awt_geom_path_iterator_winding_rule) rule) - { - case java_awt_geom_path_iterator_WIND_NON_ZERO: - cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_WINDING); - break; - case java_awt_geom_path_iterator_WIND_EVEN_ODD: - cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth - (JNIEnv *env, jobject obj, jdouble width) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_width %f\n", width); - cairo_set_line_width (gr->cr, width); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap - (JNIEnv *env, jobject obj, jint cap) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_cap %d\n", cap); - switch ((enum java_awt_basic_stroke_cap_rule) cap) - { - case java_awt_basic_stroke_CAP_BUTT: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_BUTT); - break; - - case java_awt_basic_stroke_CAP_ROUND: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_ROUND); - break; - - case java_awt_basic_stroke_CAP_SQUARE: - cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin - (JNIEnv *env, jobject obj, jint join) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_line_join %d\n", join); - switch ((enum java_awt_basic_stroke_join_rule) join) - { - case java_awt_basic_stroke_JOIN_MITER: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_MITER); - break; - - case java_awt_basic_stroke_JOIN_ROUND: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_ROUND); - break; - - case java_awt_basic_stroke_JOIN_BEVEL: - cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); - break; - } - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash - (JNIEnv *env, jobject obj, jdoubleArray dashes, jint ndash, jdouble offset) -{ - struct graphics2d *gr = NULL; - jdouble *dasharr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_dash\n"); - dasharr = (*env)->GetDoubleArrayElements (env, dashes, NULL); - g_assert (dasharr != NULL); - cairo_set_dash (gr->cr, dasharr, ndash, offset); - (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit - (JNIEnv *env, jobject obj, jdouble miter) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter); - cairo_set_miter_limit (gr->cr, miter); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) printf ("cairo_new_path\n"); - cairo_new_path (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo - (JNIEnv *env, jobject obj, jdouble x, jdouble y) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y); - cairo_move_to (gr->cr, x, y); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo - (JNIEnv *env, jobject obj, jdouble x, jdouble y) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y); - cairo_line_to (gr->cr, x, y); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo - (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) - printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", - x1, y1, x2, y2, x3, y3); - cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo - (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy); - cairo_rel_move_to (gr->cr, dx, dy); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo - (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy); - cairo_rel_line_to (gr->cr, dx, dy); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo - (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) - printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", - dx1, dy1, dx2, dy2, dx3, dy3); - cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle - (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) - printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height); - cairo_rectangle (gr->cr, x, y, width, height); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_close_path\n"); - cairo_close_path (gr->cr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_stroke\n"); - begin_drawing_operation (env, gr); - cairo_stroke (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - if (gr->debug) printf ("cairo_fill\n"); - begin_drawing_operation (env, gr); - cairo_fill (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - if (gr->debug) printf ("cairo_clip\n"); - begin_drawing_operation (env, gr); - cairo_reset_clip (gr->cr); - cairo_clip (gr->cr); - end_drawing_operation (env, gr); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter - (JNIEnv *env, jobject obj, jint filter) -{ - struct graphics2d *gr = NULL; - - gdk_threads_enter(); - - if (peer_is_disposed(env, obj)) - { - gdk_threads_leave(); - return; - } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->pattern == NULL) - return; - - if (gr->debug) printf ("cairo_pattern_set_filter %d\n", filter); - switch ((enum java_awt_rendering_hints_filter) filter) - { - case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); - break; - case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BILINEAR); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_FAST); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_NEAREST); - break; - case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY: - cairo_pattern_set_filter (gr->pattern, CAIRO_FILTER_BEST); - break; - } - - gdk_threads_leave(); -} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c index 7662800f0..89adcd1e5 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c @@ -1,5 +1,5 @@ /* gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,9 +35,43 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ +#include <glib.h> +#include <gdk/gdk.h> + #include "gdkfont.h" +#include "gdkdisplay.h" #include "gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h" +struct state_table *cp_gtk_native_display_state_table; + +jclass gdkGraphicsEnvironment_class; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_initStaticState +(JNIEnv *env, jclass klazz __attribute__((unused))) +{ + gdkGraphicsEnvironment_class = (*env)->NewGlobalRef + (env, klazz); + + NSA_DISPLAY_INIT(env, gdkGraphicsEnvironment_class); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeInitState +(JNIEnv *env, jobject obj) +{ + GdkDisplay *defaultDisplay; + + gdk_threads_enter(); + + /* Retrieve the default display. */ + defaultDisplay = gdk_display_get_default(); + + gdk_threads_leave(); + + /* Store display pointer in GdkGraphicsEnvironment instance. */ + NSA_SET_DISPLAY_PTR(env, obj, (void *) defaultDisplay); +} static gint cmp_families (const void *a, const void *b) @@ -101,3 +135,109 @@ Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetNumFontFamilies return num; } + +JNIEXPORT jobjectArray JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetScreenDevices +(JNIEnv *env, jobject obj) +{ + jmethodID gdkScreenGraphicsDevice_ctor, gdkScreenGraphicsDevice_init; + jclass gdkScreenGraphicsDevice_class; + int numScreens = 0, i = 0; + GdkDisplay *display; + jobjectArray array; + jobject instance; + + gdkScreenGraphicsDevice_class = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice"); + + gdkScreenGraphicsDevice_ctor = (*env)->GetMethodID + (env, gdkScreenGraphicsDevice_class, "<init>", + "(Lgnu/java/awt/peer/gtk/GdkGraphicsEnvironment;)V"); + + gdkScreenGraphicsDevice_init = (*env)->GetMethodID + (env, gdkScreenGraphicsDevice_class, "init", "()V"); + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, obj); + + gdk_threads_enter(); + + numScreens = gdk_display_get_n_screens(display); + + + /* Create a suitably sized array. */ + array = (*env)->NewObjectArray(env, + numScreens, + gdkScreenGraphicsDevice_class, + NULL); + + /* Create GdkScreenGraphicsDevice instances, store the native pointer to + * the GScreen object with them, run a 2nd initialization phase and + * put the new instance into the result array. + */ + for ( ; i < numScreens ; i++) + { + instance = (*env)->NewObject (env, + gdkScreenGraphicsDevice_class, + gdkScreenGraphicsDevice_ctor, + obj); + + NSA_SET_SCREEN_PTR(env, + instance, + gdk_display_get_screen(display, i)); + + gdk_threads_leave(); + (*env)->CallVoidMethod(env, + instance, + gdkScreenGraphicsDevice_init); + gdk_threads_enter(); + + (*env)->SetObjectArrayElement(env, array, i, instance); + } + + gdk_threads_leave(); + + return array; +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetDefaultScreenDevice +(JNIEnv *env, jobject obj) +{ + jclass gdkScreenGraphicsDevice_class; + jmethodID gdkScreenGraphicsDevice_ctor, gdkScreenGraphicsDevice_init; + jobject defaultDevice; + GdkScreen *defaultScreen; + + gdkScreenGraphicsDevice_class = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice"); + + gdkScreenGraphicsDevice_ctor = (*env)->GetMethodID + (env, gdkScreenGraphicsDevice_class, "<init>", + "(Lgnu/java/awt/peer/gtk/GdkGraphicsEnvironment;)V"); + + gdkScreenGraphicsDevice_init = (*env)->GetMethodID + (env, gdkScreenGraphicsDevice_class, "init", "()V"); + + /* Create the GdkScreenGraphicsDevice instance. */ + defaultDevice = (*env)->NewObject (env, + gdkScreenGraphicsDevice_class, + gdkScreenGraphicsDevice_ctor, + obj); + + gdk_threads_enter(); + + defaultScreen = gdk_screen_get_default(); + + gdk_threads_leave(); + + /* Class initialization will have set up the native_state storage + * mechanism for GdkScreenGraphicsDevice. + */ + NSA_SET_SCREEN_PTR(env, defaultDevice, defaultScreen); + + (*env)->CallVoidMethod(env, + defaultDevice, + gdkScreenGraphicsDevice_init); + + return defaultDevice; +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c new file mode 100644 index 000000000..965fb5a23 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c @@ -0,0 +1,354 @@ +/* gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ + +#include <jcl.h> + +#include <gdk/gdk.h> +#include <gdk/gdkx.h> + +#ifdef HAVE_XRANDR +#include <X11/Xlib.h> +#include <X11/extensions/Xrandr.h> +#endif + +#include "gdkdisplay.h" + +#include "gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.h" + +struct state_table *cp_gtk_native_screen_state_table; + +jclass gdkScreenGraphicsDevice_class; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_initStaticState +(JNIEnv *env, jclass klazz) +{ + gdkScreenGraphicsDevice_class = (*env)->NewGlobalRef + (env, klazz); + + NSA_SCREEN_INIT(env, gdkScreenGraphicsDevice_class); +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetFixedDisplayMode +(JNIEnv *env, jobject obj, jobject gdkGraphicsEnv __attribute__((unused))) +{ + jclass displayMode_class; + jmethodID displayMode_ctor; + GdkScreen *screen; + jobject fixedDisplayMode = NULL; +#ifdef HAVE_XRANDR + int temp1, temp2; + GdkDisplay *display; + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, gdkGraphicsEnv); + + gdk_threads_enter(); + + if (!XRRQueryExtension(GDK_DISPLAY_XDISPLAY(display), &temp1, &temp2)) + { + displayMode_class = (*env)->FindClass(env, "java/awt/DisplayMode"); + displayMode_ctor = (*env)->GetMethodID(env, + displayMode_class, + "<init>", + "(IIII)V"); + + screen = (GdkScreen *) NSA_GET_SCREEN_PTR(env, obj); + + fixedDisplayMode = (*env)->NewObject(env, + displayMode_class, + displayMode_ctor, + gdk_screen_get_width(screen), + gdk_screen_get_height(screen), + -1, + 0); + } + + gdk_threads_leave(); + +#else + + displayMode_class = (*env)->FindClass(env, "java/awt/DisplayMode"); + displayMode_ctor = (*env)->GetMethodID(env, + displayMode_class, + "<init>", + "(IIII)V"); + + screen = (GdkScreen *) NSA_GET_SCREEN_PTR(env, obj); + + fixedDisplayMode = (*env)->NewObject(env, + displayMode_class, + displayMode_ctor, + gdk_screen_get_width(screen), + gdk_screen_get_height(screen), + -1, + 0); + +#endif + return fixedDisplayMode; +} + +JNIEXPORT jstring JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetIDString +(JNIEnv *env, jobject obj) +{ + GdkScreen *screen; + gchar* displayName; + jstring string; + + screen = (GdkScreen *) NSA_GET_SCREEN_PTR(env, obj); + + gdk_threads_enter(); + + displayName = gdk_screen_make_display_name(screen); + + gdk_threads_leave(); + + string = (*env)->NewStringUTF(env, displayName); + + g_free(displayName); + + return string; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetDisplayModeRate +(JNIEnv *env, jobject obj __attribute__((unused)), jobject gdkGraphicsEnv __attribute__((unused))) +{ +#ifdef HAVE_XRANDR + + GdkDisplay *display; + XRRScreenConfiguration *config; + int rate; + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, gdkGraphicsEnv); + + gdk_threads_enter(); + + config = XRRGetScreenInfo (GDK_DISPLAY_XDISPLAY(display), GDK_ROOT_WINDOW()); + + rate = (int) XRRConfigCurrentRate (config); + + XRRFreeScreenConfigInfo (config); + + gdk_threads_leave(); + + return rate; +#else + JCL_ThrowException(env, + "java/lang/InternalError", + "Method should not have been invoked."); + + return -1; +#endif +} + +JNIEXPORT jint JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetDisplayModeIndex +(JNIEnv *env, jobject obj __attribute__((unused)), jobject gdkGraphicsEnv __attribute__((unused))) +{ +#ifdef HAVE_XRANDR + + GdkDisplay *display; + XRRScreenConfiguration *config; + SizeID index; + Rotation rotation; + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, gdkGraphicsEnv); + + gdk_threads_enter(); + + config = XRRGetScreenInfo (GDK_DISPLAY_XDISPLAY(display), GDK_ROOT_WINDOW()); + + index = XRRConfigCurrentConfiguration (config, &rotation); + + XRRFreeScreenConfigInfo (config); + + gdk_threads_leave(); + + return (int) index; + +#else + + JCL_ThrowException(env, + "java/lang/InternalError", + "Method should not have been invoked."); + + return -1; + +#endif +} + +JNIEXPORT jobjectArray JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetDisplayModes +(JNIEnv *env, jobject obj __attribute__((unused)), jobject gdkGraphicsEnv __attribute__((unused))) +{ +#ifdef HAVE_XRANDR + GdkDisplay *display; + XRRScreenConfiguration *config; + XRRScreenSize *screenSizes; + int nsizes = 0, nrates = 0, i = 0; + jclass x11DisplayMode_class; + jmethodID x11DisplayMode_ctor; + jobjectArray array; + jobject instance; + short *rates; + jshortArray shortArray; + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, gdkGraphicsEnv); + + gdk_threads_enter(); + + config = XRRGetScreenInfo (GDK_DISPLAY_XDISPLAY(display), GDK_ROOT_WINDOW()); + + screenSizes = XRRConfigSizes(config, &nsizes); + + x11DisplayMode_class = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice$X11DisplayMode"); + + x11DisplayMode_ctor = (*env)->GetMethodID(env, x11DisplayMode_class, "<init>", "(II[S)V"); + + array = (*env)->NewObjectArray(env, nsizes, x11DisplayMode_class, NULL); + + for (; i < nsizes ; i++) + { + /* Retrieves refresh rate information. */ + rates = XRRConfigRates(config, i, &nrates); + + /* Create a Java int array and put them in. */ + shortArray = (*env)->NewIntArray(env, nrates); + (*env)->SetShortArrayRegion(env, shortArray, 0, nrates, (jshort *) rates); + + /* Create a GdkScreenGraphicsDevice.X11DisplayMode instance. */ + instance = (*env)->NewObject(env, + x11DisplayMode_class, + x11DisplayMode_ctor, + screenSizes[i].width, + screenSizes[i].height, + shortArray); + + /* Put it into the result array. */ + (*env)->SetObjectArrayElement(env, array, i, instance); + } + + /* Free everything acquired by xlib. */ + XRRFreeScreenConfigInfo (config); + + gdk_threads_leave(); + + return array; +#else + JCL_ThrowException(env, + "java/lang/InternalError", + "Method should not have been invoked."); + + return NULL; + +#endif +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeSetDisplayMode +(JNIEnv *env, jobject obj __attribute__((unused)), jobject gdkGraphicsEnv __attribute__((unused)), jint index __attribute__((unused)), jshort rate __attribute__((unused))) +{ +#ifdef HAVE_XRANDR + GdkDisplay *display; + XRRScreenConfiguration *config; + Rotation rotation; + + display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, gdkGraphicsEnv); + + gdk_threads_enter(); + + config = XRRGetScreenInfo (GDK_DISPLAY_XDISPLAY(display), GDK_ROOT_WINDOW()); + + /* The rotation is not exposed to the Java API. So we retrieve its current + * value and set it to the same when switching resolution. + */ + XRRConfigCurrentConfiguration (config, &rotation); + + XRRSetScreenConfigAndRate (GDK_DISPLAY_XDISPLAY(display), + config, + GDK_ROOT_WINDOW(), + index, + rotation, + rate, + CurrentTime); + + XRRFreeScreenConfigInfo(config); + + gdk_threads_leave(); + +#else + JCL_ThrowException(env, + "java/lang/InternalError", + "Method should not have been invoked."); +#endif +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetBounds +(JNIEnv *env, jobject obj) +{ + jclass rectangle_class; + jmethodID rectangle_ctor; + GdkScreen *screen; + GdkWindow *window; + int x, y, w, h; + jobject instance; + + rectangle_class = (*env)->FindClass(env, "java/awt/Rectangle"); + + rectangle_ctor = (*env)->GetMethodID + (env, rectangle_class, "<init>", "(IIII)V"); + + screen = (GdkScreen *) NSA_GET_SCREEN_PTR(env, obj); + + gdk_threads_enter(); + + window = gdk_screen_get_root_window(screen); + + gdk_window_get_geometry(window, &x, &y, &w, &h, NULL); + + gdk_threads_leave(); + + instance = (*env)->NewObject(env, + rectangle_class, + rectangle_ctor, + x, y, w, h); + + return instance; +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c index edce3917d..849998791 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c @@ -1,5 +1,5 @@ /* gnu_java_awt_GdkTextLayout.c - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,9 +44,11 @@ #include <pango/pangofc-font.h> #include <freetype/ftglyph.h> #include <freetype/ftoutln.h> +#include "jcl.h" #include "native_state.h" #include "gdkfont.h" #include "gnu_java_awt_peer_gtk_GdkTextLayout.h" +#include "cairographics2d.h" struct state_table *cp_gtk_native_text_layout_state_table; @@ -60,6 +62,9 @@ typedef struct gp double sy; } generalpath ; +static void paint_glyph_run(cairo_t *cr, cairo_glyph_t **glyphs, + gint *n_glyphs, PangoLayoutRun *run); + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState (JNIEnv *env, jclass clazz) @@ -93,8 +98,6 @@ Java_gnu_java_awt_peer_gtk_GdkTextLayout_setText gchar *str = NULL; gint len = 0; - gdk_threads_enter (); - g_assert(self != NULL); g_assert(text != NULL); @@ -106,13 +109,37 @@ Java_gnu_java_awt_peer_gtk_GdkTextLayout_setText str = (gchar *)(*env)->GetStringUTFChars (env, text, NULL); g_assert (str != NULL); - pango_layout_set_text (tl->pango_layout, text, len); + gdk_threads_enter (); + + pango_layout_set_text (tl->pango_layout, str, len); (*env)->ReleaseStringUTFChars (env, text, str); gdk_threads_leave (); } +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_setFont (JNIEnv *env, jobject obj, jobject font) +{ + struct textlayout *tl; + struct peerfont *pf; + + g_assert(obj != NULL); + g_assert(font != NULL); + + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj); + g_assert(tl != NULL); + g_assert(tl->pango_layout != NULL); + pf = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert(pf != NULL); + + gdk_threads_enter (); + + pango_layout_set_font_description(tl->pango_layout, pf->desc); + + gdk_threads_leave (); +} + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_indexToPos (JNIEnv *env, jobject self, jint idx, jdoubleArray javaPos) @@ -207,10 +234,106 @@ Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose gdk_threads_leave (); } +/** + * Draw this textlayout on a cairo surface + * FIXME: Seems completely broken. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkTextLayout_cairoDrawGdkTextLayout + (JNIEnv *env, jobject obj, jlong cg2d, jfloat x, jfloat y) +{ + /* + * FIXME: Some day we expect either cairo or pango will know how to make + * a pango layout paint to a cairo surface. that day is not yet here. + */ + + struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, cg2d); + cairo_t *cr = gr->cr; + struct textlayout *tl = NULL; + PangoLayoutIter *i = NULL; + PangoLayoutRun *run = NULL; + cairo_glyph_t *glyphs = NULL; + gint n_glyphs = 0; + + tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj); + + g_assert (cr != NULL); + g_assert (tl != NULL); + g_assert (tl->pango_layout != NULL); + + gdk_threads_enter (); + + i = pango_layout_get_iter (tl->pango_layout); + g_assert (i != NULL); + + cairo_translate (cr, x, y); + + do + { + run = pango_layout_iter_get_run (i); + if (run != NULL) + paint_glyph_run (cr, &glyphs, &n_glyphs, run); + } + while (pango_layout_iter_next_run (i)); + + if (glyphs != NULL) + g_free (glyphs); + + cairo_translate (cr, -x, -y); + + pango_layout_iter_free (i); + + gdk_threads_leave (); +} + +static void +paint_glyph_run(cairo_t *cr, + cairo_glyph_t **glyphs, + gint *n_glyphs, + PangoLayoutRun *run) +{ + gint i = 0; + gint x = 0, y = 0; + + g_assert (cr != NULL); + g_assert (glyphs != NULL); + g_assert (n_glyphs != NULL); + g_assert (run != NULL); + + if (run->glyphs != NULL && run->glyphs->num_glyphs > 0) + { + if (*n_glyphs < run->glyphs->num_glyphs) + { + *glyphs = g_realloc(*glyphs, + (sizeof(cairo_glyph_t) + * run->glyphs->num_glyphs)); + *n_glyphs = run->glyphs->num_glyphs; + } + + g_assert (*glyphs != NULL); + + for (i = 0; i < run->glyphs->num_glyphs; ++i) + { + (*glyphs)[i].index = run->glyphs->glyphs[i].glyph; + + (*glyphs)[i].x = + ((double) (x + run->glyphs->glyphs[i].geometry.x_offset)) + / ((double) PANGO_SCALE); + + (*glyphs)[i].y = + ((double) (y + run->glyphs->glyphs[i].geometry.y_offset)) + / ((double) PANGO_SCALE); + + x += run->glyphs->glyphs[i].geometry.width; + } + cairo_show_glyphs (cr, *glyphs, run->glyphs->num_glyphs); + } +} + /* GetOutline code follows ****************************/ /********* Freetype callback functions *****************************/ -static int _moveTo( FT_Vector* to, +static int _moveTo( const FT_Vector* to, void *p) { JNIEnv *env; @@ -233,7 +356,7 @@ static int _moveTo( FT_Vector* to, return 0; } -static int _lineTo( FT_Vector* to, +static int _lineTo( const FT_Vector* to, void *p) { JNIEnv *env; @@ -255,8 +378,8 @@ static int _lineTo( FT_Vector* to, return 0; } -static int _quadTo( FT_Vector* cp, - FT_Vector* to, +static int _quadTo( const FT_Vector* cp, + const FT_Vector* to, void *p) { JNIEnv *env; @@ -280,9 +403,9 @@ static int _quadTo( FT_Vector* cp, return 0; } -static int _curveTo( FT_Vector* cp1, - FT_Vector* cp2, - FT_Vector* to, +static int _curveTo( const FT_Vector* cp1, + const FT_Vector* cp2, + const FT_Vector* to, void *p) { JNIEnv *env; @@ -320,10 +443,10 @@ Java_gnu_java_awt_peer_gtk_GdkTextLayout_getOutline PangoLayoutLine *current_line; FT_Outline_Funcs ftCallbacks = { - _moveTo, - _lineTo, - _quadTo, - _curveTo, + (FT_Outline_MoveToFunc) _moveTo, + (FT_Outline_LineToFunc) _lineTo, + (FT_Outline_ConicToFunc) _quadTo, + (FT_Outline_CubicToFunc) _curveTo, 0, 0 }; diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c index cb2c87238..7ce1185a4 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c @@ -242,14 +242,7 @@ clipboard_get_func (GtkClipboard *clipboard, pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage); if (pixbuf != NULL) - { - gtk_selection_data_set_pixbuf (selection, pixbuf); - - /* if the GtkImage is offscreen, this is a temporary pixbuf - which should be thrown out. */ - if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - } + gtk_selection_data_set_pixbuf (selection, pixbuf); } else if (info == URI_TARGET) { diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c index c60f48f51..766964314 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c @@ -186,10 +186,5 @@ Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImage gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf); - /* if the GtkImage is offscreen, this is a temporary pixbuf which should - be thrown out. */ - if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - gdk_threads_leave (); } diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c index dad6a1182..ff3fbe896 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c @@ -51,13 +51,11 @@ exception statement from your version. */ /* local stuff */ static GdkInterpType mapHints(jint hints); -static jboolean offScreen (JNIEnv * env, jobject obj); -static void *getData (JNIEnv * env, jobject obj); static void createRawData (JNIEnv * env, jobject obj, void *ptr); static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height); /** - * Loads a pixmap from a file. + * Loads a pixbuf from a file. */ JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf @@ -119,10 +117,14 @@ Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData if (pixbuf == NULL) { + g_object_unref (loader); createRawData (env, obj, NULL); return JNI_FALSE; } + g_object_ref (pixbuf); + g_object_unref (loader); + width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); @@ -137,7 +139,7 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf (JNIEnv *env, jobject obj) { int width, heigth; - GdkPixbuf *pixbuf = (GdkPixbuf *) getData (env, obj); + GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj); width = gdk_pixbuf_get_width (pixbuf); heigth = gdk_pixbuf_get_height (pixbuf); setWidthHeight(env, obj, width, heigth); @@ -194,9 +196,6 @@ Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv *env, jobject obj) } } - if (offScreen (env, obj) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); gdk_threads_leave (); @@ -211,7 +210,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj, jintArray pixels) { - GdkPixbuf *pixbuf = (GdkPixbuf *)getData (env, obj); + GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj); int width, height, rowstride; guchar *pixeldata; jint *src_array_iter, *src; @@ -236,10 +235,10 @@ Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj, } /** - * Allocates a Gtk Pixbuf or Pixmap. + * Allocates a Gtk Pixbuf */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv *env, jobject obj) +Java_gnu_java_awt_peer_gtk_GtkImage_createPixbuf(JNIEnv *env, jobject obj) { int width, height; jclass cls; @@ -254,35 +253,58 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv *env, jobject obj) g_assert (field != 0); height = (*env)->GetIntField (env, obj, field); - if (offScreen (env, obj) == JNI_FALSE) - createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - width, - height)); - else - createRawData (env, obj, gdk_pixmap_new (NULL, width, height, - gdk_rgb_get_visual ()->depth)); + createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height)); +} + +/** + * Allocates a Gtk Pixbuf + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkImage_initFromBuffer(JNIEnv *env, jobject obj, + jlong bufferPointer) +{ + int width, height; + jclass cls; + jfieldID field; + GdkPixbuf *pixbuf; + const guchar *bp = JLONG_TO_PTR(const guchar, bufferPointer); + + g_assert(bp != NULL); + cls = (*env)->GetObjectClass( env, obj ); + field = (*env)->GetFieldID( env, cls, "width", "I" ); + g_assert( field != 0 ); + width = (*env)->GetIntField( env, obj, field ); + + field = (*env)->GetFieldID( env, cls, "height", "I" ); + g_assert( field != 0 ); + height = (*env)->GetIntField( env, obj, field ); + + pixbuf = gdk_pixbuf_new_from_data( bp, + GDK_COLORSPACE_RGB, TRUE, 8, + width, height, width * 4, NULL, NULL ); + g_assert( pixbuf != NULL ); + createRawData( env, obj, pixbuf ); } /** - * Frees the Gtk Pixmap. + * Frees the Gtk Pixbuf. */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap(JNIEnv *env, jobject obj) +Java_gnu_java_awt_peer_gtk_GtkImage_freePixbuf(JNIEnv *env, jobject obj) { - if (offScreen (env, obj) == JNI_FALSE) - gdk_pixbuf_unref ((GdkPixbuf *)getData (env, obj)); - else - g_object_unref ((GdkPixmap *)getData (env, obj)); + gdk_pixbuf_unref (cp_gtk_image_get_pixbuf (env, obj)); } /** - * Sets this pixmap to a scaled version of the source pixmap. + * Sets this to a scaled version of the original pixbuf * width and height of the destination GtkImage must be set. */ JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv *env, +Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixbuf(JNIEnv *env, jobject destination, jobject source, jint hints) @@ -309,238 +331,25 @@ Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv *env, width, height, mapHints(hints)); - if (offScreen (env, source) == JNI_TRUE) - gdk_pixbuf_unref (pixbuf); - createRawData (env, destination, (void *)dst); } /** - * Draws the pixbuf at x, y, scaled to width and height and - * optionally composited with a given background color. - */ -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled - (JNIEnv *env, jobject obj, jobject gc_obj, - jint bg_red, jint bg_green, jint bg_blue, - jint x, jint y, jint width, jint height, jboolean composite) -{ - GdkPixbuf* dst; - struct graphics2d *g; - guint32 bgColor; - - gdk_threads_enter (); - - if (width <= 0 || height <= 0) - { - gdk_threads_leave (); - return; - } - - bgColor = ((bg_red & 0xFF) << 16) | - ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); - - g = (struct graphics2d *) NSA_GET_G2D_PTR (env, gc_obj); - - if (!g || !GDK_IS_DRAWABLE (g->drawable)) - { - gdk_threads_leave (); - return; - } - - if (offScreen (env, obj) == JNI_FALSE) - { - GdkPixbuf* pixbuf = (GdkPixbuf *)getData (env, obj); - - /* Scale and composite the image */ - if (composite == JNI_TRUE) - dst = gdk_pixbuf_composite_color_simple (pixbuf, - width, - height, - GDK_INTERP_BILINEAR, - 255, - width, - bgColor, - bgColor); - else - dst = gdk_pixbuf_scale_simple(pixbuf, - width, height, - GDK_INTERP_BILINEAR); - - gdk_cairo_set_source_pixbuf (g->cr, dst, (double) x, (double) y); - gdk_pixbuf_unref (dst); - - } else { - /* Get a pixmap */ - GdkPixmap* pixmap = (GdkPixmap *)getData (env, obj); - cairo_xlib_surface_set_drawable (g->surface, - GDK_PIXMAP_XID(pixmap), - width, - height); - } - - gdk_threads_leave (); -} - -/** - * Draws the pixbuf at x, y, scaled to width and height and - * optionally composited and/or flipped with a given background color. - */ -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped -(JNIEnv *env, jobject obj, jobject gc_obj, - jint bg_red, jint bg_green, jint bg_blue, -#if GTK_MINOR_VERSION > 4 - jboolean flipx, jboolean flipy, -#else - jboolean flipx __attribute__((unused)), - jboolean flipy __attribute__((unused)), -#endif - jint srcx, jint srcy, jint srcwidth, jint srcheight, - jint dstx, jint dsty, jint dstwidth, jint dstheight, - jboolean composite) -{ - GdkPixbuf *pixbuf; - GdkPixbuf *tmp, *dst; - struct graphics2d *g; - guint32 bgColor; - - gdk_threads_enter (); - - if (srcwidth <= 0 || srcheight <= 0 - || dstwidth <= 0 || dstheight <= 0) - { - gdk_threads_leave (); - return; - } - - bgColor = ((bg_red & 0xFF) << 16) | - ((bg_green & 0xFF) << 8) | (bg_blue & 0xFF); - - g = (struct graphics2d *) NSA_GET_G2D_PTR (env, gc_obj); - - if (!g || !GDK_IS_DRAWABLE (g->drawable)) - { - gdk_threads_leave (); - return; - } - - if (offScreen (env, obj) == JNI_FALSE) - { - pixbuf = (GdkPixbuf *)getData (env, obj); - - /* Get the source area */ - tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - srcwidth, - srcheight); - - gdk_pixbuf_copy_area (pixbuf, - srcx, srcy, - srcwidth, srcheight, - tmp, - 0, 0); /* dst x , dst y */ - } else { - /* Get a pixbuf from the pixmap */ - GdkDrawable *pixmap = (GdkDrawable *)getData(env, obj); - tmp = gdk_pixbuf_get_from_drawable (NULL, - pixmap, - gdk_drawable_get_colormap( pixmap ), - srcx, srcy, - 0, 0, /* dst x , dst y */ - srcwidth, srcheight); - } - - /* FIXME: This #if should be discarded once I feel comfortable about - GTK 2.6 dependence */ -#if GTK_MINOR_VERSION > 4 - /* Flip it if necessary. */ - if (flipx == JNI_TRUE) - { - GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, TRUE); - gdk_pixbuf_unref (tmp); - tmp = tmp2; - } - if (flipy == JNI_TRUE) - { - GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, FALSE); - gdk_pixbuf_unref (tmp); - tmp = tmp2; - } -#endif - - /* Scale and composite the image */ - if (composite == JNI_TRUE) - dst = gdk_pixbuf_composite_color_simple (tmp, - dstwidth, - dstheight, - GDK_INTERP_BILINEAR, - 255, - dstwidth, - bgColor, - bgColor); - else - dst = gdk_pixbuf_scale_simple(tmp, - dstwidth, dstheight, - GDK_INTERP_BILINEAR); - gdk_pixbuf_unref (tmp); - - gdk_cairo_set_source_pixbuf (g->cr, dst, (double) dstx, - (double) dsty); - gdk_pixbuf_unref (dst); - - gdk_threads_leave (); -} - -/** * Used by GtkFramePeer */ GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj) { - int width, height; - GdkPixbuf *pixbuf; - GdkPixmap* pixmap; jclass cls; - jfieldID field; - - if (offScreen (env, obj) == JNI_FALSE) - return (GdkPixbuf *)getData (env, obj); + jfieldID data_fid; + jobject data; cls = (*env)->GetObjectClass (env, obj); - field = (*env)->GetFieldID (env, cls, "width", "I"); - g_assert (field != 0); - width = (*env)->GetIntField (env, obj, field); - - field = (*env)->GetFieldID (env, cls, "height", "I"); - g_assert (field != 0); - height = (*env)->GetIntField (env, obj, field); - - /* Get a pixmap */ - pixmap = (GdkPixmap *)getData (env, obj); - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, - pixmap, - gdk_drawable_get_colormap( pixmap ), - 0, 0, /* src x , src y */ - 0, 0, /* dst x , dst y */ - width, height); - return pixbuf; -} - -/** - * Used by GdkGraphics - */ -GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj) -{ - if (offScreen (env, obj) == JNI_FALSE) - return NULL; - return (GdkPixmap *)getData (env, obj); -} + data_fid = (*env)->GetFieldID (env, cls, "pixbuf", + "Lgnu/classpath/Pointer;"); + g_assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); -jboolean cp_gtk_image_is_offscreen (JNIEnv *env, jobject obj) -{ - return offScreen(env, obj); + return (GdkPixbuf *)JCL_GetRawData (env, data); } /** @@ -585,18 +394,6 @@ static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height) (*env)->SetIntField (env, obj, field, (jint)height); } -/* Returns the value of the offScreen field. */ -static jboolean offScreen (JNIEnv *env, jobject obj) -{ - jclass cls; - jfieldID field; - - cls = (*env)->GetObjectClass (env, obj); - field = (*env)->GetFieldID (env, cls, "offScreen", "Z"); - g_assert (field != 0); - return (*env)->GetBooleanField (env, obj, field); -} - /* Store and get the pixbuf pointer */ static void createRawData (JNIEnv * env, jobject obj, void *ptr) @@ -606,7 +403,7 @@ createRawData (JNIEnv * env, jobject obj, void *ptr) jfieldID data_fid; cls = (*env)->GetObjectClass (env, obj); - data_fid = (*env)->GetFieldID (env, cls, "pixmap", + data_fid = (*env)->GetFieldID (env, cls, "pixbuf", "Lgnu/classpath/Pointer;"); g_assert (data_fid != 0); @@ -615,18 +412,3 @@ createRawData (JNIEnv * env, jobject obj, void *ptr) (*env)->SetObjectField (env, obj, data_fid, data); } -static void * -getData (JNIEnv * env, jobject obj) -{ - jclass cls; - jfieldID data_fid; - jobject data; - - cls = (*env)->GetObjectClass (env, obj); - data_fid = (*env)->GetFieldID (env, cls, "pixmap", - "Lgnu/classpath/Pointer;"); - g_assert (data_fid != 0); - data = (*env)->GetObjectField (env, obj, data_fid); - - return JCL_GetRawData (env, data); -} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c new file mode 100644 index 000000000..d7ef474e0 --- /dev/null +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c @@ -0,0 +1,195 @@ +/* gnu_java_awt_peer_gtk_VolatileImage.c + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "jcl.h" +#include "gtkpeer.h" +#include <gdk/gdkx.h> +#include <gdk/gdktypes.h> +#include <gdk/gdkprivate.h> +#include <gdk/gdkx.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf/gdk-pixdata.h> + +#include "gnu_java_awt_peer_gtk_GtkVolatileImage.h" +#include "cairographics2d.h" + + +/** + * Creates a cairo surface, ARGB32, native ordering, premultiplied alpha. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_awt_peer_gtk_GtkVolatileImage_init (JNIEnv *env, + jobject obj __attribute__ ((__unused__)), + jobject peer, + jint width, jint height) +{ + GtkWidget *widget = NULL; + GdkPixmap* pixmap; + void *ptr = NULL; + + gdk_threads_enter(); + + if( peer != NULL ) + { + ptr = NSA_GET_PTR (env, peer); + g_assert (ptr != NULL); + + widget = GTK_WIDGET (ptr); + g_assert (widget != NULL); + pixmap = gdk_pixmap_new( widget->window, width, height, -1 ); + } + else + pixmap = gdk_pixmap_new( NULL, width, height, 16 ); + + gdk_threads_leave(); + + g_assert( pixmap != NULL ); + + return PTR_TO_JLONG( pixmap ); +} + +/** + * Destroy the surface + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkVolatileImage_destroy +(JNIEnv *env __attribute__((unused)), jobject obj __attribute((unused)), + jlong pointer) +{ + GdkPixmap* pixmap = JLONG_TO_PTR(GdkPixmap, pointer); + if( pixmap != NULL ) + { + gdk_threads_enter(); + g_object_unref( pixmap ); + gdk_threads_leave(); + } +} + +/** + * Gets all pixels in an array + */ +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GtkVolatileImage_nativeGetPixels +(JNIEnv *env, jobject obj, jlong pointer) +{ + /* jint *pixeldata, *jpixdata; */ + jint *jpixdata; + GdkPixmap *pixmap; + jintArray jpixels; + int width, height, depth, size; + jclass cls; + jfieldID field; + + cls = (*env)->GetObjectClass (env, obj); + field = (*env)->GetFieldID (env, cls, "width", "I"); + g_assert (field != 0); + width = (*env)->GetIntField (env, obj, field); + + field = (*env)->GetFieldID (env, cls, "height", "I"); + g_assert (field != 0); + height = (*env)->GetIntField (env, obj, field); + + pixmap = JLONG_TO_PTR(GdkPixmap, pointer); + g_assert(pixmap != NULL); + + gdk_threads_enter(); + + /* get depth in bytes */ + depth = gdk_drawable_get_depth( pixmap ) >> 3; + size = width * height * 4; + jpixels = (*env)->NewIntArray ( env, size ); + jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL); + /* memcpy (jpixdata, pixeldata, size * sizeof( jint )); */ + + (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0); + + gdk_threads_leave(); + + return jpixels; +} + +/** + * Copy area + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkVolatileImage_nativeCopyArea +(JNIEnv *env __attribute__((unused)), jobject obj __attribute((unused)), + jlong pointer, jint x, jint y, jint w, jint h, jint dx, jint dy) +{ + GdkPixbuf *pixbuf; + GdkPixmap* pixmap = JLONG_TO_PTR(GdkPixmap, pointer); + + g_assert (pixmap != NULL); + + gdk_threads_enter(); + + pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h ); + gdk_pixbuf_get_from_drawable( pixbuf, pixmap, NULL, x, y, 0, 0, w, h ); + gdk_draw_pixbuf (pixmap, NULL, pixbuf, + 0, 0, x + dx, y + dy, + w, h, + GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkVolatileImage_nativeDrawVolatile +(JNIEnv *env __attribute__((unused)), jobject obj __attribute((unused)), + jlong pointer, jlong srcptr, jint x, jint y, jint w, jint h) +{ + GdkPixmap *dst, *src; + GdkGC *gc; + + src = JLONG_TO_PTR(GdkPixmap, srcptr); + dst = JLONG_TO_PTR(GdkPixmap, pointer); + g_assert (src != NULL); + g_assert (dst != NULL); + + gdk_threads_enter(); + + gc = gdk_gc_new( dst ); + gdk_draw_drawable(dst, + gc, + src, + 0, 0, + x, y, + w, h); + g_object_unref( gc ); + + gdk_threads_leave(); +} + diff --git a/native/jni/gtk-peer/gtkpeer.h b/native/jni/gtk-peer/gtkpeer.h index 6ae7b06ae..065d20608 100644 --- a/native/jni/gtk-peer/gtkpeer.h +++ b/native/jni/gtk-peer/gtkpeer.h @@ -101,53 +101,6 @@ extern struct state_table *cp_gtk_native_graphics2d_state_table; #define SWAPU32(w) \ (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) -/* - A graphics2d struct is both simpler and uglier than a graphics - struct. - - Most of the graphics2d drawing state is held in the referenced cairo_t - and corresponding cairo_surface_t, so we can ignore it. - - In addition to the cairo_t, we need to hold an extra reference to the - underlying GdkDrawable so its refcount matches the lifecycle of the java - Graphics object which is peering with us; also a reference to a byte - buffer and cairo_surface_t which contain the pattern you're drawing from - (if it exists). - - Finally, it is possible that we are using a non-RENDER capable X server, - therefore we will be drawing to an cairo_surface_t which is actually a - pixbuf. When this is the case, the pointer to a GdkPixbuf will be - non-NULL and any drawing operation needs to be bracketed by pixbuf - load/save operations. If the GdkPixbuf pointer is NULL, we will treat - the cairo_surface_t as RENDER-capable. - */ -struct graphics2d -{ - cairo_t *cr; - cairo_surface_t *surface; - GdkDrawable *drawable; - GdkWindow *win; - GdkPixbuf *drawbuf; - char *pattern_pixels; - cairo_surface_t *pattern_surface; - cairo_pattern_t *pattern; - gboolean debug; - enum - { - MODE_DRAWABLE_WITH_RENDER, - MODE_DRAWABLE_NO_RENDER, - MODE_JAVA_ARRAY - } - mode; - - /* Support for MODE_JAVA_ARRAY */ - jintArray jarray; - jint width, height; - jint *javabuf; - jint *javabuf_copy; - jboolean isCopy; -}; - /* New-style event masks. */ #define AWT_BUTTON1_DOWN_MASK (1 << 10) #define AWT_BUTTON2_DOWN_MASK (1 << 11) @@ -229,8 +182,10 @@ jint cp_gtk_state_to_awt_mods (guint state); /* Image helpers */ GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj); -GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj); -jboolean cp_gtk_image_is_offscreen (JNIEnv *env, jobject obj); + +/* Component Graphics helpers */ +void cp_gtk_grab_current_drawable(GtkWidget *widget, GdkDrawable **draw, + GdkWindow **win); /* JNI initialization functions */ void cp_gtk_button_init_jni (void); @@ -254,6 +209,8 @@ void cp_gtk_textcomponent_connect_signals (GObject *ptr, jobject *gref); /* Debugging */ void cp_gtk_print_current_thread (void); +GdkPixmap *cp_gtk_get_pixmap( JNIEnv *env, jobject obj); + #define SYNCHRONIZE_GDK 0 #define DEBUG_LOCKING 0 diff --git a/native/jni/java-io/java_io_VMFile.c b/native/jni/java-io/java_io_VMFile.c index 354df04ed..7a3fdaf43 100644 --- a/native/jni/java-io/java_io_VMFile.c +++ b/native/jni/java-io/java_io_VMFile.c @@ -1,5 +1,5 @@ /* java_io_VMFile.c - Native methods for java.io.File class - Copyright (C) 1998, 2004 Free Software Foundation, Inc. + Copyright (C) 1998, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -730,3 +730,237 @@ Java_java_io_VMFile_list (JNIEnv * env, jobject obj return (0); #endif /* not WITHOUT_FILESYSTEM */ } + +/*************************************************************************/ + +/* + * These two methods are used to maintain dynamically allocated + * buffers for getCanonicalPath without the overhead of calling + * realloc every time a buffer is modified. Buffers are sized + * at the smallest multiple of CHUNKSIZ that is greater than or + * equal to the desired length. The default CHUNKSIZ is 256, + * longer than most paths, so in most cases a getCanonicalPath + * will require only one malloc per buffer. + */ + +#define CHUNKLOG 8 +#define CHUNKSIZ (1 << CHUNKLOG) + +static int +nextChunkSize (int size) +{ + return ((size >> CHUNKLOG) + ((size & (CHUNKSIZ - 1)) ? 1 : 0)) << CHUNKLOG; +} + +static char * +maybeGrowBuf (JNIEnv *env, char *buf, int *size, int required) +{ + if (required > *size) + { + *size = nextChunkSize (required); + buf = JCL_realloc (env, buf, *size); + } + return buf; +} + +/*************************************************************************/ + +/* + * This method converts a path to canonical form on GNU/Posix systems. + * This involves the removal of redundant separators, references to + * "." and "..", and symbolic links. + * + * The conversion proceeds on a component-by-component basis: symbolic + * links and references to ".." are resolved as and when they occur. + * This means that if "/foo/bar" is a symbolic link to "/baz" then the + * canonical form of "/foo/bar/.." is "/" and not "/foo". + * + * In order to mimic the behaviour of proprietary JVMs, non-existant + * path components are allowed (a departure from the normal GNU system + * convention). This means that if "/foo/bar" is a symbolic link to + * "/baz", the canonical form of "/non-existant-directory/../foo/bar" + * is "/baz". + * + * Class: java_io_VMFile + * Method: toCanonicalForm + * Signature: (Ljava/lang/String)Ljava/lang/String + */ + +JNIEXPORT jstring JNICALL +Java_java_io_VMFile_toCanonicalForm (JNIEnv *env, + jclass class __attribute__ ((__unused__)), + jstring jpath) +{ +#ifndef WITHOUT_FILESYSTEM + const char *path; + char *src, *dst; + int srci, dsti; + int srcl, dstl; + int len; + int fschecks; +#if defined (HAVE_LSTAT) && defined (HAVE_READLINK) + struct stat sb; +#endif /* HAVE_LSTAT && HAVE_READLINK */ + + path = JCL_jstring_to_cstring (env, jpath); + if (path == NULL) + return NULL; + + /* It is the caller's responsibility to ensure the path is absolute. */ + if (path[0] == 0 || path[0] != '/') + { + JCL_free_cstring (env, jpath, path); + JCL_ThrowException (env, "java/lang/RuntimeException", "Not absolute"); + return NULL; + } + + len = strlen (path); + srcl = nextChunkSize (len + 1); + src = JCL_malloc (env, srcl); + if (src == NULL) + { + JCL_free_cstring (env, jpath, path); + return NULL; + } + strcpy (src, path); + JCL_free_cstring (env, jpath, path); + srci = 1; + + dstl = nextChunkSize (2); + dst = JCL_malloc (env, dstl); + if (dst == NULL) + { + JCL_free (env, src); + return NULL; + } + dst[0] = '/'; + dsti = 1; + + fschecks = JNI_TRUE; + + while (src[srci] != '\0') + { + int tmpi, dsti_save; + + /* Skip slashes. */ + while (src[srci] == '/') + srci++; + tmpi = srci; + /* Find next slash. */ + while (src[srci] != '/' && src[srci] != '\0') + srci++; + if (srci == tmpi) + /* We hit the end. */ + break; + len = srci - tmpi; + + /* Handle "." and "..". */ + if (len == 1 && src[tmpi] == '.') + continue; + if (len == 2 && src[tmpi] == '.' && src[tmpi + 1] == '.') + { + while (dsti > 1 && dst[dsti - 1] != '/') + dsti--; + if (dsti != 1) + dsti--; + /* Reenable filesystem checking if disabled, as we might + * have reversed over whatever caused the problem before. + * At least one proprietary JVM has inconsistencies because + * it does not do this. + */ + fschecks = JNI_TRUE; + continue; + } + + /* Handle real path components. */ + dst = maybeGrowBuf (env, + dst, &dstl, dsti + (dsti > 1 ? 1 : 0) + len + 1); + if (dst == NULL) + { + JCL_free (env, src); + return NULL; + } + dsti_save = dsti; + if (dsti > 1) + dst[dsti++] = '/'; + strncpy (&dst[dsti], &src[tmpi], len); + dsti += len; + if (fschecks == JNI_FALSE) + continue; + +#if defined (HAVE_LSTAT) && defined (HAVE_READLINK) + dst[dsti] = '\0'; + if (lstat (dst, &sb) == 0) + { + if (S_ISLNK (sb.st_mode)) + { + int tmpl = CHUNKSIZ; + char *tmp = JCL_malloc (env, tmpl); + if (tmp == NULL) + { + JCL_free (env, src); + JCL_free (env, dst); + return NULL; + } + + while (1) + { + tmpi = readlink (dst, tmp, tmpl); + if (tmpi < 1) + { + JCL_free (env, src); + JCL_free (env, dst); + JCL_free (env, tmp); + JCL_ThrowException (env, "java/io/IOException", + "readlink failed"); + return NULL; + } + if (tmpi < tmpl) + break; + tmpl += CHUNKSIZ; + tmp = JCL_realloc (env, tmp, tmpl); + } + + /* Prepend the link's path to src. */ + tmp = maybeGrowBuf (env, + tmp, &tmpl, tmpi + strlen (&src[srci]) + 1); + if (tmp == NULL) + { + JCL_free (env, src); + JCL_free (env, dst); + return NULL; + } + + strcpy (&tmp[tmpi], &src[srci]); + JCL_free (env, src); + src = tmp; + srcl = tmpl; + srci = 0; + + /* Either replace or append dst depending on whether the + * link is relative or absolute. + */ + dsti = src[0] == '/' ? 1 : dsti_save; + } + } + else + { + /* Something doesn't exist, or we don't have permission to + * read it, or a previous path component is a directory, or + * a symlink is looped. Whatever, we can't check the + * filesystem any more. + */ + fschecks = JNI_FALSE; + } +#endif /* HAVE_LSTAT && HAVE_READLINK */ + } + dst[dsti] = '\0'; + + jpath = (*env)->NewStringUTF (env, dst); + JCL_free (env, src); + JCL_free (env, dst); + return jpath; +#else /* not WITHOUT_FILESYSTEM */ + return NULL; +#endif /* not WITHOUT_FILESYSTEM */ +} diff --git a/native/jni/midi-dssi/dssi_data.h b/native/jni/midi-dssi/dssi_data.h index 8278f7b9e..27a4e2831 100644 --- a/native/jni/midi-dssi/dssi_data.h +++ b/native/jni/midi-dssi/dssi_data.h @@ -1,5 +1,5 @@ /* dssi_data.h - DSSI data - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -55,11 +55,6 @@ exception statement from your version. */ 1/40th of a second). */ #define EVENT_BUFFER_SIZE 1024 -/* Helper macros for going between pointers and jlongs. */ -#define JLONG_TO_PTR(T,P) ((T *)(long)P) -#define PTR_TO_JLONG(P) ((jlong)(long)P) - - /* Every DSSI Synthesizer has one of these associated with it. The Java class sees it as a "long" handle. */ diff --git a/native/jni/qt-peer/qtmenupeer.cpp b/native/jni/qt-peer/qtmenupeer.cpp index 1ac17145c..6f35c89b9 100644 --- a/native/jni/qt-peer/qtmenupeer.cpp +++ b/native/jni/qt-peer/qtmenupeer.cpp @@ -44,9 +44,11 @@ exception statement from your version. */ #include "slotcallbacks.h" #include "componentevent.h" -#define ADDMENU 0 -#define ADDITEM 1 -#define ADDSEPA 2 +typedef enum ActionType { + ActionMenu, + ActionItem, + ActionSeparator +} ActionType; // Sets the title, but also tear-off. class MenuTitleEvent : public AWTEvent { @@ -81,18 +83,18 @@ class MenuAction : public AWTEvent { private: QMenu *menu; QAction *action; - int isMenu; // 0 to add a menu, 1 to add an item, 2 to add a seperator + ActionType actionType; // type of action to add JavaVM *vm; jobject menuPeer; jobject itemPeer; public: MenuAction(JNIEnv *env, jobject mp, jobject ip, QMenu *m, QAction *a, - bool ismenu) : AWTEvent() + ActionType actionType) : AWTEvent() { menu = m; action = a; - isMenu = ismenu; + this->actionType = actionType; env->GetJavaVM( &vm ); menuPeer = env->NewGlobalRef( mp ); if( ip != NULL ) @@ -104,35 +106,22 @@ public: void runEvent() { JNIEnv *env; - QAction *newAction; // adding an action creates a new duplicate. vm->GetEnv((void **)&env, JNI_VERSION_1_1); - - switch(isMenu) - { - case ADDMENU: - newAction = menu->addMenu( (QMenu *)action ); - break; - case ADDITEM: - newAction = menu->addAction(action->text()); - newAction->setSeparator(action->isSeparator()); - newAction->setCheckable(action->isCheckable()); - // delete action; - break; - case ADDSEPA: - newAction = menu->addSeparator(); - break; - } + if (actionType == ActionMenu) + menu->addMenu ((QMenu *) action); + else + menu->addAction (action); jclass menuCls = env->GetObjectClass( menuPeer ); jmethodID mid = env->GetMethodID(menuCls, "add", "(J)V"); env->DeleteLocalRef(menuCls); - env->CallVoidMethod( menuPeer, mid, (jlong)newAction ); + env->CallVoidMethod( menuPeer, mid, (jlong)action ); env->DeleteGlobalRef( menuPeer ); if( itemPeer != NULL ) { - setNativeObject( env, itemPeer, newAction ); - connectAction(newAction, env, itemPeer); + setNativeObject( env, itemPeer, action ); + connectAction(action, env, itemPeer); env->DeleteGlobalRef( itemPeer ); } } @@ -190,7 +179,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_qt_QtMenuPeer_insertSeperator QMenu *menu = (QMenu *)getNativeObject( env, obj ); assert( menu ); mainThread->postEventToMain( new MenuAction( env, obj, NULL, - menu, NULL, ADDSEPA ) ); + menu, NULL, ActionSeparator ) ); } /* @@ -205,7 +194,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_qt_QtMenuPeer_insertItem QAction *action = (QAction *)getNativeObject( env, item ); assert( action ); - mainThread->postEventToMain( new MenuAction( env, obj, item, menu, action, ADDITEM )); + mainThread->postEventToMain( new MenuAction( env, obj, item, menu, action, ActionItem )); } /* @@ -220,7 +209,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_qt_QtMenuPeer_insertMenu QMenu *insMenu = (QMenu *)getNativeObject(env, menu); assert( insMenu ); - mainThread->postEventToMain( new MenuAction( env, obj, menu, thisMenu, (QAction *)insMenu, ADDMENU ) ); + mainThread->postEventToMain( new MenuAction( env, obj, menu, thisMenu, (QAction *)insMenu, ActionMenu ) ); } /* diff --git a/native/plugin/Makefile.am b/native/plugin/Makefile.am index 7358381eb..e1331fe45 100644 --- a/native/plugin/Makefile.am +++ b/native/plugin/Makefile.am @@ -4,15 +4,15 @@ libgcjwebplugin_la_SOURCES = gcjwebplugin.cc libgcjwebplugin_la_CXXFLAGS = \ -Wall -DAPPLETVIEWER_EXECUTABLE="\"$(bindir)/appletviewer\"" \ - $(MOZILLA_CFLAGS) $(GLIB_CFLAGS) + $(MOZILLA_CFLAGS) $(GLIB_CFLAGS) $(GTK_CFLAGS) libgcjwebplugin_la_LDFLAGS = -avoid-version \ - $(GLIB_LIBS) \ + $(GLIB_LIBS) $(GTK_LIBS) \ -lstdc++ -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - $(INSTALL) -d -m0755 $(DESTDIR)@PLUGIN_DIR@ - $(INSTALL) .libs/libgcjwebplugin.so $(DESTDIR)@PLUGIN_DIR@ +install-plugin: $(lib_LTLIBRARIES) + $(INSTALL) -d -m0755 $(DESTDIR)$(PLUGIN_DIR) + $(INSTALL) .libs/libgcjwebplugin.so $(DESTDIR)$(PLUGIN_DIR) -uninstall-libLTLIBRARIES: - rm -f $(DESTDIR)@PLUGIN_DIR@/libgcjwebplugin.so +uninstall-plugin: + rm -f $(DESTDIR)$(PLUGIN_DIR)/libgcjwebplugin.so diff --git a/native/plugin/gcjwebplugin.cc b/native/plugin/gcjwebplugin.cc index bbb9809be..ad65c7ef1 100644 --- a/native/plugin/gcjwebplugin.cc +++ b/native/plugin/gcjwebplugin.cc @@ -49,6 +49,10 @@ exception statement from your version. */ // GLib includes. #include <glib.h> +#include <glib/gstdio.h> + +// GTK includes. +#include <gtk/gtk.h> // gcjwebplugin includes. #include "config.h" @@ -75,6 +79,10 @@ exception statement from your version. */ g_printerr ("%s:%d: thread %p: Error: %s: %s\n", __FILE__, __LINE__, \ g_thread_self (), first, second) +#define PLUGIN_ERROR_THREE(first, second, third) \ + g_printerr ("%s:%d: thread %p: Error: %s: %s: %s\n", __FILE__, \ + __LINE__, g_thread_self (), first, second, third) + // Plugin information passed to about:plugins. #define PLUGIN_NAME "GCJ Web Browser Plugin" #define PLUGIN_DESC "The " PLUGIN_NAME " executes Java applets." @@ -113,8 +121,25 @@ exception statement from your version. */ #define PLUGIN_FILE_EXTS "class,jar,zip" #define PLUGIN_MIME_COUNT 1 -// Directory in which named pipes are created. -#define PIPE_DIRECTORY "/tmp" +// Security dialog messages. +#define RESPONSE_TRUST_APPLET "Trust Applet" +#define RESPONSE_TRUST_APPLET_ADD_TO_LIST "Trust Applet and Add to Whitelist" +#define SECURITY_WARNING \ + "%s wants to load an applet.\n" \ + "GNU Classpath's security implementation is not complete.\n" \ + "HOSTILE APPLETS WILL STEAL AND/OR DESTROY YOUR DATA!\n" +#define SECURITY_DESCRIPTION \ + "Click \"Cancel\" if you do not trust the source of this applet.\n" \ + "Click \"Trust Applet\" to load and run this applet now.\n" \ + "Click \"Trust Applet and Add To Whitelist\" to always load" \ + " and run this applet from now on, without asking.\n" \ + "The whitelist is a list of the URLs from which you trust" \ + " applets.\n" \ + "Your whitelist file is \" %s \"." +#define FAILURE_MESSAGE \ + "This page wants to load an applet.\n" \ + "The appletviewer is missing or not installed properly in \"" \ + APPLETVIEWER_EXECUTABLE "\"." // Documentbase retrieval required definition. static NS_DEFINE_IID (kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID); @@ -122,6 +147,16 @@ static NS_DEFINE_IID (kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID); // Browser function table. static NPNetscapeFuncs browserFunctions; +// Data directory for plugin. +static gchar* data_directory; + +// Whitelist filename +static gchar* whitelist_filename; + +// Keeps track of initialization. NP_Initialize should only be +// called once. +gboolean initialized = false; + // GCJPluginData stores all the data associated with a single plugin // instance. A separate plugin instance is created for each <APPLET> // tag. For now, each plugin instance spawns its own applet viewer @@ -173,6 +208,12 @@ typedef union static void plugin_data_new (GCJPluginData** data); // Documentbase retrieval. static gchar* plugin_get_documentbase (NPP instance); +// plugin failure handling. +static bool plugin_failed (); +// Whitelist handling. +static bool plugin_user_trusts_documentbase (char* documentbase); +static bool plugin_ask_user_about_documentbase (char* documentbase); +static void plugin_add_documentbase_to_whitelist (char* documentbase); // Callback used to monitor input pipe status. static gboolean plugin_in_pipe_callback (GIOChannel* source, GIOCondition condition, @@ -181,7 +222,7 @@ static gboolean plugin_in_pipe_callback (GIOChannel* source, static gboolean plugin_out_pipe_callback (GIOChannel* source, GIOCondition condition, gpointer plugin_data); -static void plugin_start_appletviewer (GCJPluginData* data); +static NPError plugin_start_appletviewer (GCJPluginData* data); static gchar* plugin_create_applet_tag (int16 argc, char* argn[], char* argv[]); static void plugin_send_message_to_appletviewer (GCJPluginData* data, @@ -195,6 +236,11 @@ static void plugin_data_destroy (GCJPluginData** data); static GMutex* plugin_instance_mutex = NULL; // A counter used to create uniquely named pipes. static gulong plugin_instance_counter = 0; +// The user's documentbase whitelist. +static GIOChannel* whitelist_file = NULL; +// A global variable for reporting GLib errors. This must be free'd +// and set to NULL after each use. +static GError* channel_error = NULL; // Functions prefixed by GCJ_ are instance functions. They are called // by the browser and operate on instances of GCJPluginData. @@ -224,7 +270,7 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, NPError np_error = NPERR_NO_ERROR; GCJPluginData* data = NULL; - GError* channel_error = NULL; + gchar* documentbase = NULL; gchar* read_message = NULL; gchar* applet_tag = NULL; @@ -278,13 +324,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, goto cleanup_appletviewer_mutex; } + if (!plugin_user_trusts_documentbase (documentbase)) + { + PLUGIN_ERROR ("User does not trust applet."); + np_error = NPERR_GENERIC_ERROR; + goto cleanup_appletviewer_mutex; + } + // Create appletviewer-to-plugin pipe which we refer to as the input // pipe. // data->in_pipe_name - data->in_pipe_name = g_strdup_printf (PIPE_DIRECTORY - "/gcj-%s-appletviewer-to-plugin", - data->instance_string); + data->in_pipe_name = g_strdup_printf ("%s/gcj-%s-appletviewer-to-plugin", + data_directory, data->instance_string); if (!data->in_pipe_name) { PLUGIN_ERROR ("Failed to create input pipe name."); @@ -305,9 +357,8 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, // output pipe. // data->out_pipe_name - data->out_pipe_name = g_strdup_printf (PIPE_DIRECTORY - "/gcj-%s-plugin-to-appletviewer", - data->instance_string); + data->out_pipe_name = g_strdup_printf ("%s/gcj-%s-plugin-to-appletviewer", + data_directory, data->instance_string); if (!data->out_pipe_name) { @@ -332,9 +383,17 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, // appletviewer, create the IO channels and install the channel // watch callbacks. g_mutex_lock (data->appletviewer_mutex); - - plugin_start_appletviewer (data); - + + np_error = plugin_start_appletviewer (data); + + // If the appletviewer is not installed, then a dialog box will + // show up and the plugin will be killed. + if (np_error != NPERR_NO_ERROR) + { + if (plugin_failed ()) + goto cleanup_applet_failure; + } + // Create plugin-to-appletviewer channel. The default encoding for // the file is UTF-8. // data->out_to_appletviewer @@ -342,16 +401,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, "w", &channel_error); if (!data->out_to_appletviewer) { - PLUGIN_ERROR_TWO ("Failed to create output channel", - channel_error->message); + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to create output channel", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to create output channel"); + np_error = NPERR_GENERIC_ERROR; goto cleanup_out_to_appletviewer; } - if (channel_error) - { - g_error_free (channel_error); - channel_error = NULL; - } // Watch for hangup and error signals on the output pipe. data->out_watch_source = @@ -366,16 +428,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, "r", &channel_error); if (!data->in_from_appletviewer) { - PLUGIN_ERROR_TWO ("Failed to create input channel", - channel_error->message); + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to create input channel", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to create input channel"); + np_error = NPERR_GENERIC_ERROR; goto cleanup_in_from_appletviewer; } - if (channel_error) - { - g_error_free (channel_error); - channel_error = NULL; - } // Watch for hangup and error signals on the input pipe. data->in_watch_source = @@ -390,16 +455,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, &channel_error) != G_IO_STATUS_NORMAL) { - PLUGIN_ERROR_TWO ("Receiving confirmation from appletviewer failed", - channel_error->message); + if (channel_error) + { + PLUGIN_ERROR_TWO ("Receiving confirmation from appletviewer failed", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Receiving confirmation from appletviewer failed"); + np_error = NPERR_GENERIC_ERROR; goto cleanup_in_watch_source; } - if (channel_error) - { - g_error_free (channel_error); - channel_error = NULL; - } PLUGIN_DEBUG ("GCJ_New: got confirmation that appletviewer is running."); data->appletviewer_alive = TRUE; @@ -448,7 +516,8 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, // cleanup_out_pipe: // Delete output pipe. unlink (data->out_pipe_name); - + + cleanup_applet_failure: cleanup_out_pipe_name: g_free (data->out_pipe_name); data->out_pipe_name = NULL; @@ -480,7 +549,6 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode, instance->pdata = NULL; cleanup_done: - g_free (tag_message); tag_message = NULL; g_free (applet_tag); @@ -602,6 +670,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window) window->width); plugin_send_message_to_appletviewer (data, width_message); g_free (width_message); + width_message = NULL; // Store the new width. data->window_width = window->width; @@ -619,6 +688,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window) window->height); plugin_send_message_to_appletviewer (data, height_message); g_free (height_message); + height_message = NULL; // Store the new height. data->window_height = window->height; @@ -651,6 +721,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window) (gulong) window->window); plugin_send_message_to_appletviewer (data, window_message); g_free (window_message); + window_message = NULL; g_mutex_unlock (data->appletviewer_mutex); @@ -833,6 +904,201 @@ plugin_get_documentbase (NPP instance) return documentbase_copy; } +// This function shows a error message if the appletviewer has +// not been installed. It returns true, if the user presses the +// ok button. +static bool +plugin_failed () +{ + GtkWidget* dialog = NULL; + GtkWidget* ok_button = NULL; + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + FAILURE_MESSAGE); + ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_OK, + GTK_RESPONSE_OK); + gtk_widget_show_all (dialog); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) + { + gtk_widget_destroy (dialog); + return true; + } + return false; +} + +// plugin_user_trusts_documentbase returns true if the given +// documentbase is in the documentbase whitelist. Otherwise it asks +// the user if he trusts the given documentbase by calling +// plugin_ask_user_about_documentbase. +static bool +plugin_user_trusts_documentbase (char* documentbase) +{ + bool applet_in_whitelist = false; + + // Check if documentbase is in whitelist. + while (true) + { + gchar* whitelist_entry = NULL; + gchar* newline_documentbase = NULL; + + // If reading fails, break out of this loop with + // applet_in_whitelist still set to false. + if (g_io_channel_read_line (whitelist_file, &whitelist_entry, + NULL, NULL, &channel_error) + != G_IO_STATUS_NORMAL) + { + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to read line from whitelist file", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to open whitelist file."); + g_free (whitelist_entry); + whitelist_entry = NULL; + break; + } + + newline_documentbase = g_strdup_printf ("%s\n", documentbase); + if (!strcmp (newline_documentbase, whitelist_entry)) + { + applet_in_whitelist = true; + g_free (newline_documentbase); + newline_documentbase = NULL; + g_free (whitelist_entry); + whitelist_entry = NULL; + break; + } + g_free (whitelist_entry); + whitelist_entry = NULL; + g_free (newline_documentbase); + newline_documentbase = NULL; + } + + return applet_in_whitelist ? true + : plugin_ask_user_about_documentbase (documentbase); +} + +// plugin_add_documentbase_to_whitelist adds the given documentbase to +// the user's documentbase whitelist. +static void +plugin_add_documentbase_to_whitelist (char* documentbase) +{ + gsize bytes_written = 0; + char* newline_documentbase = NULL; + GIOStatus status = G_IO_STATUS_NORMAL; + + newline_documentbase = g_strdup_printf ("%s\n", documentbase); + status = g_io_channel_write_chars (whitelist_file, + newline_documentbase, -1, &bytes_written, + &channel_error); + g_free (newline_documentbase); + newline_documentbase = NULL; + + if (status != G_IO_STATUS_NORMAL) + { + if (channel_error) + { + PLUGIN_ERROR_TWO ("Error writing to whitelist file", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Error writing to whitelist file."); + } + + if (g_io_channel_flush (whitelist_file, &channel_error) + != G_IO_STATUS_NORMAL) + { + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to write whitelist file", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to write whitelist file."); + } + + if (g_io_channel_shutdown (whitelist_file, TRUE, &channel_error) + != G_IO_STATUS_NORMAL) + { + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to close whitelist file", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to close whitelist file."); + } +} + +// plugin_ask_user_about_documentbase puts up a dialog box that asks if the +// user trusts applets from this documentbase. The user has three +// options: "Cancel", "Trust Applet" and "Trust Applet and Add to +// Whitelist". If the user selects Cancel (the default) then a +// generic error code is returned from GCJ_New, telling the browser +// that the applet failed to load. If the user selects "Trust Applet" +// then plugin loading proceeds. If the user selects "Trust Applet +// and Add to Whitelist" then this documentbase is added to the user's +// applet whitelist and plugin loading proceeds. +static bool +plugin_ask_user_about_documentbase (char* documentbase) +{ + GtkWidget* dialog = NULL; + GtkWidget* ok_button = NULL; + GtkWidget* cancel_button = NULL; + GtkWidget* whitelist_button = NULL; + gint dialog_response = GTK_RESPONSE_NONE; + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + SECURITY_WARNING, + documentbase); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + SECURITY_DESCRIPTION, whitelist_filename); + + cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), + RESPONSE_TRUST_APPLET, + GTK_RESPONSE_OK); + whitelist_button = gtk_dialog_add_button (GTK_DIALOG (dialog), + RESPONSE_TRUST_APPLET_ADD_TO_LIST, + GTK_RESPONSE_APPLY); + gtk_widget_grab_focus (cancel_button); + + gtk_widget_show_all (dialog); + dialog_response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + if (dialog_response == GTK_RESPONSE_CANCEL) + { + // The user does not trust this documentbase. + return false; + } + else if (dialog_response == GTK_RESPONSE_APPLY) + { + // The user wants this documentbase added to his documentbase + // whitelist. + plugin_add_documentbase_to_whitelist (documentbase); + } + // The user trusts this documentbase. + return true; +} + // plugin_in_pipe_callback is called when data is available on the // input pipe, or when the appletviewer crashes or is killed. It may // be called after data has been destroyed in which case it simply @@ -858,7 +1124,6 @@ plugin_in_pipe_callback (GIOChannel* source, if (condition & G_IO_IN) { - GError* channel_error = NULL; gchar* message = NULL; if (g_io_channel_read_line (data->in_from_appletviewer, @@ -866,8 +1131,15 @@ plugin_in_pipe_callback (GIOChannel* source, &channel_error) != G_IO_STATUS_NORMAL) { - PLUGIN_ERROR_TWO ("Failed to read line from input channel", - channel_error->message); + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to read line from input channel", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to read line from input channel"); } else { @@ -899,12 +1171,6 @@ plugin_in_pipe_callback (GIOChannel* source, g_print (" PIPE: plugin read %s\n", message); } - if (channel_error) - { - g_error_free (channel_error); - channel_error = NULL; - } - g_free (message); message = NULL; @@ -958,14 +1224,14 @@ plugin_out_pipe_callback (GIOChannel* source, return FALSE; } -static void +static NPError plugin_start_appletviewer (GCJPluginData* data) { PLUGIN_DEBUG ("plugin_start_appletviewer"); - + NPError error = NPERR_NO_ERROR; + if (!data->appletviewer_alive) { - GError* spawn_error = NULL; gchar* command_line[3] = { NULL, NULL, NULL }; command_line[0] = g_strdup (APPLETVIEWER_EXECUTABLE); @@ -977,25 +1243,32 @@ plugin_start_appletviewer (GCJPluginData* data) command_line[2] = NULL; if (!g_spawn_async (NULL, command_line, NULL, (GSpawnFlags) 0, - NULL, NULL, NULL, &spawn_error)) + NULL, NULL, NULL, &channel_error)) { - PLUGIN_ERROR_TWO ("Failed to spawn applet viewer", - spawn_error->message); + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to spawn applet viewer", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to spawn applet viewer"); + error = NPERR_GENERIC_ERROR; goto cleanup; } cleanup: g_free (command_line[0]); + command_line[0] = NULL; g_free (command_line[1]); + command_line[1] = NULL; g_free (command_line[2]); - if (spawn_error) - { - g_error_free (spawn_error); - spawn_error = NULL; - } + command_line[2] = NULL; } PLUGIN_DEBUG ("plugin_start_appletviewer return"); + return error; } // Build up the applet tag string that we'll send to the applet @@ -1015,30 +1288,35 @@ plugin_create_applet_tag (int16 argc, char* argn[], char* argv[]) gchar* code = g_strdup_printf ("CODE=\"%s\" ", argv[i]); applet_tag = g_strconcat (applet_tag, code, NULL); g_free (code); + code = NULL; } else if (!g_ascii_strcasecmp (argn[i], "codebase")) { gchar* codebase = g_strdup_printf ("CODEBASE=\"%s\" ", argv[i]); applet_tag = g_strconcat (applet_tag, codebase, NULL); g_free (codebase); + codebase = NULL; } else if (!g_ascii_strcasecmp (argn[i], "archive")) { gchar* archive = g_strdup_printf ("ARCHIVE=\"%s\" ", argv[i]); applet_tag = g_strconcat (applet_tag, archive, NULL); g_free (archive); + archive = NULL; } else if (!g_ascii_strcasecmp (argn[i], "width")) { gchar* width = g_strdup_printf ("WIDTH=\"%s\" ", argv[i]); applet_tag = g_strconcat (applet_tag, width, NULL); g_free (width); + width = NULL; } else if (!g_ascii_strcasecmp (argn[i], "height")) { gchar* height = g_strdup_printf ("HEIGHT=\"%s\" ", argv[i]); applet_tag = g_strconcat (applet_tag, height, NULL); g_free (height); + height = NULL; } else { @@ -1046,10 +1324,14 @@ plugin_create_applet_tag (int16 argc, char* argn[], char* argv[]) // characters will pass through the pipe. if (argv[i] != '\0') { - gchar* escaped = g_strescape (argv[i], NULL); + gchar* escaped = NULL; + + escaped = g_strescape (argv[i], NULL); parameters = g_strconcat (parameters, "<PARAM NAME=\"", argn[i], "\" VALUE=\"", escaped, "\">", NULL); + g_free (escaped); + escaped = NULL; } } } @@ -1073,7 +1355,6 @@ plugin_send_message_to_appletviewer (GCJPluginData* data, gchar const* message) if (data->appletviewer_alive) { - GError* channel_error = NULL; gchar* newline_message = NULL; gsize bytes_written = 0; @@ -1086,27 +1367,34 @@ plugin_send_message_to_appletviewer (GCJPluginData* data, gchar const* message) if (g_io_channel_write_chars (data->out_to_appletviewer, newline_message, -1, &bytes_written, &channel_error) - != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to write bytes to output channel", - channel_error->message); - - if (channel_error) + != G_IO_STATUS_NORMAL) { - g_error_free (channel_error); - channel_error = NULL; - } + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to write bytes to output channel", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to write bytes to output channel"); + } if (g_io_channel_flush (data->out_to_appletviewer, &channel_error) != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to flush bytes to output channel", - channel_error->message); - - if (channel_error) { - g_error_free (channel_error); - channel_error = NULL; + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to flush bytes to output channel", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to flush bytes to output channel"); } g_free (newline_message); + newline_message = NULL; g_print (" PIPE: plugin wrote %s\n", message); } @@ -1135,7 +1423,6 @@ plugin_stop_appletviewer (GCJPluginData* data) if (data->appletviewer_alive) { // Shut down the appletviewer. - GError* channel_error = NULL; gsize bytes_written = 0; if (data->out_to_appletviewer) @@ -1143,36 +1430,45 @@ plugin_stop_appletviewer (GCJPluginData* data) if (g_io_channel_write_chars (data->out_to_appletviewer, "shutdown", -1, &bytes_written, &channel_error) != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to write shutdown message to" - " appletviewer", channel_error->message); - - if (channel_error) { - g_error_free (channel_error); - channel_error = NULL; + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to write shutdown message to" + " appletviewer", channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to write shutdown message to"); } if (g_io_channel_flush (data->out_to_appletviewer, &channel_error) != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to write shutdown message to" - " appletviewer", channel_error->message); - - if (channel_error) { - g_error_free (channel_error); - channel_error = NULL; + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to write shutdown message to" + " appletviewer", channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to write shutdown message to"); } if (g_io_channel_shutdown (data->out_to_appletviewer, TRUE, &channel_error) != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to shut down appletviewer" - " output channel", channel_error->message); - - if (channel_error) { - g_error_free (channel_error); - channel_error = NULL; + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to shut down appletviewer" + " output channel", channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to shut down appletviewer"); } } @@ -1181,13 +1477,16 @@ plugin_stop_appletviewer (GCJPluginData* data) if (g_io_channel_shutdown (data->in_from_appletviewer, TRUE, &channel_error) != G_IO_STATUS_NORMAL) - PLUGIN_ERROR_TWO ("Failed to shut down appletviewer" - " input channel", channel_error->message); - - if (channel_error) { - g_error_free (channel_error); - channel_error = NULL; + if (channel_error) + { + PLUGIN_ERROR_TWO ("Failed to shut down appletviewer" + " input channel", channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to shut down appletviewer"); } } } @@ -1267,18 +1566,25 @@ plugin_data_destroy (GCJPluginData** data) // implement and initializes a local table with browser functions that // we may wish to call. Called once, after browser startup and before // the first plugin instance is created. +// The field 'initialized' is set to true once this function has +// finished. If 'initialized' is already true at the beginning of +// this function, then it is evident that NP_Initialize has already +// been called. There is no need to call this function more than once and +// this workaround avoids any duplicate calls. NPError NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) { PLUGIN_DEBUG ("NP_Initialize"); - - if ((browserTable == NULL) || (pluginTable == NULL)) + + if (initialized) + return NPERR_NO_ERROR; + else if ((browserTable == NULL) || (pluginTable == NULL)) { PLUGIN_ERROR ("Browser or plugin function table is NULL."); return NPERR_INVALID_FUNCTABLE_ERROR; } - + // Ensure that the major version of the plugin API that the browser // expects is not more recent than the major version of the API that // we've implemented. @@ -1307,6 +1613,45 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) return NPERR_INVALID_FUNCTABLE_ERROR; } + data_directory = g_strconcat(getenv("HOME"), "/.gcjwebplugin", NULL); + whitelist_filename = g_strconcat (data_directory, "/whitelist.txt", NULL); + // Make sure the plugin data directory exists, creating it if + // necessary. + if (!g_file_test (data_directory, + (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) + { + int file_error = 0; + + file_error = g_mkdir (data_directory, 0700); + if (file_error != 0) + { + PLUGIN_ERROR_THREE ("Failed to create data directory", + data_directory, + strerror (errno)); + return NPERR_GENERIC_ERROR; + } + } + + // Open the user's documentbase whitelist. + whitelist_file = g_io_channel_new_file (whitelist_filename, + "a+", &channel_error); + if (!whitelist_file) + { + if (channel_error) + { + PLUGIN_ERROR_THREE ("Failed to open whitelist file", + whitelist_filename, + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR_TWO ("Failed to open whitelist file", + whitelist_filename); + + return NPERR_GENERIC_ERROR; + } + // Store in a local table the browser functions that we may use. browserFunctions.version = browserTable->version; browserFunctions.size = browserTable->size; @@ -1339,7 +1684,8 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) pluginTable->print = NewNPP_PrintProc (GCJ_Print); pluginTable->urlnotify = NewNPP_URLNotifyProc (GCJ_URLNotify); pluginTable->getvalue = NewNPP_GetValueProc (GCJ_GetValue); - + + initialized = true; plugin_instance_mutex = g_mutex_new (); PLUGIN_DEBUG ("NP_Initialize: using " APPLETVIEWER_EXECUTABLE "."); @@ -1402,9 +1748,32 @@ NP_Shutdown (void) PLUGIN_DEBUG ("NP_Shutdown"); // Free mutex. - g_mutex_free (plugin_instance_mutex); - plugin_instance_mutex = NULL; + if (plugin_instance_mutex) + { + g_mutex_free (plugin_instance_mutex); + plugin_instance_mutex = NULL; + } + if (whitelist_file) + { + g_io_channel_close (whitelist_file); + whitelist_file = NULL; + } + + if (data_directory) + { + g_free (data_directory); + data_directory = NULL; + } + + if (whitelist_filename) + { + g_free (whitelist_filename); + whitelist_filename = NULL; + } + + initialized = false; + PLUGIN_DEBUG ("NP_Shutdown return"); return NPERR_NO_ERROR; |