diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 13 | ||||
-rw-r--r-- | README.nanox | 126 | ||||
-rw-r--r-- | configure.in | 259 | ||||
-rw-r--r-- | gdk/Makefile.am | 68 | ||||
-rw-r--r-- | gdk/linux-fb/Makefile.am | 11 | ||||
-rw-r--r-- | gdk/linux-fb/gdkpoly-generic.h | 291 | ||||
-rw-r--r-- | gdk/linux-fb/gdkpolyreg-generic.c | 616 | ||||
-rw-r--r-- | gdk/linux-fb/gdkregion-generic.c | 1505 | ||||
-rw-r--r-- | gdk/linux-fb/gdkregion-generic.h | 162 | ||||
-rw-r--r-- | gdk/nanox/Makefile.am | 14 | ||||
-rw-r--r-- | gdk/nanox/gdkpoly-generic.h | 291 | ||||
-rw-r--r-- | gdk/nanox/gdkpolyreg-generic.c | 616 | ||||
-rw-r--r-- | gdk/nanox/gdkregion-generic.c | 1505 | ||||
-rw-r--r-- | gdk/nanox/gdkregion-generic.h | 167 | ||||
-rw-r--r-- | gdk/x11/Makefile.am | 7 | ||||
-rw-r--r-- | gtk-config.in | 9 | ||||
-rw-r--r-- | gtk/Makefile.am | 46 |
23 files changed, 377 insertions, 5407 deletions
@@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 0f939d27e8..14fe06306e 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +Mon Jun 5 19:32:53 CEST 2000 Paolo Molaro <lupus@linuxcare.com> + + * configure.in, gtk-config.in, gdk/Makefile.am, gdk/*/Makefile.am, + gtk/Makefile.am: make it possible to configure gtk for different + targets on the same platform. The library name is now + libgtk-$target-$version.so. gtk-config accepts a --target x11|nanox|linux-fb + flag. Only the x11 target compiles right now. + * gdk/gdkregion-generic.h, gdk/gdkregion-generic.c, gdk/gdkpoly-generic.h, + gdk/gdkpolyreg-generic.c: move generic region code in the main GDK dir. + * gdk/nanox/gdk*generic*: delete generic region code. + * gdk/linux-fb/gdk*generic*: delete generic region code. + * README.nanox: update information. + Tue Jun 6 10:53:59 2000 Owen Taylor <otaylor@redhat.com> * gtk/gtktoolbar.c (gtk_toolbar_prepend_widget): Fix to diff --git a/README.nanox b/README.nanox index 8c75896148..79909f2a24 100644 --- a/README.nanox +++ b/README.nanox @@ -21,134 +21,12 @@ We need to be able to clip and change the background of windows at runtime for apps to not look so ugly! Fonts: wait for better nano-X font implementation. Properties on windows. - +Provide a pango module. If you want to work on this port or get additional informnation, get in touch with me. -To get the beast to compile you also need to apply the patch below -(any auto* wizard here?): the issue of having two gtk libraries in the -system needs to be addressed too, maybe use libgtk-x11-1.4.so and -libgtk-nanox-1.4.so ... +Configure gtk with the --with-gdktarget=nanox to compile with nano-X support. Paolo Molaro lupus@linuxcare.com - -Index: acconfig.h -=================================================================== -RCS file: /cvs/gnome/gtk+/acconfig.h,v -retrieving revision 1.16 -diff -u -r1.16 acconfig.h ---- acconfig.h 1999/03/20 00:52:29 1.16 -+++ acconfig.h 2000/05/06 11:52:38 -@@ -49,6 +49,8 @@ - /* Most machines will be happy with int or void. IRIX requires '...' */ - #undef SIGNAL_ARG_TYPE - -+#undef USE_NANOX -+ - /* #undef PACKAGE */ - /* #undef VERSION */ - -Index: configure.in -=================================================================== -RCS file: /cvs/gnome/gtk+/configure.in,v -retrieving revision 1.142 -diff -u -r1.142 configure.in ---- configure.in 2000/05/04 00:29:46 1.142 -+++ configure.in 2000/05/06 11:52:38 -@@ -99,6 +99,8 @@ - AC_ARG_WITH(locale, [ --with-locale=LOCALE locale name you want to use ]) - - AC_ARG_WITH(xinput, [ --with-xinput=[no/gxi/xfree] support XInput ]) -+AC_ARG_ENABLE(nanox, [ --enable-nanox use nano-X instead of X11 [default=no]], -+ , enable_nanox="no") - - if test "x$enable_debug" = "xyes"; then - test "$cflags_set" = set || CFLAGS="$CFLAGS -g" -@@ -322,6 +324,8 @@ - saved_cflags="$CFLAGS" - saved_ldflags="$LDFLAGS" - -+if text "x$enable_nanox" = "xno"; then -+ - CFLAGS="$CFLAGS $X_CFLAGS" - LDFLAGS="$LDFLAGS $X_LDFLAGS $X_LIBS" - -@@ -465,6 +469,13 @@ - GTK_LOCALE_FLAGS="-DX_LOCALE" - fi - -+else -+AC_CHECK_LIB(nano-X, GrOpen) -+LIBS="-lnano-X $LIBS" -+ AC_DEFINE(USE_NANOX) -+AM_CONDITIONAL(USE_NANOX, test x$enable_nanox = xyes) -+fi # if enable_nanox -+ - # Checks for header files. - AC_HEADER_STDC - -@@ -602,8 +613,13 @@ - esac - ],[ - # Currently we always use X11 on those systems where we run configure... -+if test x$enable_nanox = xno; then - gdk_windowing=' - #define GDK_WINDOWING_X11' -+else -+gdk_windowing=' -+#define GDK_WINDOWING_NANOX' -+fi - if test x$gdk_wchar_h = xyes; then - gdk_wc=' - #define GDK_HAVE_WCHAR_H 1' -@@ -629,6 +645,7 @@ - docs/Makefile - gdk/Makefile - gdk/x11/Makefile -+gdk/nanox/Makefile - gdk/win32/Makefile - gtk/Makefile - gtk/gtkfeatures.h -Index: gdk/Makefile.am -=================================================================== -RCS file: /cvs/gnome/gtk+/gdk/Makefile.am,v -retrieving revision 1.41 -diff -u -r1.41 Makefile.am ---- gdk/Makefile.am 2000/04/05 04:11:10 1.41 -+++ gdk/Makefile.am 2000/05/06 11:52:38 -@@ -1,6 +1,10 @@ - ## Makefile.am for gtk+/gdk - -+if USE_NANOX -+SUBDIRS=win32 nanox -+else - SUBDIRS=x11 win32 -+endif - - EXTRA_DIST = \ - gdkconfig.h.win32 \ -@@ -36,8 +40,13 @@ - -lm \ - @STRIP_END@ - -+if USE_NANOX - libgdk_la_LIBADD = \ -+ nanox/libgdk-nanox.la -+else -+libgdk_la_LIBADD = \ - x11/libgdk-x11.la -+endif - - # - # setup source file variables -@@ -138,3 +147,8 @@ - @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \ - echo $$p; \ - done -+ -+noinst_PROGRAMS = simple -+simple_DEPENDENCIES = libgdk.la simple.c -+simple_LDADD = libgdk.la -+ diff --git a/configure.in b/configure.in index da74abef4d..5a24288c8f 100644 --- a/configure.in +++ b/configure.in @@ -100,6 +100,18 @@ AC_ARG_WITH(locale, [ --with-locale=LOCALE locale name you want to use ]) AC_ARG_WITH(xinput, [ --with-xinput=[no/gxi/xfree] support XInput ]) +gdktarget=x11 +gdktargetlib=libgdk-x11.la +gtktargetlib=libgtk-x11.la +AC_ARG_WITH(gdktarget, [ --with-gdktarget=[x11/nanox/linux-fb] select GDK target [default=x11] ], + gdktarget=$with_gdktarget) + +AC_SUBST(gdktarget) +case $gdktarget in + x11|nanox|linux-fb) ;; + *) AC_MSG_ERROR([Invalid target for GDK: use x11, nanox or linux-fb.]);; +esac + if test "x$enable_debug" = "xyes"; then test "$cflags_set" = set || CFLAGS="$CFLAGS -g" GTK_DEBUG_FLAGS="-DG_ENABLE_DEBUG" @@ -311,47 +323,47 @@ AC_CHECK_HEADERS(dirent.h, AC_DEFINE(HAVE_DIRENT_H)) AC_CHECK_HEADERS(pwd.h, AC_DEFINE(HAVE_PWD_H)) AC_CHECK_HEADERS(sys/time.h, AC_DEFINE(HAVE_SYS_TIME_H)) +if test "x$gdktarget" = "xx11"; then + # Find the X11 include and library directories + AC_PATH_X + AC_PATH_XTRA -# Find the X11 include and library directories -AC_PATH_X -AC_PATH_XTRA - -if test "x$x_includes" = "x"; then - x_includes="/usr/include" -fi + if test "x$x_includes" = "x"; then + x_includes="/usr/include" + fi -saved_cflags="$CFLAGS" -saved_ldflags="$LDFLAGS" + saved_cflags="$CFLAGS" + saved_ldflags="$LDFLAGS" -CFLAGS="$CFLAGS $X_CFLAGS" -LDFLAGS="$LDFLAGS $X_LDFLAGS $X_LIBS" + CFLAGS="$CFLAGS $X_CFLAGS" + LDFLAGS="$LDFLAGS $X_LDFLAGS $X_LIBS" -if test "x$no_x" = "xyes"; then - AC_MSG_ERROR([ + if test "x$no_x" = "xyes"; then + AC_MSG_ERROR([ *** X libraries or include files not found. Check 'config.log' for *** more details.]) -fi + fi -# Checks for libraries. -# Check for the X11 library -AC_CHECK_LIB(X11, XOpenDisplay, x_libs="-lX11 $X_EXTRA_LIBS", - AC_MSG_ERROR([*** libX11 not found. Check 'config.log' for more details.]), - $X_EXTRA_LIBS) - -if test "x$enable_shm" = "xyes"; then - # Check for the Xext library (needed for XShm extention) - AC_CHECK_LIB(Xext, XShmAttach, - x_libs="-lXext $x_libs", - # On AIX, it is in XextSam instead, but we still need -lXext - AC_CHECK_LIB(XextSam, XShmAttach, - x_libs="-lXextSam -lXext $x_libs", - no_xext_lib=yes, $x_libs), - $x_libs) -fi + # Checks for libraries. + # Check for the X11 library + AC_CHECK_LIB(X11, XOpenDisplay, x_libs="-lX11 $X_EXTRA_LIBS", + AC_MSG_ERROR([*** libX11 not found. Check 'config.log' for more details.]), + $X_EXTRA_LIBS) + + if test "x$enable_shm" = "xyes"; then + # Check for the Xext library (needed for XShm extention) + AC_CHECK_LIB(Xext, XShmAttach, + x_libs="-lXext $x_libs", + # On AIX, it is in XextSam instead, but we still need -lXext + AC_CHECK_LIB(XextSam, XShmAttach, + x_libs="-lXextSam -lXext $x_libs", + no_xext_lib=yes, $x_libs), + $x_libs) + fi -# Check for shaped window extension + # Check for shaped window extension -AC_CHECK_LIB(Xext, XShapeCombineMask, + AC_CHECK_LIB(Xext, XShapeCombineMask, if test -z "`echo $x_libs | grep "\-lXext" 2> /dev/null`"; then x_libs="-lXext $x_libs" fi @@ -359,44 +371,134 @@ AC_CHECK_LIB(Xext, XShapeCombineMask, , $x_libs) -# Check for XConvertCase (X11R6 specific) + # Check for XConvertCase (X11R6 specific) -AC_CHECK_LIB(X11, XConvertCase, + AC_CHECK_LIB(X11, XConvertCase, AC_DEFINE(HAVE_XCONVERTCASE), , $x_libs) -# Check for XIM support. + # Check for XIM support. -AC_CHECK_LIB(X11, XUnregisterIMInstantiateCallback, + AC_CHECK_LIB(X11, XUnregisterIMInstantiateCallback, : , enable_xim_inst="no", $x_libs) -# On Solaris, calling XRegisterIMInstantiateCallback seems to -# cause an immediate segfault, so we disable it, unless -# the user specifically forces it to be on. + # On Solaris, calling XRegisterIMInstantiateCallback seems to + # cause an immediate segfault, so we disable it, unless + # the user specifically forces it to be on. -if test x$enable_xim_inst = xmaybe ; then - case host in - *-*-solaris*) + if test x$enable_xim_inst = xmaybe ; then + case host in + *-*-solaris*) enable_xim_inst="no" ;; - *) + *) enable_xim_inst="yes" ;; - esac -fi + esac + fi + + if test "x$enable_xim" = "xyes"; then + GTK_XIM_FLAGS="-DUSE_XIM" + if test "x$enable_xim_inst" = "xyes"; then + AC_DEFINE(USE_X11R6_XIM) + fi + fi -if test "x$enable_xim" = "xyes"; then - GTK_XIM_FLAGS="-DUSE_XIM" - if test "x$enable_xim_inst" = "xyes"; then - AC_DEFINE(USE_X11R6_XIM) + x_cflags="$X_CFLAGS" + x_ldflags="$X_LDFLAGS $X_LIBS" + + # set up things for XInput + + if test "x$with_xinput" = "xgxi" || test "x$with_xinput" = "xyes"; then + AC_DEFINE(XINPUT_GXI) + xinput_progs=gxid + x_libs="-lXi $x_libs" + elif test "x$with_xinput" = "xxfree"; then + AC_DEFINE(XINPUT_XFREE) + x_libs="-lXi $x_libs" + else + AC_DEFINE(XINPUT_NONE) + fi + + AM_CONDITIONAL(XINPUT_GXI, test x$with_xinput = xgxi) + AM_CONDITIONAL(XINPUT_XFREE, test x$with_xinput = xxfree) + + if test "x$enable_shm" = "xyes"; then + # Check for shared memory + AC_CHECK_HEADER(sys/ipc.h, AC_DEFINE(HAVE_IPC_H), no_sys_ipc=yes) + AC_CHECK_HEADER(sys/shm.h, AC_DEFINE(HAVE_SHM_H), no_sys_shm=yes) + + # Check for the X shared memory extension header file + AC_MSG_CHECKING(X11/extensions/XShm.h) + if test "x$no_xext_lib" = "xyes"; then + AC_MSG_RESULT(no) + no_xshm=yes + else + if test -f "$x_includes/X11/extensions/XShm.h"; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_XSHM_H) + else + AC_MSG_RESULT(no) + no_xshm=yes + fi + fi fi + + more_cflags="$x_cflags" + more_ldflags="$x_ldflags" + more_libs="$x_libs" + more_includes="$x_includes" + + # these are already defined above + #gdktargetlib = "libgdk-x11.la" + #gtktargetlib = "libgtk-x11.la" + + AM_CONDITIONAL(USE_X11, true) fi -x_cflags="$X_CFLAGS" -x_ldflags="$X_LDFLAGS $X_LIBS" +if test "x$gdktarget" = "xnanox"; then + AC_CHECK_LIB(nano-X, GrOpen,,AC_MSG_ERROR([nano-X libraries not found.])) + # nano-X may require additional libraries + more_cflags= + more_ldflags= + more_libs="-lnano-X" + more_includes= + + gdktargetlib = "libgdk-nanox.la" + gtktargetlib = "libgtk-nanox.la" + + with_xinput=no + AC_DEFINE(XINPUT_NONE) + x_cflags= + x_includes= + x_ldflags= + x_libs= + xinput_progs= + AM_CONDITIONAL(USE_NANOX, true) +fi + +if test "x$gdktarget" = "xlinux-fb"; then + more_cflags= + more_ldflags= + more_libs= + more_includes= + + gdktargetlib = "libgdk-linux-fb.la" + gtktargetlib = "libgtk-linux-fb.la" + + with_xinput=no + AC_DEFINE(XINPUT_NONE) + x_cflags= + x_includes= + x_ldflags= + x_libs= + xinput_progs= + + AM_CONDITIONAL(USE_LINUX_FB, true) +fi # # Check for Pango @@ -415,23 +517,6 @@ AC_CHECK_LIB(pango, pango_context_new, :, AC_MSG_ERROR([ *** Pango not found. Pango is required to build *** GTK+. For more information see http://www.pango.org]), $PANGO_LIBS $x_ldflags $x_libs) - -# set up things for XInput - -if test "x$with_xinput" = "xgxi" || test "x$with_xinput" = "xyes"; then - AC_DEFINE(XINPUT_GXI) - xinput_progs=gxid - x_libs="-lXi $x_libs" -elif test "x$with_xinput" = "xxfree"; then - AC_DEFINE(XINPUT_XFREE) - x_libs="-lXi $x_libs" -else - AC_DEFINE(XINPUT_NONE) -fi - -AM_CONDITIONAL(XINPUT_GXI, test x$with_xinput = xgxi) -AM_CONDITIONAL(XINPUT_XFREE, test x$with_xinput = xxfree) - CFLAGS="$saved_cflags" LDFLAGS="$saved_ldflags" @@ -441,26 +526,13 @@ AC_SUBST(x_ldflags) AC_SUBST(x_libs) AC_SUBST(xinput_progs) -if test "x$enable_shm" = "xyes"; then - # Check for shared memory - AC_CHECK_HEADER(sys/ipc.h, AC_DEFINE(HAVE_IPC_H), no_sys_ipc=yes) - AC_CHECK_HEADER(sys/shm.h, AC_DEFINE(HAVE_SHM_H), no_sys_shm=yes) +AC_SUBST(more_cflags) +AC_SUBST(more_includes) +AC_SUBST(more_ldflags) +AC_SUBST(more_libs) +AC_SUBST(gdktargetlib) +AC_SUBST(gtktargetlib) - # Check for the X shared memory extension header file - AC_MSG_CHECKING(X11/extensions/XShm.h) - if test "x$no_xext_lib" = "xyes"; then - AC_MSG_RESULT(no) - no_xshm=yes - else - if test -f "$x_includes/X11/extensions/XShm.h"; then - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_XSHM_H) - else - AC_MSG_RESULT(no) - no_xshm=yes - fi - fi -fi # Check if X_LOCALE definition is necessary @@ -621,8 +693,17 @@ _______EOF esac ],[ # Currently we always use X11 on those systems where we run configure... -gdk_windowing=' +if test "x$gdktarget" = "xx11" ; then + gdk_windowing=' #define GDK_WINDOWING_X11' +elif test "x$gdktarget" = "xnanox" ; then + gdk_windowing=' +#define GDK_WINDOWING_NANOX' +elif test "x$gdktarget" = "xlinux-fb" ; then + gdk_windowing=' +#define GDK_WINDOWING_FB' +fi + if test x$gdk_wchar_h = xyes; then gdk_wc=' #define GDK_HAVE_WCHAR_H 1' @@ -652,6 +733,8 @@ docs/Makefile gdk/Makefile gdk/x11/Makefile gdk/win32/Makefile +gdk/nanox/Makefile +gdk/linux-fb/Makefile gtk/Makefile gtk/gtkfeatures.h gtk/gtkcompat.h diff --git a/gdk/Makefile.am b/gdk/Makefile.am index 1936d9c552..722453088b 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -1,6 +1,6 @@ ## Makefile.am for gtk+/gdk -SUBDIRS=x11 win32 +SUBDIRS=x11 win32 nanox linux-fb EXTRA_DIST = \ gdkconfig.h.win32 \ @@ -8,7 +8,7 @@ EXTRA_DIST = \ makefile.cygwin \ makefile.msc -INCLUDES = @STRIP_BEGIN@ \ +common_includes = @STRIP_BEGIN@ \ -DG_LOG_DOMAIN=\"Gdk\" \ -I$(top_srcdir) \ -I$(top_builddir)/gdk \ @@ -17,30 +17,27 @@ INCLUDES = @STRIP_BEGIN@ \ @GTK_LOCALE_FLAGS@ \ @PANGO_CFLAGS@ \ @GLIB_CFLAGS@ \ - @x_cflags@ \ + @more_cflags@ \ @STRIP_END@ -# -# libraries to compile and install -# -lib_LTLIBRARIES = libgdk.la +INCLUDES = $(common_includes) +gtarget=@gdktarget@ # libtool stuff: set version and export symbols for resolving -libgdkincludedir = $(includedir)/gdk -libgdk_la_LDFLAGS = @STRIP_BEGIN@ \ +# since automake doesn't support conditionalized libsomething_la_LDFLAGS +# we use the general approach here +LDFLAGS = @STRIP_BEGIN@ \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) \ -export-dynamic \ + -rpath @prefix@/lib \ @PANGO_LIBS@ \ @GLIB_DEPLIBS@ \ - @x_ldflags@ \ - @x_libs@ \ + @more_ldflags@ \ + @more_libs@ \ -lm \ @STRIP_END@ -libgdk_la_LIBADD = \ - x11/libgdk-x11.la - # # setup source file variables # @@ -90,16 +87,55 @@ gdk_c_sources = @STRIP_BEGIN@ \ gdkimage.c \ gdkinternals.h \ gdkpango.c \ + gdkpoly-generic.h \ + gdkpolyreg-generic.c \ gdkrgb.c \ gdkrectangle.c \ + gdkregion-generic.c \ + gdkregion-generic.h \ gdkwindow.c \ @STRIP_END@ # # setup GDK sources and their dependancies # -libgdkinclude_HEADERS = $(gdk_public_h_sources) -libgdk_la_SOURCES = $(gdk_c_sources) +extra = @gdktargetlib@ + +if USE_X11 +libgdk_x11_includedir = $(includedir)/gdk + +libgdk_x11_la_LIBADD = \ + $(gtarget)/libgdk-$(gtarget).la + +libgdk_x11_include_HEADERS = $(gdk_public_h_sources) +libgdk_x11_la_SOURCES = $(gdk_c_sources) +endif + +if USE_NANOX +libgdk_nanox_includedir = $(includedir)/gdk + +libgdk_nanox_la_LIBADD = \ + $(gtarget)/libgdk-$(gtarget).la + +libgdk_nanox_include_HEADERS = $(gdk_public_h_sources) +libgdk_nanox_la_SOURCES = $(gdk_c_sources) +endif + +if USE_LINUX_FB +libgdk_linux_fb_includedir = $(includedir)/gdk + +libgdk_linux_fb_la_LIBADD = \ + $(gtarget)/libgdk-$(gtarget).la + +libgdk_linux_fb_include_HEADERS = $(gdk_public_h_sources) +libgdk_linux_fb_la_SOURCES = $(gdk_c_sources) +endif + +# now define the real one to workaround automake's mishandling +lib_LTLIBRARIES = $(extra) + +EXTRA_LTLIBRARIES = libgdk-x11.la libgdk-nanox.la libgdk-linux-fb.la + MAINTAINERCLEANFILES += EXTRA_HEADERS += EXTRA_DIST += diff --git a/gdk/linux-fb/Makefile.am b/gdk/linux-fb/Makefile.am index bdaeb24a5b..ace052e06f 100644 --- a/gdk/linux-fb/Makefile.am +++ b/gdk/linux-fb/Makefile.am @@ -18,6 +18,8 @@ LDFLAGS = @STRIP_BEGIN@ \ -lm \ @STRIP_END@ +if USE_LINUX_FB + lib_LTLIBRARIES = libgdk-fb.la noinst_PROGRAMS=test-fb @@ -38,12 +40,9 @@ libgdk_fb_la_SOURCES = \ gdkmain-fb.c \ gdkpixmap-fb.c \ gdkproperty-fb.c \ - gdkpolyreg-generic.c \ - gdkregion-generic.c \ gdkselection-fb.c \ gdkvisual-fb.c \ gdkwindow-fb.c \ - gdkx.h \ gdkprivate-fb.h \ gdkinputprivate.h \ gdkinput-ps2.c \ @@ -59,3 +58,9 @@ libgdk_fb_la_SOURCES = \ mizerclip.c \ mizerline.c \ mispans.c +else +lib_LTLIBRARIES = +noinst_PROGRAMS= + +endif + diff --git a/gdk/linux-fb/gdkpoly-generic.h b/gdk/linux-fb/gdkpoly-generic.h deleted file mode 100644 index 660c689adb..0000000000 --- a/gdk/linux-fb/gdkpoly-generic.h +++ /dev/null @@ -1,291 +0,0 @@ -/* $TOG: poly.h /main/5 1998/02/06 17:47:27 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -/* - * This file contains a few macros to help track - * the edge of a filled object. The object is assumed - * to be filled in scanline order, and thus the - * algorithm used is an extension of Bresenham's line - * drawing algorithm which assumes that y is always the - * major axis. - * Since these pieces of code are the same for any filled shape, - * it is more convenient to gather the library in one - * place, but since these pieces of code are also in - * the inner loops of output primitives, procedure call - * overhead is out of the question. - * See the author for a derivation if needed. - */ - - -/* - * In scan converting polygons, we want to choose those pixels - * which are inside the polygon. Thus, we add .5 to the starting - * x coordinate for both left and right edges. Now we choose the - * first pixel which is inside the pgon for the left edge and the - * first pixel which is outside the pgon for the right edge. - * Draw the left pixel, but not the right. - * - * How to add .5 to the starting x coordinate: - * If the edge is moving to the right, then subtract dy from the - * error term from the general form of the algorithm. - * If the edge is moving to the left, then add dy to the error term. - * - * The reason for the difference between edges moving to the left - * and edges moving to the right is simple: If an edge is moving - * to the right, then we want the algorithm to flip immediately. - * If it is moving to the left, then we don't want it to flip until - * we traverse an entire pixel. - */ -#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \ - int dx; /* local storage */ \ -\ - /* \ - * if the edge is horizontal, then it is ignored \ - * and assumed not to be processed. Otherwise, do this stuff. \ - */ \ - if ((dy) != 0) { \ - xStart = (x1); \ - dx = (x2) - xStart; \ - if (dx < 0) { \ - m = dx / (dy); \ - m1 = m - 1; \ - incr1 = -2 * dx + 2 * (dy) * m1; \ - incr2 = -2 * dx + 2 * (dy) * m; \ - d = 2 * m * (dy) - 2 * dx - 2 * (dy); \ - } else { \ - m = dx / (dy); \ - m1 = m + 1; \ - incr1 = 2 * dx - 2 * (dy) * m1; \ - incr2 = 2 * dx - 2 * (dy) * m; \ - d = -2 * m * (dy) + 2 * dx; \ - } \ - } \ -} - -#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \ - if (m1 > 0) { \ - if (d > 0) { \ - minval += m1; \ - d += incr1; \ - } \ - else { \ - minval += m; \ - d += incr2; \ - } \ - } else {\ - if (d >= 0) { \ - minval += m1; \ - d += incr1; \ - } \ - else { \ - minval += m; \ - d += incr2; \ - } \ - } \ -} - - -/* - * This structure contains all of the information needed - * to run the bresenham algorithm. - * The variables may be hardcoded into the declarations - * instead of using this structure to make use of - * register declarations. - */ -typedef struct { - int minor_axis; /* minor axis */ - int d; /* decision variable */ - int m, m1; /* slope and slope+1 */ - int incr1, incr2; /* error increments */ -} BRESINFO; - - -#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \ - BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \ - bres.m, bres.m1, bres.incr1, bres.incr2) - -#define BRESINCRPGONSTRUCT(bres) \ - BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2) - - - -/* - * These are the data structures needed to scan - * convert regions. Two different scan conversion - * methods are available -- the even-odd method, and - * the winding number method. - * The even-odd rule states that a point is inside - * the polygon if a ray drawn from that point in any - * direction will pass through an odd number of - * path segments. - * By the winding number rule, a point is decided - * to be inside the polygon if a ray drawn from that - * point in any direction passes through a different - * number of clockwise and counter-clockwise path - * segments. - * - * These data structures are adapted somewhat from - * the algorithm in (Foley/Van Dam) for scan converting - * polygons. - * The basic algorithm is to start at the top (smallest y) - * of the polygon, stepping down to the bottom of - * the polygon by incrementing the y coordinate. We - * keep a list of edges which the current scanline crosses, - * sorted by x. This list is called the Active Edge Table (AET) - * As we change the y-coordinate, we update each entry in - * in the active edge table to reflect the edges new xcoord. - * This list must be sorted at each scanline in case - * two edges intersect. - * We also keep a data structure known as the Edge Table (ET), - * which keeps track of all the edges which the current - * scanline has not yet reached. The ET is basically a - * list of ScanLineList structures containing a list of - * edges which are entered at a given scanline. There is one - * ScanLineList per scanline at which an edge is entered. - * When we enter a new edge, we move it from the ET to the AET. - * - * From the AET, we can implement the even-odd rule as in - * (Foley/Van Dam). - * The winding number rule is a little trickier. We also - * keep the EdgeTableEntries in the AET linked by the - * nextWETE (winding EdgeTableEntry) link. This allows - * the edges to be linked just as before for updating - * purposes, but only uses the edges linked by the nextWETE - * link as edges representing spans of the polygon to - * drawn (as with the even-odd rule). - */ - -/* - * for the winding number rule - */ -#define CLOCKWISE 1 -#define COUNTERCLOCKWISE -1 - -typedef struct _EdgeTableEntry { - int ymax; /* ycoord at which we exit this edge. */ - BRESINFO bres; /* Bresenham info to run the edge */ - struct _EdgeTableEntry *next; /* next in the list */ - struct _EdgeTableEntry *back; /* for insertion sort */ - struct _EdgeTableEntry *nextWETE; /* for winding num rule */ - int ClockWise; /* flag for winding number rule */ -} EdgeTableEntry; - - -typedef struct _ScanLineList{ - int scanline; /* the scanline represented */ - EdgeTableEntry *edgelist; /* header node */ - struct _ScanLineList *next; /* next in the list */ -} ScanLineList; - - -typedef struct { - int ymax; /* ymax for the polygon */ - int ymin; /* ymin for the polygon */ - ScanLineList scanlines; /* header node */ -} EdgeTable; - - -/* - * Here is a struct to help with storage allocation - * so we can allocate a big chunk at a time, and then take - * pieces from this heap when we need to. - */ -#define SLLSPERBLOCK 25 - -typedef struct _ScanLineListBlock { - ScanLineList SLLs[SLLSPERBLOCK]; - struct _ScanLineListBlock *next; -} ScanLineListBlock; - - - -/* - * - * a few macros for the inner loops of the fill code where - * performance considerations don't allow a procedure call. - * - * Evaluate the given edge at the given scanline. - * If the edge has expired, then we leave it and fix up - * the active edge table; otherwise, we increment the - * x value to be ready for the next scanline. - * The winding number rule is in effect, so we must notify - * the caller when the edge has been removed so he - * can reorder the Winding Active Edge Table. - */ -#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ - if (pAET->ymax == y) { /* leaving this edge */ \ - pPrevAET->next = pAET->next; \ - pAET = pPrevAET->next; \ - fixWAET = 1; \ - if (pAET) \ - pAET->back = pPrevAET; \ - } \ - else { \ - BRESINCRPGONSTRUCT(pAET->bres); \ - pPrevAET = pAET; \ - pAET = pAET->next; \ - } \ -} - - -/* - * Evaluate the given edge at the given scanline. - * If the edge has expired, then we leave it and fix up - * the active edge table; otherwise, we increment the - * x value to be ready for the next scanline. - * The even-odd rule is in effect. - */ -#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ - if (pAET->ymax == y) { /* leaving this edge */ \ - pPrevAET->next = pAET->next; \ - pAET = pPrevAET->next; \ - if (pAET) \ - pAET->back = pPrevAET; \ - } \ - else { \ - BRESINCRPGONSTRUCT(pAET->bres); \ - pPrevAET = pAET; \ - pAET = pAET->next; \ - } \ -} diff --git a/gdk/linux-fb/gdkpolyreg-generic.c b/gdk/linux-fb/gdkpolyreg-generic.c deleted file mode 100644 index b98bd5641e..0000000000 --- a/gdk/linux-fb/gdkpolyreg-generic.c +++ /dev/null @@ -1,616 +0,0 @@ -/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ -/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */ - -#define LARGE_COORDINATE 1000000 -#define SMALL_COORDINATE -LARGE_COORDINATE - -#include <gdkregion.h> -#include "gdkregion-generic.h" -#include "gdkpoly-generic.h" - -/* - * InsertEdgeInET - * - * Insert the given edge into the edge table. - * First we must find the correct bucket in the - * Edge table, then find the right slot in the - * bucket. Finally, we can insert it. - * - */ -static void -InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock) - EdgeTable *ET; - EdgeTableEntry *ETE; - int scanline; - ScanLineListBlock **SLLBlock; - int *iSLLBlock; -{ - EdgeTableEntry *start, *prev; - ScanLineList *pSLL, *pPrevSLL; - ScanLineListBlock *tmpSLLBlock; - - /* - * find the right bucket to put the edge into - */ - pPrevSLL = &ET->scanlines; - pSLL = pPrevSLL->next; - while (pSLL && (pSLL->scanline < scanline)) - { - pPrevSLL = pSLL; - pSLL = pSLL->next; - } - - /* - * reassign pSLL (pointer to ScanLineList) if necessary - */ - if ((!pSLL) || (pSLL->scanline > scanline)) - { - if (*iSLLBlock > SLLSPERBLOCK-1) - { - tmpSLLBlock = - (ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock)); - (*SLLBlock)->next = tmpSLLBlock; - tmpSLLBlock->next = (ScanLineListBlock *)NULL; - *SLLBlock = tmpSLLBlock; - *iSLLBlock = 0; - } - pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); - - pSLL->next = pPrevSLL->next; - pSLL->edgelist = (EdgeTableEntry *)NULL; - pPrevSLL->next = pSLL; - } - pSLL->scanline = scanline; - - /* - * now insert the edge in the right bucket - */ - prev = (EdgeTableEntry *)NULL; - start = pSLL->edgelist; - while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) - { - prev = start; - start = start->next; - } - ETE->next = start; - - if (prev) - prev->next = ETE; - else - pSLL->edgelist = ETE; -} - -/* - * CreateEdgeTable - * - * This routine creates the edge table for - * scan converting polygons. - * The Edge Table (ET) looks like: - * - * EdgeTable - * -------- - * | ymax | ScanLineLists - * |scanline|-->------------>-------------->... - * -------- |scanline| |scanline| - * |edgelist| |edgelist| - * --------- --------- - * | | - * | | - * V V - * list of ETEs list of ETEs - * - * where ETE is an EdgeTableEntry data structure, - * and there is one ScanLineList per scanline at - * which an edge is initially entered. - * - */ - -static void -CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock) - int count; - GdkPoint *pts; - EdgeTable *ET; - EdgeTableEntry *AET; - EdgeTableEntry *pETEs; - ScanLineListBlock *pSLLBlock; -{ - GdkPoint *top, *bottom; - GdkPoint *PrevPt, *CurrPt; - int iSLLBlock = 0; - int dy; - - if (count < 2) return; - - /* - * initialize the Active Edge Table - */ - AET->next = (EdgeTableEntry *)NULL; - AET->back = (EdgeTableEntry *)NULL; - AET->nextWETE = (EdgeTableEntry *)NULL; - AET->bres.minor_axis = SMALL_COORDINATE; - - /* - * initialize the Edge Table. - */ - ET->scanlines.next = (ScanLineList *)NULL; - ET->ymax = SMALL_COORDINATE; - ET->ymin = LARGE_COORDINATE; - pSLLBlock->next = (ScanLineListBlock *)NULL; - - PrevPt = &pts[count-1]; - - /* - * for each vertex in the array of points. - * In this loop we are dealing with two vertices at - * a time -- these make up one edge of the polygon. - */ - while (count--) - { - CurrPt = pts++; - - /* - * find out which point is above and which is below. - */ - if (PrevPt->y > CurrPt->y) - { - bottom = PrevPt, top = CurrPt; - pETEs->ClockWise = 0; - } - else - { - bottom = CurrPt, top = PrevPt; - pETEs->ClockWise = 1; - } - - /* - * don't add horizontal edges to the Edge table. - */ - if (bottom->y != top->y) - { - pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ - - /* - * initialize integer edge algorithm - */ - dy = bottom->y - top->y; - BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); - - InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock); - - if (PrevPt->y > ET->ymax) - ET->ymax = PrevPt->y; - if (PrevPt->y < ET->ymin) - ET->ymin = PrevPt->y; - pETEs++; - } - - PrevPt = CurrPt; - } -} - -/* - * loadAET - * - * This routine moves EdgeTableEntries from the - * EdgeTable into the Active Edge Table, - * leaving them sorted by smaller x coordinate. - * - */ - -static void -loadAET(AET, ETEs) - EdgeTableEntry *AET, *ETEs; -{ - EdgeTableEntry *pPrevAET; - EdgeTableEntry *tmp; - - pPrevAET = AET; - AET = AET->next; - while (ETEs) - { - while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) - { - pPrevAET = AET; - AET = AET->next; - } - tmp = ETEs->next; - ETEs->next = AET; - if (AET) - AET->back = ETEs; - ETEs->back = pPrevAET; - pPrevAET->next = ETEs; - pPrevAET = ETEs; - - ETEs = tmp; - } -} - -/* - * computeWAET - * - * This routine links the AET by the - * nextWETE (winding EdgeTableEntry) link for - * use by the winding number rule. The final - * Active Edge Table (AET) might look something - * like: - * - * AET - * ---------- --------- --------- - * |ymax | |ymax | |ymax | - * | ... | |... | |... | - * |next |->|next |->|next |->... - * |nextWETE| |nextWETE| |nextWETE| - * --------- --------- ^-------- - * | | | - * V-------------------> V---> ... - * - */ -static void -computeWAET(AET) - EdgeTableEntry *AET; -{ - EdgeTableEntry *pWETE; - int inside = 1; - int isInside = 0; - - AET->nextWETE = (EdgeTableEntry *)NULL; - pWETE = AET; - AET = AET->next; - while (AET) - { - if (AET->ClockWise) - isInside++; - else - isInside--; - - if ((!inside && !isInside) || - ( inside && isInside)) - { - pWETE->nextWETE = AET; - pWETE = AET; - inside = !inside; - } - AET = AET->next; - } - pWETE->nextWETE = (EdgeTableEntry *)NULL; -} - -/* - * InsertionSort - * - * Just a simple insertion sort using - * pointers and back pointers to sort the Active - * Edge Table. - * - */ - -static int -InsertionSort(AET) - EdgeTableEntry *AET; -{ - EdgeTableEntry *pETEchase; - EdgeTableEntry *pETEinsert; - EdgeTableEntry *pETEchaseBackTMP; - int changed = 0; - - AET = AET->next; - while (AET) - { - pETEinsert = AET; - pETEchase = AET; - while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis) - pETEchase = pETEchase->back; - - AET = AET->next; - if (pETEchase != pETEinsert) - { - pETEchaseBackTMP = pETEchase->back; - pETEinsert->back->next = AET; - if (AET) - AET->back = pETEinsert->back; - pETEinsert->next = pETEchase; - pETEchase->back->next = pETEinsert; - pETEchase->back = pETEinsert; - pETEinsert->back = pETEchaseBackTMP; - changed = 1; - } - } - return(changed); -} - -/* - * Clean up our act. - */ -static void -FreeStorage(pSLLBlock) - ScanLineListBlock *pSLLBlock; -{ - ScanLineListBlock *tmpSLLBlock; - - while (pSLLBlock) - { - tmpSLLBlock = pSLLBlock->next; - g_free (pSLLBlock); - pSLLBlock = tmpSLLBlock; - } -} - -/* - * Create an array of rectangles from a list of points. - * If indeed these things (POINTS, RECTS) are the same, - * then this proc is still needed, because it allocates - * storage for the array, which was allocated on the - * stack by the calling procedure. - * - */ -static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg) - int numFullPtBlocks, iCurPtBlock; - POINTBLOCK *FirstPtBlock; - GdkRegion *reg; -{ - GdkRegionBox *rects; - GdkPoint *pts; - POINTBLOCK *CurPtBlock; - int i; - GdkRegionBox *extents; - int numRects; - - extents = ®->extents; - - numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1; - - reg->rects = g_renew (GdkRegionBox, reg->rects, numRects); - - reg->size = numRects; - CurPtBlock = FirstPtBlock; - rects = reg->rects - 1; - numRects = 0; - extents->x1 = G_MAXSHORT, extents->x2 = G_MINSHORT; - - for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) { - /* the loop uses 2 points per iteration */ - i = NUMPTSTOBUFFER >> 1; - if (!numFullPtBlocks) - i = iCurPtBlock >> 1; - for (pts = CurPtBlock->pts; i--; pts += 2) { - if (pts->x == pts[1].x) - continue; - if (numRects && pts->x == rects->x1 && pts->y == rects->y2 && - pts[1].x == rects->x2 && - (numRects == 1 || rects[-1].y1 != rects->y1) && - (i && pts[2].y > pts[1].y)) { - rects->y2 = pts[1].y + 1; - continue; - } - numRects++; - rects++; - rects->x1 = pts->x; rects->y1 = pts->y; - rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1; - if (rects->x1 < extents->x1) - extents->x1 = rects->x1; - if (rects->x2 > extents->x2) - extents->x2 = rects->x2; - } - CurPtBlock = CurPtBlock->next; - } - - if (numRects) { - extents->y1 = reg->rects->y1; - extents->y2 = rects->y2; - } else { - extents->x1 = 0; - extents->y1 = 0; - extents->x2 = 0; - extents->y2 = 0; - } - reg->numRects = numRects; - - return(TRUE); -} - -/* - * polytoregion - * - * Scan converts a polygon by returning a run-length - * encoding of the resultant bitmap -- the run-length - * encoding is in the form of an array of rectangles. - */ -GdkRegion * -gdk_region_polygon(GdkPoint *Pts, gint Count, GdkFillRule rule) -{ - GdkRegion *region; - EdgeTableEntry *pAET; /* Active Edge Table */ - int y; /* current scanline */ - int iPts = 0; /* number of pts in buffer */ - EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ - ScanLineList *pSLL; /* current scanLineList */ - GdkPoint *pts; /* output buffer */ - EdgeTableEntry *pPrevAET; /* ptr to previous AET */ - EdgeTable ET; /* header node for ET */ - EdgeTableEntry AET; /* header node for AET */ - EdgeTableEntry *pETEs; /* EdgeTableEntries pool */ - ScanLineListBlock SLLBlock; /* header for scanlinelist */ - int fixWAET = FALSE; - POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ - POINTBLOCK *tmpPtBlock; - int numFullPtBlocks = 0; - - region = gdk_region_new (); - - /* special case a rectangle */ - pts = Pts; - if (((Count == 4) || - ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) && - (((pts[0].y == pts[1].y) && - (pts[1].x == pts[2].x) && - (pts[2].y == pts[3].y) && - (pts[3].x == pts[0].x)) || - ((pts[0].x == pts[1].x) && - (pts[1].y == pts[2].y) && - (pts[2].x == pts[3].x) && - (pts[3].y == pts[0].y)))) { - region->extents.x1 = MIN(pts[0].x, pts[2].x); - region->extents.y1 = MIN(pts[0].y, pts[2].y); - region->extents.x2 = MAX(pts[0].x, pts[2].x); - region->extents.y2 = MAX(pts[0].y, pts[2].y); - if ((region->extents.x1 != region->extents.x2) && - (region->extents.y1 != region->extents.y2)) { - region->numRects = 1; - *(region->rects) = region->extents; - } - return(region); - } - - pETEs = g_new (EdgeTableEntry, Count); - - pts = FirstPtBlock.pts; - CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock); - pSLL = ET.scanlines.next; - curPtBlock = &FirstPtBlock; - - if (rule == GDK_EVEN_ODD_RULE) { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL != NULL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - - /* - * for each active edge - */ - while (pAET) { - pts->x = pAET->bres.minor_axis, pts->y = y; - pts++, iPts++; - - /* - * send out the buffer - */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK)); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - numFullPtBlocks++; - iPts = 0; - } - EVALUATEEDGEEVENODD(pAET, pPrevAET, y); - } - (void) InsertionSort(&AET); - } - } - else { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL != NULL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - computeWAET(&AET); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - pWETE = pAET; - - /* - * for each active edge - */ - while (pAET) { - /* - * add to the buffer only those edges that - * are in the Winding active edge table. - */ - if (pWETE == pAET) { - pts->x = pAET->bres.minor_axis, pts->y = y; - pts++, iPts++; - - /* - * send out the buffer - */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK)); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - numFullPtBlocks++; iPts = 0; - } - pWETE = pWETE->nextWETE; - } - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); - } - - /* - * recompute the winding active edge table if - * we just resorted or have exited an edge. - */ - if (InsertionSort(&AET) || fixWAET) { - computeWAET(&AET); - fixWAET = FALSE; - } - } - } - FreeStorage(SLLBlock.next); - (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); - for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { - tmpPtBlock = curPtBlock->next; - g_free (curPtBlock); - curPtBlock = tmpPtBlock; - } - g_free (pETEs); - return(region); -} diff --git a/gdk/linux-fb/gdkregion-generic.c b/gdk/linux-fb/gdkregion-generic.c deleted file mode 100644 index 1140ce0421..0000000000 --- a/gdk/linux-fb/gdkregion-generic.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* $TOG: Region.c /main/31 1998/02/06 17:50:22 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1988, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ -/* $XFree86: xc/lib/X11/Region.c,v 1.5 1999/05/09 10:50:01 dawes Exp $ */ -/* - * The functions in this file implement the Region abstraction, similar to one - * used in the X11 sample server. A Region is simply an area, as the name - * implies, and is implemented as a "y-x-banded" array of rectangles. To - * explain: Each Region is made up of a certain number of rectangles sorted - * by y coordinate first, and then by x coordinate. - * - * Furthermore, the rectangles are banded such that every rectangle with a - * given upper-left y coordinate (y1) will have the same lower-right y - * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it - * will span the entire vertical distance of the band. This means that some - * areas that could be merged into a taller rectangle will be represented as - * several shorter rectangles to account for shorter rectangles to its left - * or right but within its "vertical scope". - * - * An added constraint on the rectangles is that they must cover as much - * horizontal area as possible. E.g. no two rectangles in a band are allowed - * to touch. - * - * Whenever possible, bands will be merged together to cover a greater vertical - * distance (and thus reduce the number of rectangles). Two bands can be merged - * only if the bottom of one touches the top of the other and they have - * rectangles in the same places (of the same width, of course). This maintains - * the y-x-banding that's so nice to have... - */ - -#include <gdkregion.h> -#include "gdkregion-generic.h" - -#ifdef DEBUG -#include <stdio.h> -#define assert(expr) {if (!(expr)) fprintf(stderr,\ -"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); } -#else -#define assert(expr) -#endif - -typedef void (*overlapFunc) (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2); -typedef void (*nonOverlapFunc) (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2); - -static void miRegionCopy (GdkRegion *dstrgn, - GdkRegion *rgn); -static void miRegionOp (GdkRegion *newReg, - GdkRegion *reg1, - GdkRegion *reg2, - overlapFunc overlapFn, - nonOverlapFunc nonOverlap1Fn, - nonOverlapFunc nonOverlap2Fn); - -/* Create a new empty region */ - -GdkRegion * -gdk_region_new () -{ - GdkRegion *temp; - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, 1); - - temp->numRects = 0; - temp->extents.x1 = 0; - temp->extents.y1 = 0; - temp->extents.x2 = 0; - temp->extents.y2 = 0; - temp->size = 1; - - return temp; -} - -GdkRegion * -gdk_region_rectangle (GdkRectangle *rectangle) -{ - GdkRegion *temp; - - if (rectangle->width <= 0 || rectangle->height <= 0) - return gdk_region_new(); - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, 1); - - temp->numRects = 1; - temp->extents.x1 = temp->rects[0].x1 = rectangle->x; - temp->extents.y1 = temp->rects[0].y1 = rectangle->y; - temp->extents.x2 = temp->rects[0].x2 = rectangle->x + rectangle->width; - temp->extents.y2 = temp->rects[0].y2 = rectangle->y + rectangle->height; - temp->size = 1; - - return temp; -} - -GdkRegion * -gdk_region_copy (GdkRegion *region) -{ - GdkRegion *temp; - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, region->numRects); - - temp->numRects = region->numRects; - temp->extents = region->extents; - temp->size = region->numRects; - - memcpy (temp->rects, region->rects, region->numRects * sizeof (GdkRegionBox)); - - return temp; -} - -void -gdk_region_get_clipbox (GdkRegion *r, GdkRectangle *rect) -{ - rect->x = r->extents.x1; - rect->y = r->extents.y1; - rect->width = r->extents.x2 - r->extents.x1; - rect->height = r->extents.y2 - r->extents.y1; -} - -void -gdk_region_union_with_rect (GdkRegion *region, - GdkRectangle *rect) -{ - GdkRegion tmp_region; - - if (!rect->width || !rect->height) - return; - - tmp_region.rects = &tmp_region.extents; - tmp_region.numRects = 1; - tmp_region.extents.x1 = rect->x; - tmp_region.extents.y1 = rect->y; - tmp_region.extents.x2 = rect->x + rect->width; - tmp_region.extents.y2 = rect->y + rect->height; - tmp_region.size = 1; - - gdk_region_union (region, &tmp_region); -} - -/*- - *----------------------------------------------------------------------- - * miSetExtents -- - * Reset the extents of a region to what they should be. Called by - * miSubtract and miIntersect b/c they can't figure it out along the - * way or do so easily, as miUnion can. - * - * Results: - * None. - * - * Side Effects: - * The region's 'extents' structure is overwritten. - * - *----------------------------------------------------------------------- - */ -static void -miSetExtents (GdkRegion *pReg) -{ - GdkRegionBox *pBox, *pBoxEnd, *pExtents; - - if (pReg->numRects == 0) - { - pReg->extents.x1 = 0; - pReg->extents.y1 = 0; - pReg->extents.x2 = 0; - pReg->extents.y2 = 0; - return; - } - - pExtents = &pReg->extents; - pBox = pReg->rects; - pBoxEnd = &pBox[pReg->numRects - 1]; - - /* - * Since pBox is the first rectangle in the region, it must have the - * smallest y1 and since pBoxEnd is the last rectangle in the region, - * it must have the largest y2, because of banding. Initialize x1 and - * x2 from pBox and pBoxEnd, resp., as good things to initialize them - * to... - */ - pExtents->x1 = pBox->x1; - pExtents->y1 = pBox->y1; - pExtents->x2 = pBoxEnd->x2; - pExtents->y2 = pBoxEnd->y2; - - assert(pExtents->y1 < pExtents->y2); - while (pBox <= pBoxEnd) - { - if (pBox->x1 < pExtents->x1) - { - pExtents->x1 = pBox->x1; - } - if (pBox->x2 > pExtents->x2) - { - pExtents->x2 = pBox->x2; - } - pBox++; - } - assert(pExtents->x1 < pExtents->x2); -} - -void -gdk_region_destroy (GdkRegion *r) -{ - g_free (r->rects); - g_free (r); -} - - -/* TranslateRegion(pRegion, x, y) - translates in place - added by raymond -*/ - -void -gdk_region_offset (GdkRegion *region, - gint x, - gint y) -{ - int nbox; - GdkRegionBox *pbox; - - pbox = region->rects; - nbox = region->numRects; - - while(nbox--) - { - pbox->x1 += x; - pbox->x2 += x; - pbox->y1 += y; - pbox->y2 += y; - pbox++; - } - region->extents.x1 += x; - region->extents.x2 += x; - region->extents.y1 += y; - region->extents.y2 += y; -} - -/* - Utility procedure Compress: - Replace r by the region r', where - p in r' iff (Quantifer m <= dx) (p + m in r), and - Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and - (x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE. - - Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region - of all points p such that p and the next dx points on the same - horizontal scan line are all in r. We do this using by noting - that p is the head of a run of length 2^i + k iff p is the head - of a run of length 2^i and p+2^i is the head of a run of length - k. Thus, the loop invariant: s contains the region corresponding - to the runs of length shift. r contains the region corresponding - to the runs of length 1 + dxo & (shift-1), where dxo is the original - value of dx. dx = dxo & ~(shift-1). As parameters, s and t are - scratch regions, so that we don't have to allocate them on every - call. -*/ - -#define ZOpRegion(a,b) if (grow) gdk_region_union (a, b); \ - else gdk_region_intersect (a,b) -#define ZShiftRegion(a,b) if (xdir) gdk_region_offset (a,b,0); \ - else gdk_region_offset (a,0,b) - -static void -Compress(GdkRegion *r, - GdkRegion *s, - GdkRegion *t, - guint dx, - int xdir, - int grow) -{ - guint shift = 1; - - miRegionCopy (s, r); - while (dx) - { - if (dx & shift) - { - ZShiftRegion(r, -(int)shift); - ZOpRegion(r, s); - dx -= shift; - if (!dx) break; - } - miRegionCopy (t, s); - ZShiftRegion(s, -(int)shift); - ZOpRegion(s, t); - shift <<= 1; - } -} - -#undef ZOpRegion -#undef ZShiftRegion -#undef ZCopyRegion - -void -gdk_region_shrink (GdkRegion *r, - int dx, - int dy) -{ - GdkRegion *s, *t; - int grow; - - if (!dx && !dy) - return; - - s = gdk_region_new (); - t = gdk_region_new (); - - grow = (dx < 0); - if (grow) - dx = -dx; - if (dx) - Compress(r, s, t, (unsigned) 2*dx, TRUE, grow); - - grow = (dy < 0); - if (grow) - dy = -dy; - if (dy) - Compress(r, s, t, (unsigned) 2*dy, FALSE, grow); - - gdk_region_offset (r, dx, dy); - gdk_region_destroy (s); - gdk_region_destroy (t); -} - - -/*====================================================================== - * Region Intersection - *====================================================================*/ -/*- - *----------------------------------------------------------------------- - * miIntersectO -- - * Handle an overlapping band for miIntersect. - * - * Results: - * None. - * - * Side Effects: - * Rectangles may be added to the region. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miIntersectO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - int x1; - int x2; - GdkRegionBox *pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - while ((r1 != r1End) && (r2 != r2End)) - { - x1 = MAX (r1->x1,r2->x1); - x2 = MIN (r1->x2,r2->x2); - - /* - * If there's any overlap between the two rectangles, add that - * overlap to the new region. - * There's no need to check for subsumption because the only way - * such a need could arise is if some region has two rectangles - * right next to each other. Since that should never happen... - */ - if (x1 < x2) - { - assert (y1<y2); - - MEMCHECK (pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - assert (pReg->numRects <= pReg->size); - } - - /* - * Need to advance the pointers. Shift the one that extends - * to the right the least, since the other still has a chance to - * overlap with that region's next rectangle, if you see what I mean. - */ - if (r1->x2 < r2->x2) - { - r1++; - } - else if (r2->x2 < r1->x2) - { - r2++; - } - else - { - r1++; - r2++; - } - } -} - -void -gdk_region_intersect (GdkRegion *region, - GdkRegion *other) -{ - /* check for trivial reject */ - if ((!(region->numRects)) || (!(other->numRects)) || - (!EXTENTCHECK(®ion->extents, &other->extents))) - region->numRects = 0; - else - miRegionOp (region, region, other, - miIntersectO, (nonOverlapFunc) NULL, (nonOverlapFunc) NULL); - - /* - * Can't alter region's extents before miRegionOp depends on the - * extents of the regions being unchanged. Besides, this way there's - * no checking against rectangles that will be nuked due to - * coalescing, so we have to examine fewer rectangles. - */ - miSetExtents(region); -} - -static void -miRegionCopy(GdkRegion *dstrgn, GdkRegion *rgn) -{ - if (dstrgn != rgn) /* don't want to copy to itself */ - { - if (dstrgn->size < rgn->numRects) - { - dstrgn->rects = g_renew (GdkRegionBox, dstrgn->rects, rgn->numRects); - dstrgn->size = rgn->numRects; - } - dstrgn->numRects = rgn->numRects; - dstrgn->extents.x1 = rgn->extents.x1; - dstrgn->extents.y1 = rgn->extents.y1; - dstrgn->extents.x2 = rgn->extents.x2; - dstrgn->extents.y2 = rgn->extents.y2; - - memcpy (dstrgn->rects, rgn->rects, rgn->numRects * sizeof (GdkRegionBox)); - } -} - - -/*====================================================================== - * Generic Region Operator - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miCoalesce -- - * Attempt to merge the boxes in the current band with those in the - * previous one. Used only by miRegionOp. - * - * Results: - * The new index for the previous band. - * - * Side Effects: - * If coalescing takes place: - * - rectangles in the previous band will have their y2 fields - * altered. - * - pReg->numRects will be decreased. - * - *----------------------------------------------------------------------- - */ -/* static int*/ -static int -miCoalesce (GdkRegion *pReg, /* Region to coalesce */ - gint prevStart, /* Index of start of previous band */ - gint curStart) /* Index of start of current band */ -{ - GdkRegionBox *pPrevBox; /* Current box in previous band */ - GdkRegionBox *pCurBox; /* Current box in current band */ - GdkRegionBox *pRegEnd; /* End of region */ - int curNumRects; /* Number of rectangles in current - * band */ - int prevNumRects; /* Number of rectangles in previous - * band */ - int bandY1; /* Y1 coordinate for current band */ - - pRegEnd = &pReg->rects[pReg->numRects]; - - pPrevBox = &pReg->rects[prevStart]; - prevNumRects = curStart - prevStart; - - /* - * Figure out how many rectangles are in the current band. Have to do - * this because multiple bands could have been added in miRegionOp - * at the end when one region has been exhausted. - */ - pCurBox = &pReg->rects[curStart]; - bandY1 = pCurBox->y1; - for (curNumRects = 0; - (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1); - curNumRects++) - { - pCurBox++; - } - - if (pCurBox != pRegEnd) - { - /* - * If more than one band was added, we have to find the start - * of the last band added so the next coalescing job can start - * at the right place... (given when multiple bands are added, - * this may be pointless -- see above). - */ - pRegEnd--; - while (pRegEnd[-1].y1 == pRegEnd->y1) - { - pRegEnd--; - } - curStart = pRegEnd - pReg->rects; - pRegEnd = pReg->rects + pReg->numRects; - } - - if ((curNumRects == prevNumRects) && (curNumRects != 0)) { - pCurBox -= curNumRects; - /* - * The bands may only be coalesced if the bottom of the previous - * matches the top scanline of the current. - */ - if (pPrevBox->y2 == pCurBox->y1) - { - /* - * Make sure the bands have boxes in the same places. This - * assumes that boxes have been added in such a way that they - * cover the most area possible. I.e. two boxes in a band must - * have some horizontal space between them. - */ - do - { - if ((pPrevBox->x1 != pCurBox->x1) || - (pPrevBox->x2 != pCurBox->x2)) - { - /* - * The bands don't line up so they can't be coalesced. - */ - return (curStart); - } - pPrevBox++; - pCurBox++; - prevNumRects -= 1; - } while (prevNumRects != 0); - - pReg->numRects -= curNumRects; - pCurBox -= curNumRects; - pPrevBox -= curNumRects; - - /* - * The bands may be merged, so set the bottom y of each box - * in the previous band to that of the corresponding box in - * the current band. - */ - do - { - pPrevBox->y2 = pCurBox->y2; - pPrevBox++; - pCurBox++; - curNumRects -= 1; - } - while (curNumRects != 0); - - /* - * If only one band was added to the region, we have to backup - * curStart to the start of the previous band. - * - * If more than one band was added to the region, copy the - * other bands down. The assumption here is that the other bands - * came from the same region as the current one and no further - * coalescing can be done on them since it's all been done - * already... curStart is already in the right place. - */ - if (pCurBox == pRegEnd) - { - curStart = prevStart; - } - else - { - do - { - *pPrevBox++ = *pCurBox++; - } - while (pCurBox != pRegEnd); - } - - } - } - return curStart; -} - -/*- - *----------------------------------------------------------------------- - * miRegionOp -- - * Apply an operation to two regions. Called by miUnion, miInverse, - * miSubtract, miIntersect... - * - * Results: - * None. - * - * Side Effects: - * The new region is overwritten. - * - * Notes: - * The idea behind this function is to view the two regions as sets. - * Together they cover a rectangle of area that this function divides - * into horizontal bands where points are covered only by one region - * or by both. For the first case, the nonOverlapFunc is called with - * each the band and the band's upper and lower extents. For the - * second, the overlapFunc is called to process the entire band. It - * is responsible for clipping the rectangles in the band, though - * this function provides the boundaries. - * At the end of each band, the new region is coalesced, if possible, - * to reduce the number of rectangles in the region. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miRegionOp(GdkRegion *newReg, - GdkRegion *reg1, - GdkRegion *reg2, - overlapFunc overlapFn, /* Function to call for over- - * lapping bands */ - nonOverlapFunc nonOverlap1Fn, /* Function to call for non- - * overlapping bands in region - * 1 */ - nonOverlapFunc nonOverlap2Fn) /* Function to call for non- - * overlapping bands in region - * 2 */ -{ - GdkRegionBox *r1; /* Pointer into first region */ - GdkRegionBox *r2; /* Pointer into 2d region */ - GdkRegionBox *r1End; /* End of 1st region */ - GdkRegionBox *r2End; /* End of 2d region */ - int ybot; /* Bottom of intersection */ - int ytop; /* Top of intersection */ - GdkRegionBox *oldRects; /* Old rects for newReg */ - int prevBand; /* Index of start of - * previous band in newReg */ - int curBand; /* Index of start of current - * band in newReg */ - GdkRegionBox *r1BandEnd; /* End of current band in r1 */ - GdkRegionBox *r2BandEnd; /* End of current band in r2 */ - int top; /* Top of non-overlapping - * band */ - int bot; /* Bottom of non-overlapping - * band */ - - /* - * Initialization: - * set r1, r2, r1End and r2End appropriately, preserve the important - * parts of the destination region until the end in case it's one of - * the two source regions, then mark the "new" region empty, allocating - * another array of rectangles for it to use. - */ - r1 = reg1->rects; - r2 = reg2->rects; - r1End = r1 + reg1->numRects; - r2End = r2 + reg2->numRects; - - oldRects = newReg->rects; - - EMPTY_REGION(newReg); - - /* - * Allocate a reasonable number of rectangles for the new region. The idea - * is to allocate enough so the individual functions don't need to - * reallocate and copy the array, which is time consuming, yet we don't - * have to worry about using too much memory. I hope to be able to - * nuke the Xrealloc() at the end of this function eventually. - */ - newReg->size = MAX (reg1->numRects, reg2->numRects) * 2; - newReg->rects = g_new (GdkRegionBox, newReg->size); - - /* - * Initialize ybot and ytop. - * In the upcoming loop, ybot and ytop serve different functions depending - * on whether the band being handled is an overlapping or non-overlapping - * band. - * In the case of a non-overlapping band (only one of the regions - * has points in the band), ybot is the bottom of the most recent - * intersection and thus clips the top of the rectangles in that band. - * ytop is the top of the next intersection between the two regions and - * serves to clip the bottom of the rectangles in the current band. - * For an overlapping band (where the two regions intersect), ytop clips - * the top of the rectangles of both regions and ybot clips the bottoms. - */ - if (reg1->extents.y1 < reg2->extents.y1) - ybot = reg1->extents.y1; - else - ybot = reg2->extents.y1; - - /* - * prevBand serves to mark the start of the previous band so rectangles - * can be coalesced into larger rectangles. qv. miCoalesce, above. - * In the beginning, there is no previous band, so prevBand == curBand - * (curBand is set later on, of course, but the first band will always - * start at index 0). prevBand and curBand must be indices because of - * the possible expansion, and resultant moving, of the new region's - * array of rectangles. - */ - prevBand = 0; - - do - { - curBand = newReg->numRects; - - /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - r1BandEnd = r1; - while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1)) - { - r1BandEnd++; - } - - r2BandEnd = r2; - while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1)) - { - r2BandEnd++; - } - - /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1->y1 < r2->y1) - { - top = MAX (r1->y1,ybot); - bot = MIN (r1->y2,r2->y1); - - if ((top != bot) && (nonOverlap1Fn != (void (*)())NULL)) - { - (* nonOverlap1Fn) (newReg, r1, r1BandEnd, top, bot); - } - - ytop = r2->y1; - } - else if (r2->y1 < r1->y1) - { - top = MAX (r2->y1,ybot); - bot = MIN (r2->y2,r1->y1); - - if ((top != bot) && (nonOverlap2Fn != (void (*)())NULL)) - { - (* nonOverlap2Fn) (newReg, r2, r2BandEnd, top, bot); - } - - ytop = r1->y1; - } - else - { - ytop = r1->y1; - } - - /* - * If any rectangles got added to the region, try and coalesce them - * with rectangles from the previous band. Note we could just do - * this test in miCoalesce, but some machines incur a not - * inconsiderable cost for function calls, so... - */ - if (newReg->numRects != curBand) - { - prevBand = miCoalesce (newReg, prevBand, curBand); - } - - /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = MIN (r1->y2, r2->y2); - curBand = newReg->numRects; - if (ybot > ytop) - { - (* overlapFn) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); - - } - - if (newReg->numRects != curBand) - { - prevBand = miCoalesce (newReg, prevBand, curBand); - } - - /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) - { - r1 = r1BandEnd; - } - if (r2->y2 == ybot) - { - r2 = r2BandEnd; - } - } while ((r1 != r1End) && (r2 != r2End)); - - /* - * Deal with whichever region still has rectangles left. - */ - curBand = newReg->numRects; - if (r1 != r1End) - { - if (nonOverlap1Fn != (nonOverlapFunc )NULL) - { - do - { - r1BandEnd = r1; - while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1)) - { - r1BandEnd++; - } - (* nonOverlap1Fn) (newReg, r1, r1BandEnd, - MAX (r1->y1,ybot), r1->y2); - r1 = r1BandEnd; - } while (r1 != r1End); - } - } - else if ((r2 != r2End) && (nonOverlap2Fn != (nonOverlapFunc) NULL)) - { - do - { - r2BandEnd = r2; - while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1)) - { - r2BandEnd++; - } - (* nonOverlap2Fn) (newReg, r2, r2BandEnd, - MAX (r2->y1,ybot), r2->y2); - r2 = r2BandEnd; - } while (r2 != r2End); - } - - if (newReg->numRects != curBand) - { - (void) miCoalesce (newReg, prevBand, curBand); - } - - /* - * A bit of cleanup. To keep regions from growing without bound, - * we shrink the array of rectangles to match the new number of - * rectangles in the region. This never goes to 0, however... - * - * Only do this stuff if the number of rectangles allocated is more than - * twice the number of rectangles in the region (a simple optimization...). - */ - if (newReg->numRects < (newReg->size >> 1)) - { - if (REGION_NOT_EMPTY (newReg)) - { - newReg->size = newReg->numRects; - newReg->rects = g_renew (GdkRegionBox, newReg->rects, newReg->size); - } - else - { - /* - * No point in doing the extra work involved in an Xrealloc if - * the region is empty - */ - newReg->size = 1; - g_free (newReg->rects); - newReg->rects = g_new (GdkRegionBox, 1); - } - } - g_free (oldRects); -} - - -/*====================================================================== - * Region Union - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miUnionNonO -- - * Handle a non-overlapping band for the union operation. Just - * Adds the rectangles into the region. Doesn't have to check for - * subsumption or anything. - * - * Results: - * None. - * - * Side Effects: - * pReg->numRects is incremented and the final rectangles overwritten - * with the rectangles we're passed. - * - *----------------------------------------------------------------------- - */ -static void -miUnionNonO (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2) -{ - GdkRegionBox *pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - assert(y1 < y2); - - while (r != rEnd) - { - assert(r->x1 < r->x2); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = r->x1; - pNextRect->y1 = y1; - pNextRect->x2 = r->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - r++; - } -} - - -/*- - *----------------------------------------------------------------------- - * miUnionO -- - * Handle an overlapping band for the union operation. Picks the - * left-most rectangle each time and merges it into the region. - * - * Results: - * None. - * - * Side Effects: - * Rectangles are overwritten in pReg->rects and pReg->numRects will - * be changed. - * - *----------------------------------------------------------------------- - */ - -/* static void*/ -static void -miUnionO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - -#define MERGERECT(r) \ - if ((pReg->numRects != 0) && \ - (pNextRect[-1].y1 == y1) && \ - (pNextRect[-1].y2 == y2) && \ - (pNextRect[-1].x2 >= r->x1)) \ - { \ - if (pNextRect[-1].x2 < r->x2) \ - { \ - pNextRect[-1].x2 = r->x2; \ - assert(pNextRect[-1].x1<pNextRect[-1].x2); \ - } \ - } \ - else \ - { \ - MEMCHECK(pReg, pNextRect, pReg->rects); \ - pNextRect->y1 = y1; \ - pNextRect->y2 = y2; \ - pNextRect->x1 = r->x1; \ - pNextRect->x2 = r->x2; \ - pReg->numRects += 1; \ - pNextRect += 1; \ - } \ - assert(pReg->numRects<=pReg->size); \ - r++; - - assert (y1<y2); - while ((r1 != r1End) && (r2 != r2End)) - { - if (r1->x1 < r2->x1) - { - MERGERECT(r1); - } - else - { - MERGERECT(r2); - } - } - - if (r1 != r1End) - { - do - { - MERGERECT(r1); - } while (r1 != r1End); - } - else while (r2 != r2End) - { - MERGERECT(r2); - } -} - -void -gdk_region_union (GdkRegion *region, - GdkRegion *other) -{ - /* checks all the simple cases */ - - /* - * region and other are the same or other is empty - */ - if ((region == other) || (!(other->numRects))) - return; - - /* - * region is empty - */ - if (!(region->numRects)) - { - miRegionCopy (region, other); - return; - } - - /* - * region completely subsumes otehr - */ - if ((region->numRects == 1) && - (region->extents.x1 <= other->extents.x1) && - (region->extents.y1 <= other->extents.y1) && - (region->extents.x2 >= other->extents.x2) && - (region->extents.y2 >= other->extents.y2)) - return; - - /* - * other completely subsumes region - */ - if ((other->numRects == 1) && - (other->extents.x1 <= region->extents.x1) && - (other->extents.y1 <= region->extents.y1) && - (other->extents.x2 >= region->extents.x2) && - (other->extents.y2 >= region->extents.y2)) - { - miRegionCopy(region, other); - return; - } - - miRegionOp (region, region, other, miUnionO, - miUnionNonO, miUnionNonO); - - region->extents.x1 = MIN (region->extents.x1, other->extents.x1); - region->extents.y1 = MIN (region->extents.y1, other->extents.y1); - region->extents.x2 = MAX (region->extents.x2, other->extents.x2); - region->extents.y2 = MAX (region->extents.y2, other->extents.y2); -} - - -/*====================================================================== - * Region Subtraction - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miSubtractNonO -- - * Deal with non-overlapping band for subtraction. Any parts from - * region 2 we discard. Anything from region 1 we add to the region. - * - * Results: - * None. - * - * Side Effects: - * pReg may be affected. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miSubtractNonO1 (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - assert(y1<y2); - - while (r != rEnd) - { - assert (r->x1<r->x2); - MEMCHECK (pReg, pNextRect, pReg->rects); - pNextRect->x1 = r->x1; - pNextRect->y1 = y1; - pNextRect->x2 = r->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert (pReg->numRects <= pReg->size); - - r++; - } -} - -/*- - *----------------------------------------------------------------------- - * miSubtractO -- - * Overlapping band subtraction. x1 is the left-most point not yet - * checked. - * - * Results: - * None. - * - * Side Effects: - * pReg may have rectangles added to it. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miSubtractO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - int x1; - - x1 = r1->x1; - - assert(y1<y2); - pNextRect = &pReg->rects[pReg->numRects]; - - while ((r1 != r1End) && (r2 != r2End)) - { - if (r2->x2 <= x1) - { - /* - * Subtrahend missed the boat: go to next subtrahend. - */ - r2++; - } - else if (r2->x1 <= x1) - { - /* - * Subtrahend preceeds minuend: nuke left edge of minuend. - */ - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend completely covered: advance to next minuend and - * reset left fence to edge of new minuend. - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend now used up since it doesn't extend beyond - * minuend - */ - r2++; - } - } - else if (r2->x1 < r1->x2) - { - /* - * Left part of subtrahend covers part of minuend: add uncovered - * part of minuend to region and skip to next subtrahend. - */ - assert(x1<r2->x1); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r2->x1; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend used up: advance to new... - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend used up - */ - r2++; - } - } - else - { - /* - * Minuend used up: add any remaining piece before advancing. - */ - if (r1->x2 > x1) - { - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r1->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - assert(pReg->numRects<=pReg->size); - } - r1++; - x1 = r1->x1; - } - } - - /* - * Add remaining minuend rectangles to region. - */ - while (r1 != r1End) - { - assert(x1<r1->x2); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r1->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - - r1++; - if (r1 != r1End) - { - x1 = r1->x1; - } - } -} - -/*- - *----------------------------------------------------------------------- - * gdk_region_subtract -- - * Subtract other from region and leave the result in region. - * - * Results: - * TRUE. - * - * Side Effects: - * region is overwritten. - * - *----------------------------------------------------------------------- - */ - -void -gdk_region_subtract (GdkRegion *region, - GdkRegion *other) -{ - /* check for trivial reject */ - if ((!(region->numRects)) || (!(other->numRects)) || - (!EXTENTCHECK(®ion->extents, &other->extents))) - return; - - miRegionOp (region, region, other, miSubtractO, - miSubtractNonO1, (nonOverlapFunc) NULL); - - /* - * Can't alter region's extents before we call miRegionOp because miRegionOp - * depends on the extents of those regions being the unaltered. Besides, this - * way there's no checking against rectangles that will be nuked - * due to coalescing, so we have to examine fewer rectangles. - */ - miSetExtents (region); -} - -void -gdk_region_xor (GdkRegion *sra, - GdkRegion *srb) -{ - GdkRegion *trb; - - trb = gdk_region_copy (srb); - - gdk_region_subtract (trb, sra); - gdk_region_subtract (sra, srb); - - gdk_region_union (sra,trb); - - gdk_region_destroy (trb); -} - -/* - * Check to see if the region is empty. Assumes a region is passed - * as a parameter - */ -gboolean -gdk_region_empty (GdkRegion *r) -{ - if (r->numRects == 0) - return TRUE; - else - return FALSE; -} - -/* - * Check to see if two regions are equal - */ -gboolean -gdk_region_equal (GdkRegion *r1, - GdkRegion *r2) -{ - int i; - - if (r1->numRects != r2->numRects) return FALSE; - else if (r1->numRects == 0) return TRUE; - else if (r1->extents.x1 != r2->extents.x1) return FALSE; - else if (r1->extents.x2 != r2->extents.x2) return FALSE; - else if (r1->extents.y1 != r2->extents.y1) return FALSE; - else if (r1->extents.y2 != r2->extents.y2) return FALSE; - else - for(i=0; i < r1->numRects; i++ ) - { - if (r1->rects[i].x1 != r2->rects[i].x1) return FALSE; - else if (r1->rects[i].x2 != r2->rects[i].x2) return FALSE; - else if (r1->rects[i].y1 != r2->rects[i].y1) return FALSE; - else if (r1->rects[i].y2 != r2->rects[i].y2) return FALSE; - } - return TRUE; -} - -gboolean -gdk_region_point_in (GdkRegion *region, - int x, - int y) -{ - int i; - - if (region->numRects == 0) - return FALSE; - if (!INBOX(region->extents, x, y)) - return FALSE; - for (i=0; i<region->numRects; i++) - { - if (INBOX (region->rects[i], x, y)) - return TRUE; - } - return FALSE; -} - -GdkOverlapType -gdk_region_rect_in (GdkRegion *region, - GdkRectangle *rectangle) -{ - GdkRegionBox *pbox; - GdkRegionBox *pboxEnd; - GdkRegionBox rect; - GdkRegionBox *prect = ▭ - gboolean partIn, partOut; - - gint rx = rectangle->x; - gint ry = rectangle->y; - - prect->x1 = rx; - prect->y1 = ry; - prect->x2 = rx + rectangle->width; - prect->y2 = ry + rectangle->height; - - /* this is (just) a useful optimization */ - if ((region->numRects == 0) || !EXTENTCHECK (®ion->extents, prect)) - return GDK_OVERLAP_RECTANGLE_OUT; - - partOut = FALSE; - partIn = FALSE; - - /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ - for (pbox = region->rects, pboxEnd = pbox + region->numRects; - pbox < pboxEnd; - pbox++) - { - - if (pbox->y2 <= ry) - continue; /* getting up to speed or skipping remainder of band */ - - if (pbox->y1 > ry) - { - partOut = TRUE; /* missed part of rectangle above */ - if (partIn || (pbox->y1 >= prect->y2)) - break; - ry = pbox->y1; /* x guaranteed to be == prect->x1 */ - } - - if (pbox->x2 <= rx) - continue; /* not far enough over yet */ - - if (pbox->x1 > rx) - { - partOut = TRUE; /* missed part of rectangle to left */ - if (partIn) - break; - } - - if (pbox->x1 < prect->x2) - { - partIn = TRUE; /* definitely overlap */ - if (partOut) - break; - } - - if (pbox->x2 >= prect->x2) - { - ry = pbox->y2; /* finished with this band */ - if (ry >= prect->y2) - break; - rx = prect->x1; /* reset x out to left again */ - } - else - { - /* - * Because boxes in a band are maximal width, if the first box - * to overlap the rectangle doesn't completely cover it in that - * band, the rectangle must be partially out, since some of it - * will be uncovered in that band. partIn will have been set true - * by now... - */ - break; - } - - } - - return (partIn ? - ((ry < prect->y2) ? - GDK_OVERLAP_RECTANGLE_PART : GDK_OVERLAP_RECTANGLE_IN) : - GDK_OVERLAP_RECTANGLE_OUT); -} diff --git a/gdk/linux-fb/gdkregion-generic.h b/gdk/linux-fb/gdkregion-generic.h deleted file mode 100644 index 33d0683dfb..0000000000 --- a/gdk/linux-fb/gdkregion-generic.h +++ /dev/null @@ -1,162 +0,0 @@ -/* $TOG: region.h /main/9 1998/02/06 17:50:30 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -#ifndef __GDK_REGION_GENERIC_H__ -#define __GDK_REGION_GENERIC_H__ - -typedef GdkSegment GdkRegionBox; - -/* - * clip region - */ - -struct _GdkRegion -{ - long size; - long numRects; - GdkRegionBox *rects; - GdkRegionBox extents; -}; - -/* 1 if two BOXs overlap. - * 0 if two BOXs do not overlap. - * Remember, x2 and y2 are not in the region - */ -#define EXTENTCHECK(r1, r2) \ - ((r1)->x2 > (r2)->x1 && \ - (r1)->x1 < (r2)->x2 && \ - (r1)->y2 > (r2)->y1 && \ - (r1)->y1 < (r2)->y2) - -/* - * update region extents - */ -#define EXTENTS(r,idRect){\ - if((r)->x1 < (idRect)->extents.x1)\ - (idRect)->extents.x1 = (r)->x1;\ - if((r)->y1 < (idRect)->extents.y1)\ - (idRect)->extents.y1 = (r)->y1;\ - if((r)->x2 > (idRect)->extents.x2)\ - (idRect)->extents.x2 = (r)->x2;\ - if((r)->y2 > (idRect)->extents.y2)\ - (idRect)->extents.y2 = (r)->y2;\ - } - -/* - * Check to see if there is enough memory in the present region. - */ -#define MEMCHECK(reg, rect, firstrect){ \ - if ((reg)->numRects >= ((reg)->size - 1)) { \ - (firstrect) = g_renew (GdkRegionBox, (firstrect), 2 * (reg)->size); \ - (reg)->size *= 2; \ - (rect) = &(firstrect)[(reg)->numRects]; \ - } \ - } - -/* this routine checks to see if the previous rectangle is the same - * or subsumes the new rectangle to add. - */ - -#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ - (!(((Reg)->numRects > 0)&&\ - ((R-1)->y1 == (Ry1)) &&\ - ((R-1)->y2 == (Ry2)) &&\ - ((R-1)->x1 <= (Rx1)) &&\ - ((R-1)->x2 >= (Rx2)))) - -/* add a rectangle to the given Region */ -#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ - if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ - CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ - (r)->x1 = (rx1);\ - (r)->y1 = (ry1);\ - (r)->x2 = (rx2);\ - (r)->y2 = (ry2);\ - EXTENTS((r), (reg));\ - (reg)->numRects++;\ - (r)++;\ - }\ - } - - - -/* add a rectangle to the given Region */ -#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ - if ((rx1 < rx2) && (ry1 < ry2) &&\ - CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ - (r)->x1 = (rx1);\ - (r)->y1 = (ry1);\ - (r)->x2 = (rx2);\ - (r)->y2 = (ry2);\ - (reg)->numRects++;\ - (r)++;\ - }\ - } - -#define EMPTY_REGION(pReg) pReg->numRects = 0 - -#define REGION_NOT_EMPTY(pReg) pReg->numRects - -#define INBOX(r, x, y) \ - ( ( ((r).x2 > x)) && \ - ( ((r).x1 <= x)) && \ - ( ((r).y2 > y)) && \ - ( ((r).y1 <= y)) ) - -/* - * number of points to buffer before sending them off - * to scanlines() : Must be an even number - */ -#define NUMPTSTOBUFFER 200 - -/* - * used to allocate buffers for points and link - * the buffers together - */ -typedef struct _POINTBLOCK { - GdkPoint pts[NUMPTSTOBUFFER]; - struct _POINTBLOCK *next; -} POINTBLOCK; - -#endif /* __GDK_REGION_GENERIC_H__ */ diff --git a/gdk/nanox/Makefile.am b/gdk/nanox/Makefile.am index fc3d1a568a..12762f25b5 100644 --- a/gdk/nanox/Makefile.am +++ b/gdk/nanox/Makefile.am @@ -8,16 +8,18 @@ INCLUDES = @STRIP_BEGIN@ \ @GTK_XIM_FLAGS@ \ @GTK_LOCALE_FLAGS@ \ @GLIB_CFLAGS@ \ - @x_cflags@ \ + @more_cflags@ \ @STRIP_END@ LDADDS = @STRIP_BEGIN@ \ - @x_ldflags@ \ - @x_libs@ \ + @more_ldflags@ \ + @more_libs@ \ @GLIB_LIBS@ \ -lm \ @STRIP_END@ +if USE_NANOX + noinst_LTLIBRARIES = libgdk-nanox.la xinput_sources = \ @@ -38,14 +40,14 @@ libgdk_nanox_la_SOURCES = \ gdkinput.c \ gdkmain-nanox.c \ gdkpixmap-nanox.c \ - gdkpolyreg-generic.c \ gdkproperty-nanox.c \ - gdkregion-generic.c \ gdkselection-nanox.c \ gdkvisual-nanox.c \ gdkwindow-nanox.c \ - gdknanox.h \ gdkprivate-nanox.h \ gdkinput-none.c +else +noinst_LTLIBRARIES = +endif diff --git a/gdk/nanox/gdkpoly-generic.h b/gdk/nanox/gdkpoly-generic.h deleted file mode 100644 index 660c689adb..0000000000 --- a/gdk/nanox/gdkpoly-generic.h +++ /dev/null @@ -1,291 +0,0 @@ -/* $TOG: poly.h /main/5 1998/02/06 17:47:27 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -/* - * This file contains a few macros to help track - * the edge of a filled object. The object is assumed - * to be filled in scanline order, and thus the - * algorithm used is an extension of Bresenham's line - * drawing algorithm which assumes that y is always the - * major axis. - * Since these pieces of code are the same for any filled shape, - * it is more convenient to gather the library in one - * place, but since these pieces of code are also in - * the inner loops of output primitives, procedure call - * overhead is out of the question. - * See the author for a derivation if needed. - */ - - -/* - * In scan converting polygons, we want to choose those pixels - * which are inside the polygon. Thus, we add .5 to the starting - * x coordinate for both left and right edges. Now we choose the - * first pixel which is inside the pgon for the left edge and the - * first pixel which is outside the pgon for the right edge. - * Draw the left pixel, but not the right. - * - * How to add .5 to the starting x coordinate: - * If the edge is moving to the right, then subtract dy from the - * error term from the general form of the algorithm. - * If the edge is moving to the left, then add dy to the error term. - * - * The reason for the difference between edges moving to the left - * and edges moving to the right is simple: If an edge is moving - * to the right, then we want the algorithm to flip immediately. - * If it is moving to the left, then we don't want it to flip until - * we traverse an entire pixel. - */ -#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \ - int dx; /* local storage */ \ -\ - /* \ - * if the edge is horizontal, then it is ignored \ - * and assumed not to be processed. Otherwise, do this stuff. \ - */ \ - if ((dy) != 0) { \ - xStart = (x1); \ - dx = (x2) - xStart; \ - if (dx < 0) { \ - m = dx / (dy); \ - m1 = m - 1; \ - incr1 = -2 * dx + 2 * (dy) * m1; \ - incr2 = -2 * dx + 2 * (dy) * m; \ - d = 2 * m * (dy) - 2 * dx - 2 * (dy); \ - } else { \ - m = dx / (dy); \ - m1 = m + 1; \ - incr1 = 2 * dx - 2 * (dy) * m1; \ - incr2 = 2 * dx - 2 * (dy) * m; \ - d = -2 * m * (dy) + 2 * dx; \ - } \ - } \ -} - -#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \ - if (m1 > 0) { \ - if (d > 0) { \ - minval += m1; \ - d += incr1; \ - } \ - else { \ - minval += m; \ - d += incr2; \ - } \ - } else {\ - if (d >= 0) { \ - minval += m1; \ - d += incr1; \ - } \ - else { \ - minval += m; \ - d += incr2; \ - } \ - } \ -} - - -/* - * This structure contains all of the information needed - * to run the bresenham algorithm. - * The variables may be hardcoded into the declarations - * instead of using this structure to make use of - * register declarations. - */ -typedef struct { - int minor_axis; /* minor axis */ - int d; /* decision variable */ - int m, m1; /* slope and slope+1 */ - int incr1, incr2; /* error increments */ -} BRESINFO; - - -#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \ - BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \ - bres.m, bres.m1, bres.incr1, bres.incr2) - -#define BRESINCRPGONSTRUCT(bres) \ - BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2) - - - -/* - * These are the data structures needed to scan - * convert regions. Two different scan conversion - * methods are available -- the even-odd method, and - * the winding number method. - * The even-odd rule states that a point is inside - * the polygon if a ray drawn from that point in any - * direction will pass through an odd number of - * path segments. - * By the winding number rule, a point is decided - * to be inside the polygon if a ray drawn from that - * point in any direction passes through a different - * number of clockwise and counter-clockwise path - * segments. - * - * These data structures are adapted somewhat from - * the algorithm in (Foley/Van Dam) for scan converting - * polygons. - * The basic algorithm is to start at the top (smallest y) - * of the polygon, stepping down to the bottom of - * the polygon by incrementing the y coordinate. We - * keep a list of edges which the current scanline crosses, - * sorted by x. This list is called the Active Edge Table (AET) - * As we change the y-coordinate, we update each entry in - * in the active edge table to reflect the edges new xcoord. - * This list must be sorted at each scanline in case - * two edges intersect. - * We also keep a data structure known as the Edge Table (ET), - * which keeps track of all the edges which the current - * scanline has not yet reached. The ET is basically a - * list of ScanLineList structures containing a list of - * edges which are entered at a given scanline. There is one - * ScanLineList per scanline at which an edge is entered. - * When we enter a new edge, we move it from the ET to the AET. - * - * From the AET, we can implement the even-odd rule as in - * (Foley/Van Dam). - * The winding number rule is a little trickier. We also - * keep the EdgeTableEntries in the AET linked by the - * nextWETE (winding EdgeTableEntry) link. This allows - * the edges to be linked just as before for updating - * purposes, but only uses the edges linked by the nextWETE - * link as edges representing spans of the polygon to - * drawn (as with the even-odd rule). - */ - -/* - * for the winding number rule - */ -#define CLOCKWISE 1 -#define COUNTERCLOCKWISE -1 - -typedef struct _EdgeTableEntry { - int ymax; /* ycoord at which we exit this edge. */ - BRESINFO bres; /* Bresenham info to run the edge */ - struct _EdgeTableEntry *next; /* next in the list */ - struct _EdgeTableEntry *back; /* for insertion sort */ - struct _EdgeTableEntry *nextWETE; /* for winding num rule */ - int ClockWise; /* flag for winding number rule */ -} EdgeTableEntry; - - -typedef struct _ScanLineList{ - int scanline; /* the scanline represented */ - EdgeTableEntry *edgelist; /* header node */ - struct _ScanLineList *next; /* next in the list */ -} ScanLineList; - - -typedef struct { - int ymax; /* ymax for the polygon */ - int ymin; /* ymin for the polygon */ - ScanLineList scanlines; /* header node */ -} EdgeTable; - - -/* - * Here is a struct to help with storage allocation - * so we can allocate a big chunk at a time, and then take - * pieces from this heap when we need to. - */ -#define SLLSPERBLOCK 25 - -typedef struct _ScanLineListBlock { - ScanLineList SLLs[SLLSPERBLOCK]; - struct _ScanLineListBlock *next; -} ScanLineListBlock; - - - -/* - * - * a few macros for the inner loops of the fill code where - * performance considerations don't allow a procedure call. - * - * Evaluate the given edge at the given scanline. - * If the edge has expired, then we leave it and fix up - * the active edge table; otherwise, we increment the - * x value to be ready for the next scanline. - * The winding number rule is in effect, so we must notify - * the caller when the edge has been removed so he - * can reorder the Winding Active Edge Table. - */ -#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ - if (pAET->ymax == y) { /* leaving this edge */ \ - pPrevAET->next = pAET->next; \ - pAET = pPrevAET->next; \ - fixWAET = 1; \ - if (pAET) \ - pAET->back = pPrevAET; \ - } \ - else { \ - BRESINCRPGONSTRUCT(pAET->bres); \ - pPrevAET = pAET; \ - pAET = pAET->next; \ - } \ -} - - -/* - * Evaluate the given edge at the given scanline. - * If the edge has expired, then we leave it and fix up - * the active edge table; otherwise, we increment the - * x value to be ready for the next scanline. - * The even-odd rule is in effect. - */ -#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ - if (pAET->ymax == y) { /* leaving this edge */ \ - pPrevAET->next = pAET->next; \ - pAET = pPrevAET->next; \ - if (pAET) \ - pAET->back = pPrevAET; \ - } \ - else { \ - BRESINCRPGONSTRUCT(pAET->bres); \ - pPrevAET = pAET; \ - pAET = pAET->next; \ - } \ -} diff --git a/gdk/nanox/gdkpolyreg-generic.c b/gdk/nanox/gdkpolyreg-generic.c deleted file mode 100644 index b98bd5641e..0000000000 --- a/gdk/nanox/gdkpolyreg-generic.c +++ /dev/null @@ -1,616 +0,0 @@ -/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ -/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */ - -#define LARGE_COORDINATE 1000000 -#define SMALL_COORDINATE -LARGE_COORDINATE - -#include <gdkregion.h> -#include "gdkregion-generic.h" -#include "gdkpoly-generic.h" - -/* - * InsertEdgeInET - * - * Insert the given edge into the edge table. - * First we must find the correct bucket in the - * Edge table, then find the right slot in the - * bucket. Finally, we can insert it. - * - */ -static void -InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock) - EdgeTable *ET; - EdgeTableEntry *ETE; - int scanline; - ScanLineListBlock **SLLBlock; - int *iSLLBlock; -{ - EdgeTableEntry *start, *prev; - ScanLineList *pSLL, *pPrevSLL; - ScanLineListBlock *tmpSLLBlock; - - /* - * find the right bucket to put the edge into - */ - pPrevSLL = &ET->scanlines; - pSLL = pPrevSLL->next; - while (pSLL && (pSLL->scanline < scanline)) - { - pPrevSLL = pSLL; - pSLL = pSLL->next; - } - - /* - * reassign pSLL (pointer to ScanLineList) if necessary - */ - if ((!pSLL) || (pSLL->scanline > scanline)) - { - if (*iSLLBlock > SLLSPERBLOCK-1) - { - tmpSLLBlock = - (ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock)); - (*SLLBlock)->next = tmpSLLBlock; - tmpSLLBlock->next = (ScanLineListBlock *)NULL; - *SLLBlock = tmpSLLBlock; - *iSLLBlock = 0; - } - pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]); - - pSLL->next = pPrevSLL->next; - pSLL->edgelist = (EdgeTableEntry *)NULL; - pPrevSLL->next = pSLL; - } - pSLL->scanline = scanline; - - /* - * now insert the edge in the right bucket - */ - prev = (EdgeTableEntry *)NULL; - start = pSLL->edgelist; - while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) - { - prev = start; - start = start->next; - } - ETE->next = start; - - if (prev) - prev->next = ETE; - else - pSLL->edgelist = ETE; -} - -/* - * CreateEdgeTable - * - * This routine creates the edge table for - * scan converting polygons. - * The Edge Table (ET) looks like: - * - * EdgeTable - * -------- - * | ymax | ScanLineLists - * |scanline|-->------------>-------------->... - * -------- |scanline| |scanline| - * |edgelist| |edgelist| - * --------- --------- - * | | - * | | - * V V - * list of ETEs list of ETEs - * - * where ETE is an EdgeTableEntry data structure, - * and there is one ScanLineList per scanline at - * which an edge is initially entered. - * - */ - -static void -CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock) - int count; - GdkPoint *pts; - EdgeTable *ET; - EdgeTableEntry *AET; - EdgeTableEntry *pETEs; - ScanLineListBlock *pSLLBlock; -{ - GdkPoint *top, *bottom; - GdkPoint *PrevPt, *CurrPt; - int iSLLBlock = 0; - int dy; - - if (count < 2) return; - - /* - * initialize the Active Edge Table - */ - AET->next = (EdgeTableEntry *)NULL; - AET->back = (EdgeTableEntry *)NULL; - AET->nextWETE = (EdgeTableEntry *)NULL; - AET->bres.minor_axis = SMALL_COORDINATE; - - /* - * initialize the Edge Table. - */ - ET->scanlines.next = (ScanLineList *)NULL; - ET->ymax = SMALL_COORDINATE; - ET->ymin = LARGE_COORDINATE; - pSLLBlock->next = (ScanLineListBlock *)NULL; - - PrevPt = &pts[count-1]; - - /* - * for each vertex in the array of points. - * In this loop we are dealing with two vertices at - * a time -- these make up one edge of the polygon. - */ - while (count--) - { - CurrPt = pts++; - - /* - * find out which point is above and which is below. - */ - if (PrevPt->y > CurrPt->y) - { - bottom = PrevPt, top = CurrPt; - pETEs->ClockWise = 0; - } - else - { - bottom = CurrPt, top = PrevPt; - pETEs->ClockWise = 1; - } - - /* - * don't add horizontal edges to the Edge table. - */ - if (bottom->y != top->y) - { - pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */ - - /* - * initialize integer edge algorithm - */ - dy = bottom->y - top->y; - BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres); - - InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock); - - if (PrevPt->y > ET->ymax) - ET->ymax = PrevPt->y; - if (PrevPt->y < ET->ymin) - ET->ymin = PrevPt->y; - pETEs++; - } - - PrevPt = CurrPt; - } -} - -/* - * loadAET - * - * This routine moves EdgeTableEntries from the - * EdgeTable into the Active Edge Table, - * leaving them sorted by smaller x coordinate. - * - */ - -static void -loadAET(AET, ETEs) - EdgeTableEntry *AET, *ETEs; -{ - EdgeTableEntry *pPrevAET; - EdgeTableEntry *tmp; - - pPrevAET = AET; - AET = AET->next; - while (ETEs) - { - while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) - { - pPrevAET = AET; - AET = AET->next; - } - tmp = ETEs->next; - ETEs->next = AET; - if (AET) - AET->back = ETEs; - ETEs->back = pPrevAET; - pPrevAET->next = ETEs; - pPrevAET = ETEs; - - ETEs = tmp; - } -} - -/* - * computeWAET - * - * This routine links the AET by the - * nextWETE (winding EdgeTableEntry) link for - * use by the winding number rule. The final - * Active Edge Table (AET) might look something - * like: - * - * AET - * ---------- --------- --------- - * |ymax | |ymax | |ymax | - * | ... | |... | |... | - * |next |->|next |->|next |->... - * |nextWETE| |nextWETE| |nextWETE| - * --------- --------- ^-------- - * | | | - * V-------------------> V---> ... - * - */ -static void -computeWAET(AET) - EdgeTableEntry *AET; -{ - EdgeTableEntry *pWETE; - int inside = 1; - int isInside = 0; - - AET->nextWETE = (EdgeTableEntry *)NULL; - pWETE = AET; - AET = AET->next; - while (AET) - { - if (AET->ClockWise) - isInside++; - else - isInside--; - - if ((!inside && !isInside) || - ( inside && isInside)) - { - pWETE->nextWETE = AET; - pWETE = AET; - inside = !inside; - } - AET = AET->next; - } - pWETE->nextWETE = (EdgeTableEntry *)NULL; -} - -/* - * InsertionSort - * - * Just a simple insertion sort using - * pointers and back pointers to sort the Active - * Edge Table. - * - */ - -static int -InsertionSort(AET) - EdgeTableEntry *AET; -{ - EdgeTableEntry *pETEchase; - EdgeTableEntry *pETEinsert; - EdgeTableEntry *pETEchaseBackTMP; - int changed = 0; - - AET = AET->next; - while (AET) - { - pETEinsert = AET; - pETEchase = AET; - while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis) - pETEchase = pETEchase->back; - - AET = AET->next; - if (pETEchase != pETEinsert) - { - pETEchaseBackTMP = pETEchase->back; - pETEinsert->back->next = AET; - if (AET) - AET->back = pETEinsert->back; - pETEinsert->next = pETEchase; - pETEchase->back->next = pETEinsert; - pETEchase->back = pETEinsert; - pETEinsert->back = pETEchaseBackTMP; - changed = 1; - } - } - return(changed); -} - -/* - * Clean up our act. - */ -static void -FreeStorage(pSLLBlock) - ScanLineListBlock *pSLLBlock; -{ - ScanLineListBlock *tmpSLLBlock; - - while (pSLLBlock) - { - tmpSLLBlock = pSLLBlock->next; - g_free (pSLLBlock); - pSLLBlock = tmpSLLBlock; - } -} - -/* - * Create an array of rectangles from a list of points. - * If indeed these things (POINTS, RECTS) are the same, - * then this proc is still needed, because it allocates - * storage for the array, which was allocated on the - * stack by the calling procedure. - * - */ -static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg) - int numFullPtBlocks, iCurPtBlock; - POINTBLOCK *FirstPtBlock; - GdkRegion *reg; -{ - GdkRegionBox *rects; - GdkPoint *pts; - POINTBLOCK *CurPtBlock; - int i; - GdkRegionBox *extents; - int numRects; - - extents = ®->extents; - - numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1; - - reg->rects = g_renew (GdkRegionBox, reg->rects, numRects); - - reg->size = numRects; - CurPtBlock = FirstPtBlock; - rects = reg->rects - 1; - numRects = 0; - extents->x1 = G_MAXSHORT, extents->x2 = G_MINSHORT; - - for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) { - /* the loop uses 2 points per iteration */ - i = NUMPTSTOBUFFER >> 1; - if (!numFullPtBlocks) - i = iCurPtBlock >> 1; - for (pts = CurPtBlock->pts; i--; pts += 2) { - if (pts->x == pts[1].x) - continue; - if (numRects && pts->x == rects->x1 && pts->y == rects->y2 && - pts[1].x == rects->x2 && - (numRects == 1 || rects[-1].y1 != rects->y1) && - (i && pts[2].y > pts[1].y)) { - rects->y2 = pts[1].y + 1; - continue; - } - numRects++; - rects++; - rects->x1 = pts->x; rects->y1 = pts->y; - rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1; - if (rects->x1 < extents->x1) - extents->x1 = rects->x1; - if (rects->x2 > extents->x2) - extents->x2 = rects->x2; - } - CurPtBlock = CurPtBlock->next; - } - - if (numRects) { - extents->y1 = reg->rects->y1; - extents->y2 = rects->y2; - } else { - extents->x1 = 0; - extents->y1 = 0; - extents->x2 = 0; - extents->y2 = 0; - } - reg->numRects = numRects; - - return(TRUE); -} - -/* - * polytoregion - * - * Scan converts a polygon by returning a run-length - * encoding of the resultant bitmap -- the run-length - * encoding is in the form of an array of rectangles. - */ -GdkRegion * -gdk_region_polygon(GdkPoint *Pts, gint Count, GdkFillRule rule) -{ - GdkRegion *region; - EdgeTableEntry *pAET; /* Active Edge Table */ - int y; /* current scanline */ - int iPts = 0; /* number of pts in buffer */ - EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ - ScanLineList *pSLL; /* current scanLineList */ - GdkPoint *pts; /* output buffer */ - EdgeTableEntry *pPrevAET; /* ptr to previous AET */ - EdgeTable ET; /* header node for ET */ - EdgeTableEntry AET; /* header node for AET */ - EdgeTableEntry *pETEs; /* EdgeTableEntries pool */ - ScanLineListBlock SLLBlock; /* header for scanlinelist */ - int fixWAET = FALSE; - POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ - POINTBLOCK *tmpPtBlock; - int numFullPtBlocks = 0; - - region = gdk_region_new (); - - /* special case a rectangle */ - pts = Pts; - if (((Count == 4) || - ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) && - (((pts[0].y == pts[1].y) && - (pts[1].x == pts[2].x) && - (pts[2].y == pts[3].y) && - (pts[3].x == pts[0].x)) || - ((pts[0].x == pts[1].x) && - (pts[1].y == pts[2].y) && - (pts[2].x == pts[3].x) && - (pts[3].y == pts[0].y)))) { - region->extents.x1 = MIN(pts[0].x, pts[2].x); - region->extents.y1 = MIN(pts[0].y, pts[2].y); - region->extents.x2 = MAX(pts[0].x, pts[2].x); - region->extents.y2 = MAX(pts[0].y, pts[2].y); - if ((region->extents.x1 != region->extents.x2) && - (region->extents.y1 != region->extents.y2)) { - region->numRects = 1; - *(region->rects) = region->extents; - } - return(region); - } - - pETEs = g_new (EdgeTableEntry, Count); - - pts = FirstPtBlock.pts; - CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock); - pSLL = ET.scanlines.next; - curPtBlock = &FirstPtBlock; - - if (rule == GDK_EVEN_ODD_RULE) { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL != NULL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - - /* - * for each active edge - */ - while (pAET) { - pts->x = pAET->bres.minor_axis, pts->y = y; - pts++, iPts++; - - /* - * send out the buffer - */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK)); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - numFullPtBlocks++; - iPts = 0; - } - EVALUATEEDGEEVENODD(pAET, pPrevAET, y); - } - (void) InsertionSort(&AET); - } - } - else { - /* - * for each scanline - */ - for (y = ET.ymin; y < ET.ymax; y++) { - /* - * Add a new edge to the active edge table when we - * get to the next edge. - */ - if (pSLL != NULL && y == pSLL->scanline) { - loadAET(&AET, pSLL->edgelist); - computeWAET(&AET); - pSLL = pSLL->next; - } - pPrevAET = &AET; - pAET = AET.next; - pWETE = pAET; - - /* - * for each active edge - */ - while (pAET) { - /* - * add to the buffer only those edges that - * are in the Winding active edge table. - */ - if (pWETE == pAET) { - pts->x = pAET->bres.minor_axis, pts->y = y; - pts++, iPts++; - - /* - * send out the buffer - */ - if (iPts == NUMPTSTOBUFFER) { - tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK)); - curPtBlock->next = tmpPtBlock; - curPtBlock = tmpPtBlock; - pts = curPtBlock->pts; - numFullPtBlocks++; iPts = 0; - } - pWETE = pWETE->nextWETE; - } - EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); - } - - /* - * recompute the winding active edge table if - * we just resorted or have exited an edge. - */ - if (InsertionSort(&AET) || fixWAET) { - computeWAET(&AET); - fixWAET = FALSE; - } - } - } - FreeStorage(SLLBlock.next); - (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); - for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { - tmpPtBlock = curPtBlock->next; - g_free (curPtBlock); - curPtBlock = tmpPtBlock; - } - g_free (pETEs); - return(region); -} diff --git a/gdk/nanox/gdkregion-generic.c b/gdk/nanox/gdkregion-generic.c deleted file mode 100644 index 0319f939f4..0000000000 --- a/gdk/nanox/gdkregion-generic.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* $TOG: Region.c /main/31 1998/02/06 17:50:22 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1988, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ -/* $XFree86: xc/lib/X11/Region.c,v 1.5 1999/05/09 10:50:01 dawes Exp $ */ -/* - * The functions in this file implement the Region abstraction, similar to one - * used in the X11 sample server. A Region is simply an area, as the name - * implies, and is implemented as a "y-x-banded" array of rectangles. To - * explain: Each Region is made up of a certain number of rectangles sorted - * by y coordinate first, and then by x coordinate. - * - * Furthermore, the rectangles are banded such that every rectangle with a - * given upper-left y coordinate (y1) will have the same lower-right y - * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it - * will span the entire vertical distance of the band. This means that some - * areas that could be merged into a taller rectangle will be represented as - * several shorter rectangles to account for shorter rectangles to its left - * or right but within its "vertical scope". - * - * An added constraint on the rectangles is that they must cover as much - * horizontal area as possible. E.g. no two rectangles in a band are allowed - * to touch. - * - * Whenever possible, bands will be merged together to cover a greater vertical - * distance (and thus reduce the number of rectangles). Two bands can be merged - * only if the bottom of one touches the top of the other and they have - * rectangles in the same places (of the same width, of course). This maintains - * the y-x-banding that's so nice to have... - */ - -#include <gdkregion.h> -#include "gdkregion-generic.h" - -#ifdef DEBUG -#include <stdio.h> -#define assert(expr) {if (!(expr)) fprintf(stderr,\ -"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); } -#else -#define assert(expr) -#endif - -typedef void (*overlapFunc) (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2); -typedef void (*nonOverlapFunc) (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2); - -static void miRegionCopy (GdkRegion *dstrgn, - GdkRegion *rgn); -static void miRegionOp (GdkRegion *newReg, - GdkRegion *reg1, - GdkRegion *reg2, - overlapFunc overlapFn, - nonOverlapFunc nonOverlap1Fn, - nonOverlapFunc nonOverlap2Fn); - -/* Create a new empty region */ - -GdkRegion * -gdk_region_new () -{ - GdkRegion *temp; - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, 1); - - temp->numRects = 0; - temp->extents.x1 = 0; - temp->extents.y1 = 0; - temp->extents.x2 = 0; - temp->extents.y2 = 0; - temp->size = 1; - - return temp; -} - -GdkRegion * -gdk_region_rectangle (GdkRectangle *rectangle) -{ - GdkRegion *temp; - - if (rectangle->width <= 0 || rectangle->height <= 0) - return gdk_region_new(); - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, 1); - - temp->numRects = 1; - temp->extents.x1 = temp->rects[0].x1 = rectangle->x; - temp->extents.y1 = temp->rects[0].y1 = rectangle->y; - temp->extents.x2 = temp->rects[0].x2 = rectangle->x + rectangle->width; - temp->extents.y2 = temp->rects[0].y2 = rectangle->y + rectangle->height; - temp->size = 1; - - return temp; -} - -GdkRegion * -gdk_region_copy (GdkRegion *region) -{ - GdkRegion *temp; - - temp = g_new (GdkRegion, 1); - temp->rects = g_new (GdkRegionBox, region->numRects); - - temp->numRects = region->numRects; - temp->extents = region->extents; - temp->size = region->numRects; - - memcpy (temp->rects, region->rects, region->numRects * sizeof (GdkRegionBox)); - - return temp; -} - -void -gdk_region_get_clipbox (GdkRegion *r, GdkRectangle *rect) -{ - rect->x = r->extents.x1; - rect->y = r->extents.y1; - rect->width = r->extents.x2 - r->extents.x1; - rect->height = r->extents.y2 - r->extents.y1; -} - -void -gdk_region_union_with_rect (GdkRegion *region, - GdkRectangle *rect) -{ - GdkRegion tmp_region; - - if (!rect->width || !rect->height) - return; - - tmp_region.rects = &tmp_region.extents; - tmp_region.numRects = 1; - tmp_region.extents.x1 = rect->x; - tmp_region.extents.y1 = rect->y; - tmp_region.extents.x2 = rect->x + rect->width; - tmp_region.extents.y2 = rect->y + rect->height; - tmp_region.size = 1; - - gdk_region_union (region, &tmp_region); -} - -/*- - *----------------------------------------------------------------------- - * miSetExtents -- - * Reset the extents of a region to what they should be. Called by - * miSubtract and miIntersect b/c they can't figure it out along the - * way or do so easily, as miUnion can. - * - * Results: - * None. - * - * Side Effects: - * The region's 'extents' structure is overwritten. - * - *----------------------------------------------------------------------- - */ -static void -miSetExtents (GdkRegion *pReg) -{ - GdkRegionBox *pBox, *pBoxEnd, *pExtents; - - if (pReg->numRects == 0) - { - pReg->extents.x1 = 0; - pReg->extents.y1 = 0; - pReg->extents.x2 = 0; - pReg->extents.y2 = 0; - return; - } - - pExtents = &pReg->extents; - pBox = pReg->rects; - pBoxEnd = &pBox[pReg->numRects - 1]; - - /* - * Since pBox is the first rectangle in the region, it must have the - * smallest y1 and since pBoxEnd is the last rectangle in the region, - * it must have the largest y2, because of banding. Initialize x1 and - * x2 from pBox and pBoxEnd, resp., as good things to initialize them - * to... - */ - pExtents->x1 = pBox->x1; - pExtents->y1 = pBox->y1; - pExtents->x2 = pBoxEnd->x2; - pExtents->y2 = pBoxEnd->y2; - - assert(pExtents->y1 < pExtents->y2); - while (pBox <= pBoxEnd) - { - if (pBox->x1 < pExtents->x1) - { - pExtents->x1 = pBox->x1; - } - if (pBox->x2 > pExtents->x2) - { - pExtents->x2 = pBox->x2; - } - pBox++; - } - assert(pExtents->x1 < pExtents->x2); -} - -void -gdk_region_destroy (GdkRegion *r) -{ - g_free (r->rects); - g_free (r); -} - - -/* TranslateRegion(pRegion, x, y) - translates in place - added by raymond -*/ - -void -gdk_region_offset (GdkRegion *region, - gint x, - gint y) -{ - int nbox; - GdkRegionBox *pbox; - - pbox = region->rects; - nbox = region->numRects; - - while(nbox--) - { - pbox->x1 += x; - pbox->x2 += x; - pbox->y1 += y; - pbox->y2 += y; - pbox++; - } - region->extents.x1 += x; - region->extents.x2 += x; - region->extents.y1 += y; - region->extents.y2 += y; -} - -/* - Utility procedure Compress: - Replace r by the region r', where - p in r' iff (Quantifer m <= dx) (p + m in r), and - Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and - (x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE. - - Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region - of all points p such that p and the next dx points on the same - horizontal scan line are all in r. We do this using by noting - that p is the head of a run of length 2^i + k iff p is the head - of a run of length 2^i and p+2^i is the head of a run of length - k. Thus, the loop invariant: s contains the region corresponding - to the runs of length shift. r contains the region corresponding - to the runs of length 1 + dxo & (shift-1), where dxo is the original - value of dx. dx = dxo & ~(shift-1). As parameters, s and t are - scratch regions, so that we don't have to allocate them on every - call. -*/ - -#define ZOpRegion(a,b) if (grow) gdk_region_union (a, b); \ - else gdk_region_intersect (a,b) -#define ZShiftRegion(a,b) if (xdir) gdk_region_offset (a,b,0); \ - else gdk_region_offset (a,0,b) - -static void -Compress(GdkRegion *r, - GdkRegion *s, - GdkRegion *t, - guint dx, - int xdir, - int grow) -{ - guint shift = 1; - - miRegionCopy (s, r); - while (dx) - { - if (dx & shift) - { - ZShiftRegion(r, -(int)shift); - ZOpRegion(r, s); - dx -= shift; - if (!dx) break; - } - miRegionCopy (t, s); - ZShiftRegion(s, -(int)shift); - ZOpRegion(s, t); - shift <<= 1; - } -} - -#undef ZOpRegion -#undef ZShiftRegion -#undef ZCopyRegion - -void -gdk_region_shrink (GdkRegion *r, - int dx, - int dy) -{ - GdkRegion *s, *t; - int grow; - - if (!dx && !dy) - return; - - s = gdk_region_new (); - t = gdk_region_new (); - - grow = (dx < 0); - if (grow) - dx = -dx; - if (dx) - Compress(r, s, t, (unsigned) 2*dx, TRUE, grow); - - grow = (dy < 0); - if (grow) - dy = -dy; - if (dy) - Compress(r, s, t, (unsigned) 2*dy, FALSE, grow); - - gdk_region_offset (r, dx, dy); - gdk_region_destroy (s); - gdk_region_destroy (t); -} - - -/*====================================================================== - * Region Intersection - *====================================================================*/ -/*- - *----------------------------------------------------------------------- - * miIntersectO -- - * Handle an overlapping band for miIntersect. - * - * Results: - * None. - * - * Side Effects: - * Rectangles may be added to the region. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miIntersectO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - int x1; - int x2; - GdkRegionBox *pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - while ((r1 != r1End) && (r2 != r2End)) - { - x1 = MAX (r1->x1,r2->x1); - x2 = MIN (r1->x2,r2->x2); - - /* - * If there's any overlap between the two rectangles, add that - * overlap to the new region. - * There's no need to check for subsumption because the only way - * such a need could arise is if some region has two rectangles - * right next to each other. Since that should never happen... - */ - if (x1 < x2) - { - assert (y1<y2); - - MEMCHECK (pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - assert (pReg->numRects <= pReg->size); - } - - /* - * Need to advance the pointers. Shift the one that extends - * to the right the least, since the other still has a chance to - * overlap with that region's next rectangle, if you see what I mean. - */ - if (r1->x2 < r2->x2) - { - r1++; - } - else if (r2->x2 < r1->x2) - { - r2++; - } - else - { - r1++; - r2++; - } - } -} - -void -gdk_region_intersect (GdkRegion *region, - GdkRegion *other) -{ - /* check for trivial reject */ - if ((!(region->numRects)) || (!(other->numRects)) || - (!EXTENTCHECK(®ion->extents, &other->extents))) - region->numRects = 0; - else - miRegionOp (region, region, other, - miIntersectO, (nonOverlapFunc) NULL, (nonOverlapFunc) NULL); - - /* - * Can't alter region's extents before miRegionOp depends on the - * extents of the regions being unchanged. Besides, this way there's - * no checking against rectangles that will be nuked due to - * coalescing, so we have to examine fewer rectangles. - */ - miSetExtents(region); -} - -static void -miRegionCopy(GdkRegion *dstrgn, GdkRegion *rgn) -{ - if (dstrgn != rgn) /* don't want to copy to itself */ - { - if (dstrgn->size < rgn->numRects) - { - dstrgn->rects = g_renew (GdkRegionBox, dstrgn->rects, rgn->numRects); - dstrgn->size = rgn->numRects; - } - dstrgn->numRects = rgn->numRects; - dstrgn->extents.x1 = rgn->extents.x1; - dstrgn->extents.y1 = rgn->extents.y1; - dstrgn->extents.x2 = rgn->extents.x2; - dstrgn->extents.y2 = rgn->extents.y2; - - memcpy (dstrgn->rects, rgn->rects, rgn->numRects * sizeof (GdkRegionBox)); - } -} - - -/*====================================================================== - * Generic Region Operator - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miCoalesce -- - * Attempt to merge the boxes in the current band with those in the - * previous one. Used only by miRegionOp. - * - * Results: - * The new index for the previous band. - * - * Side Effects: - * If coalescing takes place: - * - rectangles in the previous band will have their y2 fields - * altered. - * - pReg->numRects will be decreased. - * - *----------------------------------------------------------------------- - */ -/* static int*/ -static int -miCoalesce (GdkRegion *pReg, /* Region to coalesce */ - gint prevStart, /* Index of start of previous band */ - gint curStart) /* Index of start of current band */ -{ - GdkRegionBox *pPrevBox; /* Current box in previous band */ - GdkRegionBox *pCurBox; /* Current box in current band */ - GdkRegionBox *pRegEnd; /* End of region */ - int curNumRects; /* Number of rectangles in current - * band */ - int prevNumRects; /* Number of rectangles in previous - * band */ - int bandY1; /* Y1 coordinate for current band */ - - pRegEnd = &pReg->rects[pReg->numRects]; - - pPrevBox = &pReg->rects[prevStart]; - prevNumRects = curStart - prevStart; - - /* - * Figure out how many rectangles are in the current band. Have to do - * this because multiple bands could have been added in miRegionOp - * at the end when one region has been exhausted. - */ - pCurBox = &pReg->rects[curStart]; - bandY1 = pCurBox->y1; - for (curNumRects = 0; - (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1); - curNumRects++) - { - pCurBox++; - } - - if (pCurBox != pRegEnd) - { - /* - * If more than one band was added, we have to find the start - * of the last band added so the next coalescing job can start - * at the right place... (given when multiple bands are added, - * this may be pointless -- see above). - */ - pRegEnd--; - while (pRegEnd[-1].y1 == pRegEnd->y1) - { - pRegEnd--; - } - curStart = pRegEnd - pReg->rects; - pRegEnd = pReg->rects + pReg->numRects; - } - - if ((curNumRects == prevNumRects) && (curNumRects != 0)) { - pCurBox -= curNumRects; - /* - * The bands may only be coalesced if the bottom of the previous - * matches the top scanline of the current. - */ - if (pPrevBox->y2 == pCurBox->y1) - { - /* - * Make sure the bands have boxes in the same places. This - * assumes that boxes have been added in such a way that they - * cover the most area possible. I.e. two boxes in a band must - * have some horizontal space between them. - */ - do - { - if ((pPrevBox->x1 != pCurBox->x1) || - (pPrevBox->x2 != pCurBox->x2)) - { - /* - * The bands don't line up so they can't be coalesced. - */ - return (curStart); - } - pPrevBox++; - pCurBox++; - prevNumRects -= 1; - } while (prevNumRects != 0); - - pReg->numRects -= curNumRects; - pCurBox -= curNumRects; - pPrevBox -= curNumRects; - - /* - * The bands may be merged, so set the bottom y of each box - * in the previous band to that of the corresponding box in - * the current band. - */ - do - { - pPrevBox->y2 = pCurBox->y2; - pPrevBox++; - pCurBox++; - curNumRects -= 1; - } - while (curNumRects != 0); - - /* - * If only one band was added to the region, we have to backup - * curStart to the start of the previous band. - * - * If more than one band was added to the region, copy the - * other bands down. The assumption here is that the other bands - * came from the same region as the current one and no further - * coalescing can be done on them since it's all been done - * already... curStart is already in the right place. - */ - if (pCurBox == pRegEnd) - { - curStart = prevStart; - } - else - { - do - { - *pPrevBox++ = *pCurBox++; - } - while (pCurBox != pRegEnd); - } - - } - } - return curStart; -} - -/*- - *----------------------------------------------------------------------- - * miRegionOp -- - * Apply an operation to two regions. Called by miUnion, miInverse, - * miSubtract, miIntersect... - * - * Results: - * None. - * - * Side Effects: - * The new region is overwritten. - * - * Notes: - * The idea behind this function is to view the two regions as sets. - * Together they cover a rectangle of area that this function divides - * into horizontal bands where points are covered only by one region - * or by both. For the first case, the nonOverlapFunc is called with - * each the band and the band's upper and lower extents. For the - * second, the overlapFunc is called to process the entire band. It - * is responsible for clipping the rectangles in the band, though - * this function provides the boundaries. - * At the end of each band, the new region is coalesced, if possible, - * to reduce the number of rectangles in the region. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miRegionOp(GdkRegion *newReg, - GdkRegion *reg1, - GdkRegion *reg2, - overlapFunc overlapFn, /* Function to call for over- - * lapping bands */ - nonOverlapFunc nonOverlap1Fn, /* Function to call for non- - * overlapping bands in region - * 1 */ - nonOverlapFunc nonOverlap2Fn) /* Function to call for non- - * overlapping bands in region - * 2 */ -{ - GdkRegionBox *r1; /* Pointer into first region */ - GdkRegionBox *r2; /* Pointer into 2d region */ - GdkRegionBox *r1End; /* End of 1st region */ - GdkRegionBox *r2End; /* End of 2d region */ - int ybot; /* Bottom of intersection */ - int ytop; /* Top of intersection */ - GdkRegionBox *oldRects; /* Old rects for newReg */ - int prevBand; /* Index of start of - * previous band in newReg */ - int curBand; /* Index of start of current - * band in newReg */ - GdkRegionBox *r1BandEnd; /* End of current band in r1 */ - GdkRegionBox *r2BandEnd; /* End of current band in r2 */ - int top; /* Top of non-overlapping - * band */ - int bot; /* Bottom of non-overlapping - * band */ - - /* - * Initialization: - * set r1, r2, r1End and r2End appropriately, preserve the important - * parts of the destination region until the end in case it's one of - * the two source regions, then mark the "new" region empty, allocating - * another array of rectangles for it to use. - */ - r1 = reg1->rects; - r2 = reg2->rects; - r1End = r1 + reg1->numRects; - r2End = r2 + reg2->numRects; - - oldRects = newReg->rects; - - EMPTY_REGION(newReg); - - /* - * Allocate a reasonable number of rectangles for the new region. The idea - * is to allocate enough so the individual functions don't need to - * reallocate and copy the array, which is time consuming, yet we don't - * have to worry about using too much memory. I hope to be able to - * nuke the Xrealloc() at the end of this function eventually. - */ - newReg->size = MAX (reg1->numRects, reg2->numRects) * 2; - newReg->rects = g_new (GdkRegionBox, newReg->size); - - /* - * Initialize ybot and ytop. - * In the upcoming loop, ybot and ytop serve different functions depending - * on whether the band being handled is an overlapping or non-overlapping - * band. - * In the case of a non-overlapping band (only one of the regions - * has points in the band), ybot is the bottom of the most recent - * intersection and thus clips the top of the rectangles in that band. - * ytop is the top of the next intersection between the two regions and - * serves to clip the bottom of the rectangles in the current band. - * For an overlapping band (where the two regions intersect), ytop clips - * the top of the rectangles of both regions and ybot clips the bottoms. - */ - if (reg1->extents.y1 < reg2->extents.y1) - ybot = reg1->extents.y1; - else - ybot = reg2->extents.y1; - - /* - * prevBand serves to mark the start of the previous band so rectangles - * can be coalesced into larger rectangles. qv. miCoalesce, above. - * In the beginning, there is no previous band, so prevBand == curBand - * (curBand is set later on, of course, but the first band will always - * start at index 0). prevBand and curBand must be indices because of - * the possible expansion, and resultant moving, of the new region's - * array of rectangles. - */ - prevBand = 0; - - do - { - curBand = newReg->numRects; - - /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - r1BandEnd = r1; - while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1)) - { - r1BandEnd++; - } - - r2BandEnd = r2; - while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1)) - { - r2BandEnd++; - } - - /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1->y1 < r2->y1) - { - top = MAX (r1->y1,ybot); - bot = MIN (r1->y2,r2->y1); - - if ((top != bot) && (nonOverlap1Fn != (void (*)())NULL)) - { - (* nonOverlap1Fn) (newReg, r1, r1BandEnd, top, bot); - } - - ytop = r2->y1; - } - else if (r2->y1 < r1->y1) - { - top = MAX (r2->y1,ybot); - bot = MIN (r2->y2,r1->y1); - - if ((top != bot) && (nonOverlap2Fn != (void (*)())NULL)) - { - (* nonOverlap2Fn) (newReg, r2, r2BandEnd, top, bot); - } - - ytop = r1->y1; - } - else - { - ytop = r1->y1; - } - - /* - * If any rectangles got added to the region, try and coalesce them - * with rectangles from the previous band. Note we could just do - * this test in miCoalesce, but some machines incur a not - * inconsiderable cost for function calls, so... - */ - if (newReg->numRects != curBand) - { - prevBand = miCoalesce (newReg, prevBand, curBand); - } - - /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = MIN (r1->y2, r2->y2); - curBand = newReg->numRects; - if (ybot > ytop) - { - (* overlapFn) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); - - } - - if (newReg->numRects != curBand) - { - prevBand = miCoalesce (newReg, prevBand, curBand); - } - - /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) - { - r1 = r1BandEnd; - } - if (r2->y2 == ybot) - { - r2 = r2BandEnd; - } - } while ((r1 != r1End) && (r2 != r2End)); - - /* - * Deal with whichever region still has rectangles left. - */ - curBand = newReg->numRects; - if (r1 != r1End) - { - if (nonOverlap1Fn != (nonOverlapFunc )NULL) - { - do - { - r1BandEnd = r1; - while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1)) - { - r1BandEnd++; - } - (* nonOverlap1Fn) (newReg, r1, r1BandEnd, - MAX (r1->y1,ybot), r1->y2); - r1 = r1BandEnd; - } while (r1 != r1End); - } - } - else if ((r2 != r2End) && (nonOverlap2Fn != (nonOverlapFunc) NULL)) - { - do - { - r2BandEnd = r2; - while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1)) - { - r2BandEnd++; - } - (* nonOverlap2Fn) (newReg, r2, r2BandEnd, - MAX (r2->y1,ybot), r2->y2); - r2 = r2BandEnd; - } while (r2 != r2End); - } - - if (newReg->numRects != curBand) - { - (void) miCoalesce (newReg, prevBand, curBand); - } - - /* - * A bit of cleanup. To keep regions from growing without bound, - * we shrink the array of rectangles to match the new number of - * rectangles in the region. This never goes to 0, however... - * - * Only do this stuff if the number of rectangles allocated is more than - * twice the number of rectangles in the region (a simple optimization...). - */ - if (newReg->numRects < (newReg->size >> 1)) - { - if (REGION_NOT_EMPTY (newReg)) - { - newReg->size = newReg->numRects; - newReg->rects = g_renew (GdkRegionBox, newReg->rects, newReg->size); - } - else - { - /* - * No point in doing the extra work involved in an Xrealloc if - * the region is empty - */ - newReg->size = 1; - g_free (newReg->rects); - newReg->rects = g_new (GdkRegionBox, 1); - } - } - g_free (oldRects); -} - - -/*====================================================================== - * Region Union - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miUnionNonO -- - * Handle a non-overlapping band for the union operation. Just - * Adds the rectangles into the region. Doesn't have to check for - * subsumption or anything. - * - * Results: - * None. - * - * Side Effects: - * pReg->numRects is incremented and the final rectangles overwritten - * with the rectangles we're passed. - * - *----------------------------------------------------------------------- - */ -static void -miUnionNonO (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2) -{ - GdkRegionBox *pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - assert(y1 < y2); - - while (r != rEnd) - { - assert(r->x1 < r->x2); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = r->x1; - pNextRect->y1 = y1; - pNextRect->x2 = r->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - r++; - } -} - - -/*- - *----------------------------------------------------------------------- - * miUnionO -- - * Handle an overlapping band for the union operation. Picks the - * left-most rectangle each time and merges it into the region. - * - * Results: - * None. - * - * Side Effects: - * Rectangles are overwritten in pReg->rects and pReg->numRects will - * be changed. - * - *----------------------------------------------------------------------- - */ - -/* static void*/ -static void -miUnionO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - -#define MERGERECT(r) \ - if ((pReg->numRects != 0) && \ - (pNextRect[-1].y1 == y1) && \ - (pNextRect[-1].y2 == y2) && \ - (pNextRect[-1].x2 >= r->x1)) \ - { \ - if (pNextRect[-1].x2 < r->x2) \ - { \ - pNextRect[-1].x2 = r->x2; \ - assert(pNextRect[-1].x1<pNextRect[-1].x2); \ - } \ - } \ - else \ - { \ - MEMCHECK(pReg, pNextRect, pReg->rects); \ - pNextRect->y1 = y1; \ - pNextRect->y2 = y2; \ - pNextRect->x1 = r->x1; \ - pNextRect->x2 = r->x2; \ - pReg->numRects += 1; \ - pNextRect += 1; \ - } \ - assert(pReg->numRects<=pReg->size); \ - r++; - - assert (y1<y2); - while ((r1 != r1End) && (r2 != r2End)) - { - if (r1->x1 < r2->x1) - { - MERGERECT(r1); - } - else - { - MERGERECT(r2); - } - } - - if (r1 != r1End) - { - do - { - MERGERECT(r1); - } while (r1 != r1End); - } - else while (r2 != r2End) - { - MERGERECT(r2); - } -} - -void -gdk_region_union (GdkRegion *region, - GdkRegion *other) -{ - /* checks all the simple cases */ - - /* - * region and other are the same or other is empty - */ - if ((region == other) || (!(other->numRects))) - return; - - /* - * region is empty - */ - if (!(region->numRects)) - { - miRegionCopy (region, other); - return; - } - - /* - * region completely subsumes otehr - */ - if ((region->numRects == 1) && - (region->extents.x1 <= other->extents.x1) && - (region->extents.y1 <= other->extents.y1) && - (region->extents.x2 >= other->extents.x2) && - (region->extents.y2 >= other->extents.y2)) - return; - - /* - * other completely subsumes region - */ - if ((other->numRects == 1) && - (other->extents.x1 <= region->extents.x1) && - (other->extents.y1 <= region->extents.y1) && - (other->extents.x2 >= region->extents.x2) && - (other->extents.y2 >= region->extents.y2)) - { - miRegionCopy(region, other); - return; - } - - miRegionOp (region, region, other, miUnionO, - miUnionNonO, miUnionNonO); - - region->extents.x1 = MIN (region->extents.x1, other->extents.x1); - region->extents.y1 = MIN (region->extents.y1, other->extents.y1); - region->extents.x2 = MAX (region->extents.x2, other->extents.x2); - region->extents.y2 = MAX (region->extents.y2, other->extents.y2); -} - - -/*====================================================================== - * Region Subtraction - *====================================================================*/ - -/*- - *----------------------------------------------------------------------- - * miSubtractNonO -- - * Deal with non-overlapping band for subtraction. Any parts from - * region 2 we discard. Anything from region 1 we add to the region. - * - * Results: - * None. - * - * Side Effects: - * pReg may be affected. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miSubtractNonO1 (GdkRegion *pReg, - GdkRegionBox *r, - GdkRegionBox *rEnd, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - - pNextRect = &pReg->rects[pReg->numRects]; - - assert(y1<y2); - - while (r != rEnd) - { - assert (r->x1<r->x2); - MEMCHECK (pReg, pNextRect, pReg->rects); - pNextRect->x1 = r->x1; - pNextRect->y1 = y1; - pNextRect->x2 = r->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert (pReg->numRects <= pReg->size); - - r++; - } -} - -/*- - *----------------------------------------------------------------------- - * miSubtractO -- - * Overlapping band subtraction. x1 is the left-most point not yet - * checked. - * - * Results: - * None. - * - * Side Effects: - * pReg may have rectangles added to it. - * - *----------------------------------------------------------------------- - */ -/* static void*/ -static void -miSubtractO (GdkRegion *pReg, - GdkRegionBox *r1, - GdkRegionBox *r1End, - GdkRegionBox *r2, - GdkRegionBox *r2End, - gint y1, - gint y2) -{ - GdkRegionBox * pNextRect; - int x1; - - x1 = r1->x1; - - assert(y1<y2); - pNextRect = &pReg->rects[pReg->numRects]; - - while ((r1 != r1End) && (r2 != r2End)) - { - if (r2->x2 <= x1) - { - /* - * Subtrahend missed the boat: go to next subtrahend. - */ - r2++; - } - else if (r2->x1 <= x1) - { - /* - * Subtrahend preceeds minuend: nuke left edge of minuend. - */ - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend completely covered: advance to next minuend and - * reset left fence to edge of new minuend. - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend now used up since it doesn't extend beyond - * minuend - */ - r2++; - } - } - else if (r2->x1 < r1->x2) - { - /* - * Left part of subtrahend covers part of minuend: add uncovered - * part of minuend to region and skip to next subtrahend. - */ - assert(x1<r2->x1); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r2->x1; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - - x1 = r2->x2; - if (x1 >= r1->x2) - { - /* - * Minuend used up: advance to new... - */ - r1++; - if (r1 != r1End) - x1 = r1->x1; - } - else - { - /* - * Subtrahend used up - */ - r2++; - } - } - else - { - /* - * Minuend used up: add any remaining piece before advancing. - */ - if (r1->x2 > x1) - { - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r1->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - assert(pReg->numRects<=pReg->size); - } - r1++; - x1 = r1->x1; - } - } - - /* - * Add remaining minuend rectangles to region. - */ - while (r1 != r1End) - { - assert(x1<r1->x2); - MEMCHECK(pReg, pNextRect, pReg->rects); - pNextRect->x1 = x1; - pNextRect->y1 = y1; - pNextRect->x2 = r1->x2; - pNextRect->y2 = y2; - pReg->numRects += 1; - pNextRect++; - - assert(pReg->numRects<=pReg->size); - - r1++; - if (r1 != r1End) - { - x1 = r1->x1; - } - } -} - -/*- - *----------------------------------------------------------------------- - * gdk_region_subtract -- - * Subtract other from region and leave the result in region. - * - * Results: - * TRUE. - * - * Side Effects: - * region is overwritten. - * - *----------------------------------------------------------------------- - */ - -void -gdk_region_subtract (GdkRegion *region, - GdkRegion *other) -{ - /* check for trivial reject */ - if ((!(region->numRects)) || (!(other->numRects)) || - (!EXTENTCHECK(®ion->extents, &other->extents))) - return; - - miRegionOp (region, region, other, miSubtractO, - miSubtractNonO1, (nonOverlapFunc) NULL); - - /* - * Can't alter region's extents before we call miRegionOp because miRegionOp - * depends on the extents of those regions being the unaltered. Besides, this - * way there's no checking against rectangles that will be nuked - * due to coalescing, so we have to examine fewer rectangles. - */ - miSetExtents (region); -} - -void -gdk_region_xor (GdkRegion *sra, - GdkRegion *srb) -{ - GdkRegion *trb; - - trb = gdk_region_copy (srb); - - gdk_region_subtract (trb, sra); - gdk_region_subtract (sra, srb); - - gdk_region_union (sra,trb); - - gdk_region_destroy (trb); -} - -/* - * Check to see if the region is empty. Assumes a region is passed - * as a parameter - */ -gboolean -gdk_region_empty (GdkRegion *r) -{ - if (r->numRects == 0) - return TRUE; - else - return FALSE; -} - -/* - * Check to see if two regions are equal - */ -gboolean -gdk_region_equal (GdkRegion *r1, - GdkRegion *r2) -{ - int i; - - if (r1->numRects != r2->numRects) return FALSE; - else if (r1->numRects == 0) return TRUE; - else if (r1->extents.x1 != r2->extents.x1) return FALSE; - else if (r1->extents.x2 != r2->extents.x2) return FALSE; - else if (r1->extents.y1 != r2->extents.y1) return FALSE; - else if (r1->extents.y2 != r2->extents.y2) return FALSE; - else - for(i=0; i < r1->numRects; i++ ) - { - if (r1->rects[i].x1 != r2->rects[i].x1) return FALSE; - else if (r1->rects[i].x2 != r2->rects[i].x2) return FALSE; - else if (r1->rects[i].y1 != r2->rects[i].y1) return FALSE; - else if (r1->rects[i].y2 != r2->rects[i].y2) return FALSE; - } - return TRUE; -} - -gboolean -gdk_region_point_in (GdkRegion *region, - int x, - int y) -{ - int i; - - if (region->numRects == 0) - return FALSE; - if (!INBOX(region->extents, x, y)) - return FALSE; - for (i=0; i<region->numRects; i++) - { - if (INBOX (region->rects[i], x, y)) - return TRUE; - } - return FALSE; -} - -GdkOverlapType -gdk_region_rect_in (GdkRegion *region, - GdkRectangle *rectangle) -{ - GdkRegionBox *pbox; - GdkRegionBox *pboxEnd; - GdkRegionBox rect; - GdkRegionBox *prect = ▭ - gboolean partIn, partOut; - - gint rx = rectangle->x; - gint ry = rectangle->y; - - prect->x1 = rx; - prect->y1 = ry; - prect->x2 = rx + rectangle->width; - prect->y2 = ry + rectangle->height; - - /* this is (just) a useful optimization */ - if ((region->numRects == 0) || !EXTENTCHECK (®ion->extents, prect)) - return GDK_OVERLAP_RECTANGLE_IN; - - partOut = FALSE; - partIn = FALSE; - - /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ - for (pbox = region->rects, pboxEnd = pbox + region->numRects; - pbox < pboxEnd; - pbox++) - { - - if (pbox->y2 <= ry) - continue; /* getting up to speed or skipping remainder of band */ - - if (pbox->y1 > ry) - { - partOut = TRUE; /* missed part of rectangle above */ - if (partIn || (pbox->y1 >= prect->y2)) - break; - ry = pbox->y1; /* x guaranteed to be == prect->x1 */ - } - - if (pbox->x2 <= rx) - continue; /* not far enough over yet */ - - if (pbox->x1 > rx) - { - partOut = TRUE; /* missed part of rectangle to left */ - if (partIn) - break; - } - - if (pbox->x1 < prect->x2) - { - partIn = TRUE; /* definitely overlap */ - if (partOut) - break; - } - - if (pbox->x2 >= prect->x2) - { - ry = pbox->y2; /* finished with this band */ - if (ry >= prect->y2) - break; - rx = prect->x1; /* reset x out to left again */ - } - else - { - /* - * Because boxes in a band are maximal width, if the first box - * to overlap the rectangle doesn't completely cover it in that - * band, the rectangle must be partially out, since some of it - * will be uncovered in that band. partIn will have been set true - * by now... - */ - break; - } - - } - - return (partIn ? - ((ry < prect->y2) ? - GDK_OVERLAP_RECTANGLE_PART : GDK_OVERLAP_RECTANGLE_IN) : - GDK_OVERLAP_RECTANGLE_OUT); -} diff --git a/gdk/nanox/gdkregion-generic.h b/gdk/nanox/gdkregion-generic.h deleted file mode 100644 index 659d44eb4c..0000000000 --- a/gdk/nanox/gdkregion-generic.h +++ /dev/null @@ -1,167 +0,0 @@ -/* $TOG: region.h /main/9 1998/02/06 17:50:30 kaleb $ */ -/************************************************************************ - -Copyright 1987, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -#ifndef __GDK_REGION_GENERIC_H__ -#define __GDK_REGION_GENERIC_H__ - -typedef struct _GdkRegionBox GdkRegionBox; - -struct _GdkRegionBox -{ - int x1, x2, y1, y2; -}; - -/* - * clip region - */ - -struct _GdkRegion -{ - long size; - long numRects; - GdkRegionBox *rects; - GdkRegionBox extents; -}; - -/* 1 if two BOXs overlap. - * 0 if two BOXs do not overlap. - * Remember, x2 and y2 are not in the region - */ -#define EXTENTCHECK(r1, r2) \ - ((r1)->x2 > (r2)->x1 && \ - (r1)->x1 < (r2)->x2 && \ - (r1)->y2 > (r2)->y1 && \ - (r1)->y1 < (r2)->y2) - -/* - * update region extents - */ -#define EXTENTS(r,idRect){\ - if((r)->x1 < (idRect)->extents.x1)\ - (idRect)->extents.x1 = (r)->x1;\ - if((r)->y1 < (idRect)->extents.y1)\ - (idRect)->extents.y1 = (r)->y1;\ - if((r)->x2 > (idRect)->extents.x2)\ - (idRect)->extents.x2 = (r)->x2;\ - if((r)->y2 > (idRect)->extents.y2)\ - (idRect)->extents.y2 = (r)->y2;\ - } - -/* - * Check to see if there is enough memory in the present region. - */ -#define MEMCHECK(reg, rect, firstrect){ \ - if ((reg)->numRects >= ((reg)->size - 1)) { \ - (firstrect) = g_renew (GdkRegionBox, (firstrect), 2 * (reg)->size); \ - (reg)->size *= 2; \ - (rect) = &(firstrect)[(reg)->numRects]; \ - } \ - } - -/* this routine checks to see if the previous rectangle is the same - * or subsumes the new rectangle to add. - */ - -#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ - (!(((Reg)->numRects > 0)&&\ - ((R-1)->y1 == (Ry1)) &&\ - ((R-1)->y2 == (Ry2)) &&\ - ((R-1)->x1 <= (Rx1)) &&\ - ((R-1)->x2 >= (Rx2)))) - -/* add a rectangle to the given Region */ -#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ - if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ - CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ - (r)->x1 = (rx1);\ - (r)->y1 = (ry1);\ - (r)->x2 = (rx2);\ - (r)->y2 = (ry2);\ - EXTENTS((r), (reg));\ - (reg)->numRects++;\ - (r)++;\ - }\ - } - - - -/* add a rectangle to the given Region */ -#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ - if ((rx1 < rx2) && (ry1 < ry2) &&\ - CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ - (r)->x1 = (rx1);\ - (r)->y1 = (ry1);\ - (r)->x2 = (rx2);\ - (r)->y2 = (ry2);\ - (reg)->numRects++;\ - (r)++;\ - }\ - } - -#define EMPTY_REGION(pReg) pReg->numRects = 0 - -#define REGION_NOT_EMPTY(pReg) pReg->numRects - -#define INBOX(r, x, y) \ - ( ( ((r).x2 > x)) && \ - ( ((r).x1 <= x)) && \ - ( ((r).y2 > y)) && \ - ( ((r).y1 <= y)) ) - -/* - * number of points to buffer before sending them off - * to scanlines() : Must be an even number - */ -#define NUMPTSTOBUFFER 200 - -/* - * used to allocate buffers for points and link - * the buffers together - */ -typedef struct _POINTBLOCK { - GdkPoint pts[NUMPTSTOBUFFER]; - struct _POINTBLOCK *next; -} POINTBLOCK; - -#endif /* __GDK_REGION_GENERIC_H__ */ diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am index 2cd04c1dd3..1e8e1ad103 100644 --- a/gdk/x11/Makefile.am +++ b/gdk/x11/Makefile.am @@ -22,6 +22,7 @@ LDADDS = @STRIP_BEGIN@ \ -lm \ @STRIP_END@ +if USE_X11 noinst_LTLIBRARIES = libgdk-x11.la if XINPUT_GXI @@ -58,10 +59,6 @@ libgdk_x11_la_SOURCES = \ gdkpango-x11.c \ gdkpixmap-x11.c \ gdkproperty-x11.c \ - gdkpoly-generic.h \ - gdkpolyreg-generic.c \ - gdkregion-generic.h \ - gdkregion-generic.c \ gdkselection-x11.c \ gdkvisual-x11.c \ gdkwindow-x11.c \ @@ -83,6 +80,8 @@ bin_PROGRAMS = @xinput_progs@ gxid_SOURCES = gxid.c gxid_LDADD = $(LDADDS) +endif + install-data-local: ../../$(MKINSTALLDIRS) $(includedir)/gdk $(INSTALL_DATA) $(srcdir)/gdkx.h $(includedir)/gdk diff --git a/gtk-config.in b/gtk-config.in index 6b226edd20..ad8cc1434d 100644 --- a/gtk-config.in +++ b/gtk-config.in @@ -5,6 +5,7 @@ glib_cflags="@glib_cflags@" glib_thread_libs="@glib_thread_libs@" glib_thread_cflags="@glib_thread_cflags@" +target=@gdktarget@ prefix=@prefix@ exec_prefix=@exec_prefix@ exec_prefix_set=no @@ -16,6 +17,7 @@ Usage: gtk-config [OPTIONS] [LIBRARIES] Options: [--prefix[=DIR]] [--exec-prefix[=DIR]] + [--target=gdktarget] [--version] [--libs] [--cflags] @@ -52,6 +54,9 @@ while test $# -gt 0; do exec_prefix=$optarg exec_prefix_set=yes ;; + --target=*) + target=$optarg + ;; --exec-prefix) echo_exec_prefix=yes ;; @@ -99,7 +104,7 @@ if test "$echo_cflags" = "yes"; then fi done fi - echo -I@libdir@/gtk+/include $includes $glib_cflags @PANGO_CFLAGS@ @x_cflags@ + echo -I@libdir@/gtk+/include $includes $glib_cflags @PANGO_CFLAGS@ @more_cflags@ fi if test "$echo_libs" = "yes"; then @@ -115,6 +120,6 @@ if test "$echo_libs" = "yes"; then fi done - echo $libdirs @x_ldflags@ -lgtk -lgdk $my_glib_libs @INTLLIBS@ @PANGO_LIBS@ @x_libs@ @GDK_WLIBS@ @MATH_LIB@ + echo $libdirs @more_ldflags@ -lgtk-$target -lgdk-$target $my_glib_libs @INTLLIBS@ @PANGO_LIBS@ @more_libs@ @GDK_WLIBS@ @MATH_LIB@ fi diff --git a/gtk/Makefile.am b/gtk/Makefile.am index d265d1d0b0..44c3d56502 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -15,25 +15,24 @@ INCLUDES = @STRIP_BEGIN@ \ @GTK_LOCALE_FLAGS@ \ @PANGO_CFLAGS@ \ @GLIB_CFLAGS@ \ - @x_cflags@ \ + @more_cflags@ \ @STRIP_END@ - -# -# libraries to compile and install -# -lib_LTLIBRARIES = libgtk.la +gtarget=@gdktarget@ # libtool stuff: set version and export symbols for resolving +# since automake doesn't support conditionalized libsomething_la_LDFLAGS +# we use the general approach here libgtkincludedir = $(includedir)/gtk -libgtk_la_LDFLAGS = @STRIP_BEGIN@ \ +LDFLAGS = @STRIP_BEGIN@ \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -release $(LT_RELEASE) \ -export-dynamic \ + -rpath @prefix@/lib @PANGO_LIBS@ \ @GLIB_DEPLIBS@ \ - @x_ldflags@ \ - @x_libs@ \ + @more_ldflags@ \ + @more_libs@ \ -lm \ @STRIP_END@ # $(top_builddir)/gdk/libgdk.la @@ -382,8 +381,33 @@ gdk_headers = @STRIP_BEGIN@ \ # # setup GTK+ sources and their dependancies # -libgtkinclude_HEADERS = $(gtk_public_h_sources) $(gtk_semipublic_h_sources) $(gtk_built_public_sources) -libgtk_la_SOURCES = $(gtk_c_sources) +all_headers = $(gtk_public_h_sources) $(gtk_semipublic_h_sources) $(gtk_built_public_sources) +all_sources = $(gtk_c_sources) + +extra = @gtktargetlib@ +if USE_X11 +libgtk_x11_includedir = $(includedir)/gtk +libgtk_x11_include_HEADERS = $(all_headers) +libgtk_x11_la_SOURCES = $(all_sources) +endif + +if USE_NANOX +libgtk_nanox_includedir = $(includedir)/gtk +libgtk_nanox_include_HEADERS = $(all_headers) +libgtk_nanox_la_SOURCES = $(all_sources) +endif + +if USE_LINUX_FB +libgtk_linux_fb_includedir = $(includedir)/gtk +libgtk_linux_fb_include_HEADERS = $(all_headers) +libgtk_linux_fb_la_SOURCES = $(all_sources) +endif + +# now define the real one to workaround automake's mishandling +lib_LTLIBRARIES = $(extra) + +EXTRA_LTLIBRARIES = libgtk-x11.la libgtk-nanox.la libgtk-linux-fb.la + MAINTAINERCLEANFILES += $(gtk_built_public_sources) $(gtk_built_sources) EXTRA_HEADERS += EXTRA_DIST += $(gtk_private_h_sources) |