diff options
author | Havoc Pennington <hp@redhat.com> | 2000-10-09 17:22:20 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-10-09 17:22:20 +0000 |
commit | 518f32d97e0e097c10a99d65da8e0e215c796c3a (patch) | |
tree | 3bdd86d81f59adff2ac1c3dff7bc19672ea9e23f | |
parent | 25840ef4a566630948e838ec69bccd392befca9e (diff) | |
download | gdk-pixbuf-518f32d97e0e097c10a99d65da8e0e215c796c3a.tar.gz |
contrib subdir
2000-10-06 Havoc Pennington <hp@redhat.com>
* Makefile.am (SRC_SUBDIRS): contrib subdir
* gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library,
so it can be used in Xlib version
* demos/testpixbuf.c (update_timeout): error checking from 1.0
tree
* gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync
change from 1.0 tree that returns first frame of animation
if the loaded file is an animation.
* contrib: add new directory to hold stuff that comes with GTK+
but isn't really part of GTK+ (for now, gdk-pixbuf-xlib)
* configure.in: add contrib/*
2000-10-06 Havoc Pennington <hp@redhat.com>
* gdk-pixbuf.h: add GdkPixbufAlphaMode
2000-10-06 Havoc Pennington <hp@redhat.com>
This entry is a summary of the merged-in changes from 1.0.
Relevant original ChangeLog entries are spliced in after
this entry; the files they refer to are from the 1.0
gdk-pixbuf sources.
* pixops/pixops.c (pixops_composite_nearest): sync a small fix
from 1.0
* io-xpm.c (xpm_seek_string): add fscanf error check from 1.0
Add progressive loader from 1.0
* io-tiff.c (gdk_pixbuf__tiff_image_begin_load): mem leak fixes
from 1.0 tree
* io-pnm.c: new version from 1.0 tree
* io-jpeg.c (gdk_pixbuf__jpeg_image_load): sync from 1.0, use
malloc not g_malloc
* io-gif.c (lzw_read_byte): sync from 1.0, change a g_error to
g_warning
(gif_get_next_step): return 0 here, sync from 1.0
* gdk-pixbuf-util.c: sync email address change for Cody
Russell
2000-09-11 Jeffrey Stedfast <fejj@helixcode.com>
* gdk-pixbuf/io-pnm.c: Pretty much totally rewrote again because
last nights code was still "broken". Should now properly handle
all error conditions gracefully.
2000-09-10 Jeffrey Stedfast <fejj@helixcode.com>
* gdk-pixbuf/io-pnm.c: Rewrote.
2000-09-09 Federico Mena Quintero <federico@helixcode.com>
* gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): Compute
the correct dest offset.
2000-08-25 Federico Mena Quintero <federico@helixcode.com>
* gdk-pixbuf/io-xpm.c: #include <unistd.h>
2000-08-05 Larry Ewing <lewing@helixcode.com>
* gdk-pixbuf/io-tiff.c: stop leaking context->tempname.
* gdk-pixbuf/io-xpm.c: same as above.
2000-07-26 Michael Meeks <michael@helixcode.com>
* gdk-pixbuf/io-jpeg.c (gdk_pixbuf__jpeg_image_load): make
g_malloc a malloc.
2000-07-21 Larry Ewing <lewing@helixcode.com>
* gdk-pixbuf/io-xpm.c: add a fake progressive loader so that
xpm at least supports the progressive interface like the one in
io-tiff.c. This should be reimplemented as an actual progressive
loader.
2000-07-19 Jonathan Blandford <jrb@redhat.com>
* demo/pixbuf-demo.c (update_timeout): changed scaling level to
make it look better.
* gdk-pixbuf/testpixbuf.c (update_timeout): Patch from michael
meeks to handle errors better.
52 files changed, 8204 insertions, 571 deletions
@@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index e2562f508..6caace120 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,22 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * Makefile.am (SRC_SUBDIRS): contrib subdir + + * gdk/gdkpixbuf.h: Move GdkPixbufAlphaMode to gdk-pixbuf library, + so it can be used in Xlib version + + * demos/testpixbuf.c (update_timeout): error checking from 1.0 + tree + + * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_pixbuf): Sync + change from 1.0 tree that returns first frame of animation + if the loaded file is an animation. + + * contrib: add new directory to hold stuff that comes with GTK+ + but isn't really part of GTK+ (for now, gdk-pixbuf-xlib) + + * configure.in: add contrib/* + 2000-10-05 Havoc Pennington <hp@redhat.com> * demos/testpixbuf-save.c: add pixbuf save test diff --git a/Makefile.am b/Makefile.am index eb9a24f29..42577a920 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## Makefile.am for GTK+ -SRC_SUBDIRS = gdk-pixbuf gdk modules gtk demos +SRC_SUBDIRS = gdk-pixbuf gdk modules gtk demos contrib SUBDIRS = po $(SRC_SUBDIRS) docs build bin_SCRIPTS = gtk-config-2.0 diff --git a/configure.in b/configure.in index 7a30ef012..c5f81d32b 100644 --- a/configure.in +++ b/configure.in @@ -825,6 +825,14 @@ AC_SUBST(GDK_PIXBUF_LIBDIR) AC_SUBST(GDK_PIXBUF_INCLUDEDIR) AC_SUBST(GDK_PIXBUF_LIBS) +GDK_PIXBUF_XLIB_LIBDIR=$GDK_PIXBUF_LIBDIR +GDK_PIXBUF_XLIB_INCLUDEDIR=$GDK_PIXBUF_INCLUDEDIR +GDK_PIXBUF_XLIB_LIBS="$GLIB_LIBS -lgdk_pixbuf_xlib $deps $X11_LIBS" + +AC_SUBST(GDK_PIXBUF_XLIB_LIBDIR) +AC_SUBST(GDK_PIXBUF_XLIB_INCLUDEDIR) +AC_SUBST(GDK_PIXBUF_XLIB_LIBS) + # Checks to see if we should compile in MMX support (there will be # a runtime test when the code is actually run to see if it should # be used - this just checks if we can compile it.) @@ -1037,4 +1045,7 @@ gtk/gtkcompat.h gtk/stock-icons/Makefile modules/Makefile modules/linux-fb/Makefile +contrib/Makefile +contrib/gdk-pixbuf-xlib/Makefile +contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-2.0.pc ], [chmod +x gtk-config-2.0]) diff --git a/contrib/gdk-pixbuf-xlib/ChangeLog b/contrib/gdk-pixbuf-xlib/ChangeLog new file mode 100644 index 000000000..14bec6217 --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/ChangeLog @@ -0,0 +1,53 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * gdk-pixbuf-xlib.c: Put display/screen here, instead of in + the main gdk-pixbuf library as it was in 1.0; since the io-xpm + loader doesn't use these variables anymore it should be OK + +2000-09-26 Federico Mena Quintero <federico@helixcode.com> + + * gdk-pixbuf/gdk-pixbuf-xlib-drawable.c + (gdk_pixbuf_xlib_get_from_drawable): Do not use + gdk_screen_{width,height}(). Thanks to John Harper for pointing + this out. + +2000-08-26 Federico Mena Quintero <federico@helixcode.com> + + * gdk-pixbuf/gdk-pixbuf-xlibrgb.c: Added API reference docs. + +2000-08-25 Federico Mena Quintero <federico@helixcode.com> + + * gdk-pixbuf/gdk-pixbuf-xlib-drawable.c (handle_x_error): Return + 0. + (xlib_window_is_viewable): Return FALSE in the last case. + + * gdk-pixbuf/gdk-pixbuf-xlib-render.c: Updated the inline docs. + + * gdk-pixbuf/gdk-pixbuf-xlib.c: Added API docs. + +2000-08-25 John Harper <john@dcs.warwick.ac.uk> + + Work to create an Xlib version of gdk-pixbuf (with the Xlib + port of GdkRGB for rendering): + + * configure.in: check for X libraries, set and substitute + GDK_PIXBUF_XLIB_{LIBDIR,INCLUDEDIR,LIBS} variables + + * gdk_pixbuf_xlibConf.sh.in: new file -- gnome-config details + for the gdk-pixbuf-xlib library + * Makefile.am: build and install gdk_pixbuf_xlibConf.sh + + * gdk-pixbuf/gdk-pixbuf-xlib-render.c, + gdk-pixbuf/gdk-pixbuf-xlib.c, gdk-pixbuf/gdk-pixbuf-xlib.h, + gdk-pixbuf/gdk-pixbuf-xlib-private.h, + gdk-pixbuf/gdk-pixbuf-xlib-drawable.c: new files, ported the + GDK dependent parts of gdk-pixbuf to use Xlib. Functions that + were called gdk_pixbuf_FOO are now gdk_pixbuf_xlib_FOO + + * gdk-pixbuf/gdk-pixbuf-xlibrgb.c, + gdk-pixbuf/gdk-pixbuf-xlibrgb.h: added Chris Blizzard's Xlib + port of GdkRGB (from Mozilla CVS) + + * gdk-pixbuf/Makefile.am: build a library libgdk_pixbuf_xlib.la + including the non-GDK dependent objects from libgdk_pixbuf.la + plus the Xlib ports and xlibrgb diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-2.0.pc.in b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-2.0.pc.in new file mode 100644 index 000000000..197c03c6e --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-2.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: GdkPixbufXlib +Description: Image loading and scaling for Xlib +Version: @VERSION@ +Requires: gobject-2.0,gmodule-2.0,gdk-pixbuf-2.0 +Libs: -L${libdir} -lgdk_pixbuf_xlib-1.3 +Cflags: -I${includedir} diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-drawable.c b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-drawable.c new file mode 100644 index 000000000..9e007bdb4 --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-drawable.c @@ -0,0 +1,1335 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* GdkPixbuf library - convert X drawable information to RGB + * + * Copyright (C) 1999 Michael Zucchi + * + * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au> + * Cody Russell <bratsche@dfw.net> + * Federico Mena-Quintero <federico@gimp.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */ + + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <gdk-pixbuf/gdk-pixbuf-private.h> +#include "gdk-pixbuf-xlib-private.h" +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +#define LITTLE +#endif +#define d(x) + + + +static guint32 mask_table[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + + +/* color handling */ + +typedef struct xlib_colormap_struct xlib_colormap; +struct xlib_colormap_struct { + int size; + XColor *colors; + Visual *visual; + Colormap colormap; +}; + +static xlib_colormap * +xlib_get_colormap (Colormap id, Visual *visual) +{ + int i; + xlib_colormap *xc = g_new (xlib_colormap, 1); + + xc->size = visual->map_entries; + xc->colors = g_new (XColor, xc->size); + xc->visual = visual; + xc->colormap = id; + + for (i = 0; i < xc->size; i++) { + xc->colors[i].pixel = i; + xc->colors[i].flags = DoRed | DoGreen | DoBlue; + } + + XQueryColors (gdk_pixbuf_dpy, xc->colormap, xc->colors, xc->size); + + return xc; +} + +static void +xlib_colormap_free (xlib_colormap *xc) +{ + g_free (xc->colors); + g_free (xc); +} + +/* from gdkvisual.c */ +static void +visual_decompose_mask (gulong mask, + gint *shift, + gint *prec) +{ + *shift = 0; + *prec = 0; + + while (!(mask & 0x1)) { + (*shift)++; + mask >>= 1; + } + + while (mask & 0x1) { + (*prec)++; + mask >>= 1; + } +} + +static gboolean x_error; + +static int +handle_x_error (Display *dpy, XErrorEvent *ev) +{ + x_error = TRUE; + return 0; +} + +static gboolean +drawable_is_pixmap (Drawable d) +{ + /* copied from Imlib */ + + XErrorHandler errh; + XWindowAttributes wa; + gboolean is_pixmap; + + errh = XSetErrorHandler (handle_x_error); + x_error = FALSE; + XGetWindowAttributes (gdk_pixbuf_dpy, d, &wa); + XSync (gdk_pixbuf_dpy, False); + is_pixmap = x_error; + XSetErrorHandler (errh); + + return is_pixmap; +} + + + +/* + convert 1 bits-pixel data + no alpha +*/ +static void +rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *s; + register guint8 data; + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + + d (printf ("1 bits/pixel\n")); + + /* convert upto 8 pixels/time */ + /* its probably not worth trying to make this run very fast, who uses + 1 bit displays anymore? */ + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + + for (xx = 0; xx < width; xx ++) { + data = srow[xx >> 3] >> (7 - (xx & 7)) & 1; + *o++ = colormap->colors[data].red; + *o++ = colormap->colors[data].green; + *o++ = colormap->colors[data].blue; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 1 bits/pixel data + with alpha +*/ +static void +rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *s; + register guint8 data; + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + guint32 remap[2]; + + d (printf ("1 bits/pixel\n")); + + /* convert upto 8 pixels/time */ + /* its probably not worth trying to make this run very fast, who uses + 1 bit displays anymore? */ + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (xx = 0; xx < 2; xx++) { +#ifdef LITTLE + remap[xx] = 0xff000000 + | colormap->colors[xx].blue << 16 + | colormap->colors[xx].green << 8 + | colormap->colors[xx].red; +#else + remap[xx] = 0xff + | colormap->colors[xx].red << 24 + | colormap->colors[xx].green << 16 + | colormap->colors[xx].blue << 8; +#endif + } + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + + for (xx = 0; xx < width; xx ++) { + data = srow[xx >> 3] >> (7 - (xx & 7)) & 1; + *o++ = remap[data]; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 8 bits/pixel data + no alpha +*/ +static void +rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint32 mask; + register guint32 data; + guint8 *srow = image->data, *orow = pixels; + register guint8 *s; + register guint8 *o; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + d (printf ("8 bit, no alpha output\n")); + + mask = mask_table[image->depth]; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + data = *s++ & mask; + *o++ = colormap->colors[data].red; + *o++ = colormap->colors[data].green; + *o++ = colormap->colors[data].blue; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 8 bits/pixel data + with alpha +*/ +static void +rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint32 mask; + register guint32 data; + guint32 remap[256]; + register guint8 *s; /* read 2 pixels at once */ + register guint32 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + d (printf ("8 bit, with alpha output\n")); + + mask = mask_table[image->depth]; + + for (xx = 0; xx < colormap->size; xx++) { +#ifdef LITTLE + remap[xx] = 0xff000000 + | colormap->colors[xx].blue << 16 + | colormap->colors[xx].green << 8 + | colormap->colors[xx].red; +#else + remap[xx] = 0xff + | colormap->colors[xx].red << 24 + | colormap->colors[xx].green << 16 + | colormap->colors[xx].blue << 8; +#endif + } + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + data = *s++ & mask; + *o++ = remap[data]; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + no alpha + data in lsb format +*/ +static void +rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint32 *s; /* read 2 pixels at once */ +#else + register guint8 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; +#else + s = srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + data = *s++; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21; + *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0xf800) | (data & 0xe000) >> 5 + | (data & 0x7e0) >> 3 | (data & 0x600) >> 9; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29; + *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); +#else + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#endif + ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7); + ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3); + ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7); + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + no alpha + data in msb format +*/ +static void +rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; /* need to swap data order */ +#else + register guint32 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = srow; +#else + s = (guint32 *) srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21; + *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + data = *s++; + *o++ = (data & 0xf800) | (data & 0xe000) >> 5 + | (data & 0x7e0) >> 3 | (data & 0x600) >> 9; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29; + *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#else + data = *((short *) s); +#endif + ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7); + ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3); + ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7); + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + with alpha + data in lsb format +*/ +static void +rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = (guint8 *) srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */ +#ifdef LITTLE + data = *s++; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11 + | (data & 0x7e0) << 13 | (data & 0x600) << 7 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + with alpha + data in msb format +*/ +static void +rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; +#else + register guint16 *s; /* read 1 pixels at once */ +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */ +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + data = *s++; + *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11 + | (data & 0x7e0) << 13 | (data & 0x600) << 7 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + no alpha + data in lsb format +*/ +static void +rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint32 *s; /* read 2 pixels at once */ +#else + register guint8 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; +#else + s = srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + data = *s++; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20; + *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4 + | (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28; + *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); +#else + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#endif + ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12; + ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + no alpha + data in msb format +*/ +static void +rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; /* read 2 pixels at once */ +#else + register guint32 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20; + *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + data = *s++; + *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4 + | (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28; + *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#else + data = *((short *) s); +#endif + ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12; + ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + with alpha + data in lsb format +*/ +static void +rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */ +#ifdef LITTLE + data = *s++; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12 + | (data & 0x3e0) << 14 | (data & 0x380) << 9 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + with alpha + data in msb format +*/ +static void +rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */ +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + data = *s++; + *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12 + | (data & 0x3e0) << 14 | (data & 0x380) << 9 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + + +static void +rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *s; /* for byte order swapping */ + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + d (printf ("32 bits/pixel with alpha\n")); + + /* lsb data */ + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[2]; + *o++ = s[1]; + *o++ = s[0]; + *o++ = 0xff; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; + guint8 *o, *s; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + d (printf ("32 bit, lsb, no alpha\n")); + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[2]; + *o++ = s[1]; + *o++ = s[0]; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; +#ifdef LITTLE + guint32 *o; + guint32 *s; +#else + guint8 *s; /* for byte order swapping */ + guint8 *o; +#endif + + d (printf ("32 bit, msb, with alpha\n")); + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + /* msb data */ + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; + o = (guint32 *) orow; +#else + s = srow; + o = orow; +#endif + for (xx = 0; xx < width; xx++) { +#ifdef LITTLE + *o++ = s[1]; + *o++ = s[2]; + *o++ = s[3]; + *o++ = 0xff; + s += 4; +#else + *o++ = (*s << 8) | 0xff; /* untested */ + s++; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; + guint8 *s; + guint8 *o; + + d (printf ("32 bit, msb, no alpha\n")); + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[1]; + *o++ = s[2]; + *o++ = s[3]; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} + +/* + This should work correctly with any display/any endianness, but will probably + run quite slow +*/ +static void +convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *srow = image->data, *orow = pixels; + guint8 *s; + guint8 *o; + guint32 pixel; + Visual *v; + guint8 component; + int i; + int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + v = cmap->visual; + + visual_decompose_mask (v->red_mask, &red_shift, &red_prec); + visual_decompose_mask (v->green_mask, &green_shift, &green_prec); + visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec); + + d(printf("rgb mask/shift/prec = %x:%x:%x %d:%d:%d %d:%d:%d\n", + v->red_mask, v->green_mask, v->blue_mask, + red_shift, green_shift, blue_shift, + red_prec, green_prec, blue_prec)); + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + pixel = XGetPixel (image, xx, yy); + switch (v->class) { + /* I assume this is right for static & greyscale's too? */ + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + *o++ = cmap->colors[pixel].red; + *o++ = cmap->colors[pixel].green; + *o++ = cmap->colors[pixel].blue; + break; + case TrueColor: + /* This is odd because it must sometimes shift left (otherwise + I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic + should work for all bit sizes/shifts/etc. */ + component = 0; + for (i = 24; i < 32; i += red_prec) + component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i; + *o++ = component; + component = 0; + for (i = 24; i < 32; i += green_prec) + component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i; + *o++ = component; + component = 0; + for (i = 24; i < 32; i += blue_prec) + component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i; + *o++ = component; + break; + case DirectColor: + *o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red; + *o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green; + *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue; + break; + } + if (alpha) + *o++ = 0xff; + } + srow += bpl; + orow += rowstride; + } +} + +typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap); + +static cfunc convert_map[] = { + rgb1,rgb1,rgb1a,rgb1a, + rgb8,rgb8,rgb8a,rgb8a, + rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb, + rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb, + rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb +}; + +/* + perform actual conversion + + If we can, try and use the optimised code versions, but as a default + fallback, and always for direct colour, use the generic/slow but complete + conversion function. +*/ +static void +rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap) +{ + int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1; + int bank=5; /* default fallback converter */ + Visual *v = cmap->visual; + + d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask)); + d(printf("image depth = %d, bpp = %d\n", image->depth, image->bits_per_pixel)); + + switch (v->class) { + /* I assume this is right for static & greyscale's too? */ + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + switch (image->bits_per_pixel) { + case 1: + bank = 0; + break; + case 8: + bank = 1; + break; + } + break; + case TrueColor: + switch (image->depth) { + case 15: + if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f + && image->bits_per_pixel == 16) + bank = 2; + break; + case 16: + if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f + && image->bits_per_pixel == 16) + bank = 3; + break; + case 24: + case 32: + if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff + && image->bits_per_pixel == 32) + bank = 4; + break; + } + break; + case DirectColor: + /* always use the slow version */ + break; + } + + d(printf("converting using conversion function in bank %d\n", bank)); + + if (bank==5) { + convert_real_slow(image, pixels, rowstride, cmap, alpha); + } else { + index |= bank << 2; + (* convert_map[index]) (image, pixels, rowstride, cmap); + } +} + +static gboolean +xlib_window_is_viewable (Window w) +{ + XWindowAttributes wa; + + while (w != 0) { + Window parent, root, *children; + int nchildren; + + XGetWindowAttributes (gdk_pixbuf_dpy, w, &wa); + if (wa.map_state != IsViewable) + return FALSE; + + if (!XQueryTree (gdk_pixbuf_dpy, w, &root, + &parent, &children, &nchildren)) + return FALSE; + + if (nchildren > 0) + XFree (children); + + if (parent == root) + return TRUE; + + w = parent; + } + + return FALSE; +} + +static gint +xlib_window_get_origin (Window w, gint *x, gint *y) +{ + Window child; + return XTranslateCoordinates (gdk_pixbuf_dpy, w, + RootWindow (gdk_pixbuf_dpy, + gdk_pixbuf_screen), + 0, 0, x, y, &child); +} + +/* Exported functions */ + +/** + * gdk_pixbuf_xlib_get_from_drawable: + * @dest: Destination pixbuf, or NULL if a new pixbuf should be created. + * @src: Source drawable. + * @cmap: A colormap if @src is a pixmap. If it is a window, this argument will + * be ignored. + * @visual: A visual if @src is a pixmap. If it is a window, this argument will + * be ignored. + * @src_x: Source X coordinate within drawable. + * @src_y: Source Y coordinate within drawable. + * @dest_x: Destination X coordinate in pixbuf, or 0 if @dest is NULL. + * @dest_y: Destination Y coordinate in pixbuf, or 0 if @dest is NULL. + * @width: Width in pixels of region to get. + * @height: Height in pixels of region to get. + * + * Transfers image data from a Gdk drawable and converts it to an RGB(A) + * representation inside a GdkPixbuf. + * + * If the drawable @src is a pixmap, then a suitable colormap must be specified, + * since pixmaps are just blocks of pixel data without an associated colormap. + * If the drawable is a window, the @cmap argument will be ignored and the + * window's own colormap will be used instead. + * + * If the specified destination pixbuf @dest is #NULL, then this function will + * create an RGB pixbuf with 8 bits per channel and no alpha, with the same size + * specified by the @width and @height arguments. In this case, the @dest_x and + * @dest_y arguments must be specified as 0, otherwise the function will return + * #NULL. If the specified destination pixbuf is not NULL and it contains alpha + * information, then the filled pixels will be set to full opacity. + * + * If the specified drawable is a pixmap, then the requested source rectangle + * must be completely contained within the pixmap, otherwise the function will + * return #NULL. + * + * If the specified drawable is a window, then it must be viewable, i.e. all of + * its ancestors up to the root window must be mapped. Also, the specified + * source rectangle must be completely contained within the window and within + * the screen. If regions of the window are obscured by noninferior windows, the + * contents of those regions are undefined. The contents of regions obscured by + * inferior windows of a different depth than that of the source window will also + * be undefined. + * + * Return value: The same pixbuf as @dest if it was non-NULL, or a newly-created + * pixbuf with a reference count of 1 if no destination pixbuf was specified; in + * the latter case, NULL will be returned if not enough memory could be + * allocated for the pixbuf to be created. + **/ +GdkPixbuf * +gdk_pixbuf_xlib_get_from_drawable (GdkPixbuf *dest, + Drawable src, + Colormap cmap, Visual *visual, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height) +{ + int src_width, src_height; + XImage *image; + int rowstride, bpp, alpha; + XWindowAttributes wa; + xlib_colormap *x_cmap; + gboolean is_pixmap; + + /* General sanity checks */ + + g_return_val_if_fail (src != 0, NULL); + + is_pixmap = drawable_is_pixmap (src); + + if (is_pixmap) { + g_return_val_if_fail (cmap != 0, NULL); + g_return_val_if_fail (visual != NULL, NULL); + } + else + g_return_val_if_fail (xlib_window_is_viewable (src), NULL); + + if (!dest) + g_return_val_if_fail (dest_x == 0 && dest_y == 0, NULL); + else { + g_return_val_if_fail (dest->colorspace == GDK_COLORSPACE_RGB, NULL); + g_return_val_if_fail (dest->n_channels == 3 + || dest->n_channels == 4, NULL); + g_return_val_if_fail (dest->bits_per_sample == 8, NULL); + } + + /* Coordinate sanity checks */ + + if (!is_pixmap) { + XGetWindowAttributes (gdk_pixbuf_dpy, src, &wa); + src_width = wa.width; + src_height = wa.height; + } else { + Window root; + int tx, ty, bwidth, depth; + XGetGeometry (gdk_pixbuf_dpy, src, &root, &tx, &ty, + &src_width, &src_height, &bwidth, &depth); + } + + g_return_val_if_fail (src_x >= 0 && src_y >= 0, NULL); + g_return_val_if_fail (src_x + width <= src_width + && src_y + height <= src_height, NULL); + + if (dest) { + g_return_val_if_fail (dest_x >= 0 && dest_y >= 0, NULL); + g_return_val_if_fail (dest_x + width <= dest->width, NULL); + g_return_val_if_fail (dest_y + height <= dest->height, NULL); + } + + if (!is_pixmap) { + int ret; + int src_xorigin, src_yorigin; + int screen_width, screen_height; + int screen_srcx, screen_srcy; + + ret = xlib_window_get_origin (src, &src_xorigin, &src_yorigin); + g_return_val_if_fail (ret != FALSE, NULL); + + screen_width = DisplayWidth (gdk_pixbuf_dpy, gdk_pixbuf_screen); + screen_height = DisplayHeight (gdk_pixbuf_dpy, gdk_pixbuf_screen); + + screen_srcx = src_xorigin + src_x; + screen_srcy = src_yorigin + src_y; + + g_return_val_if_fail (screen_srcx >= 0 && screen_srcy >= 0, NULL); + g_return_val_if_fail (screen_srcx + width <= screen_width, NULL); + g_return_val_if_fail (screen_srcy + height <= screen_height, NULL); + } + + /* Get Image in ZPixmap format (packed bits). */ + image = XGetImage (gdk_pixbuf_dpy, src, src_x, src_y, + width, height, AllPlanes, ZPixmap); + g_return_val_if_fail (image != NULL, NULL); + + /* Create the pixbuf if needed */ + if (!dest) { + dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, 8, width, height); + if (!dest) { + XDestroyImage (image); + return NULL; + } + } + + /* Get the colormap if needed */ + if (!is_pixmap) + { + cmap = wa.colormap; + visual = wa.visual; + } + + x_cmap = xlib_get_colormap (cmap, visual); + + alpha = dest->has_alpha; + rowstride = dest->rowstride; + bpp = alpha ? 4 : 3; + + /* we offset into the image data based on the position we are retrieving from */ + rgbconvert (image, dest->pixels + + (dest_y * rowstride) + (dest_x * bpp), + rowstride, + alpha, + x_cmap); + + xlib_colormap_free (x_cmap); + XDestroyImage (image); + + return dest; +} diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-private.h b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-private.h new file mode 100644 index 000000000..6605be538 --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-private.h @@ -0,0 +1,30 @@ +/* GdkPixbuf library - Xlib header file + * + * Authors: John Harper <john@dcs.warwick.ac.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GDK_PIXBUF_XLIB_PRIVATE_H +#define GDK_PIXBUF_XLIB_PRIVATE_H + +#include "gdk-pixbuf-xlib.h" +#include <X11/Xlib.h> + +extern Display *gdk_pixbuf_dpy; +extern int gdk_pixbuf_screen; + +#endif diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-render.c b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-render.c new file mode 100644 index 000000000..b6a26ebf3 --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib-render.c @@ -0,0 +1,398 @@ +/* GdkPixbuf library - Rendering functions + * + * Copyright (C) 1999 The Free Software Foundation + * + * Author: Federico Mena-Quintero <federico@gimp.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Trivially ported to Xlib(RGB) by John Harper. */ + +#include <config.h> +#include "gdk-pixbuf-private.h" +#include "gdk-pixbuf-xlib-private.h" + + + +/** + * gdk_pixbuf_xlib_render_threshold_alpha: + * @pixbuf: A pixbuf. + * @bitmap: Bitmap where the bilevel mask will be painted to. + * @src_x: Source X coordinate. + * @src_y: source Y coordinate. + * @dest_x: Destination X coordinate. + * @dest_y: Destination Y coordinate. + * @width: Width of region to threshold. + * @height: Height of region to threshold. + * @alpha_threshold: Opacity values below this will be painted as zero; all + * other values will be painted as one. + * + * Takes the opacity values in a rectangular portion of a pixbuf and thresholds + * them to produce a bi-level alpha mask that can be used as a clipping mask for + * a drawable. + * + **/ +void +gdk_pixbuf_xlib_render_threshold_alpha (GdkPixbuf *pixbuf, Pixmap bitmap, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int alpha_threshold) +{ + GC gc; + XColor color; + int x, y; + guchar *p; + int start, start_status; + int status; + XGCValues gcv; + + g_return_if_fail (pixbuf != NULL); + g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); + g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); + g_return_if_fail (pixbuf->bits_per_sample == 8); + + g_return_if_fail (bitmap != 0); + g_return_if_fail (width >= 0 && height >= 0); + g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width); + g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height); + + g_return_if_fail (alpha_threshold >= 0 && alpha_threshold <= 255); + + if (width == 0 || height == 0) + return; + + gc = XCreateGC (gdk_pixbuf_dpy, bitmap, 0, &gcv); + + if (!pixbuf->has_alpha) { + color.pixel = (alpha_threshold == 255) ? 0 : 1; + XSetForeground (gdk_pixbuf_dpy, gc, color.pixel); + XFillRectangle (gdk_pixbuf_dpy, bitmap, gc, + dest_x, dest_y, width, height); + XFreeGC (gdk_pixbuf_dpy, gc); + return; + } + + color.pixel = 0; + XSetForeground (gdk_pixbuf_dpy, gc, color.pixel); + XFillRectangle (gdk_pixbuf_dpy, bitmap, gc, + dest_x, dest_y, width, height); + + color.pixel = 1; + XSetForeground (gdk_pixbuf_dpy, gc, color.pixel); + + for (y = 0; y < height; y++) { + p = (pixbuf->pixels + (y + src_y) * pixbuf->rowstride + src_x * pixbuf->n_channels + + pixbuf->n_channels - 1); + + start = 0; + start_status = *p < alpha_threshold; + + for (x = 0; x < width; x++) { + status = *p < alpha_threshold; + + if (status != start_status) { + if (!start_status) + XDrawLine (gdk_pixbuf_dpy, bitmap, gc, + start + dest_x, y + dest_y, + x - 1 + dest_x, y + dest_y); + + start = x; + start_status = status; + } + + p += pixbuf->n_channels; + } + + if (!start_status) + XDrawLine (gdk_pixbuf_dpy, bitmap, gc, + start + dest_x, y + dest_y, + x - 1 + dest_x, y + dest_y); + } + + XFreeGC (gdk_pixbuf_dpy, gc); +} + + + +/* Creates a buffer by stripping the alpha channel of a pixbuf */ +static guchar * +remove_alpha (GdkPixbuf *pixbuf, int x, int y, int width, int height, int *rowstride) +{ + guchar *buf; + int xx, yy; + guchar *src, *dest; + + g_assert (pixbuf->n_channels == 4); + g_assert (pixbuf->has_alpha); + g_assert (width > 0 && height > 0); + g_assert (x >= 0 && x + width <= pixbuf->width); + g_assert (y >= 0 && y + height <= pixbuf->height); + + *rowstride = 4 * ((width * 3 + 3) / 4); + + buf = g_new (guchar, *rowstride * height); + + for (yy = 0; yy < height; yy++) { + src = pixbuf->pixels + pixbuf->rowstride * (yy + y) + x * pixbuf->n_channels; + dest = buf + *rowstride * yy; + + for (xx = 0; xx < width; xx++) { + *dest++ = *src++; + *dest++ = *src++; + *dest++ = *src++; + src++; + } + } + + return buf; +} + +/** + * gdk_pixbuf_xlib_render_to_drawable: + * @pixbuf: A pixbuf. + * @drawable: Destination drawable. + * @gc: GC used for rendering. + * @src_x: Source X coordinate within pixbuf. + * @src_y: Source Y coordinate within pixbuf. + * @dest_x: Destination X coordinate within drawable. + * @dest_y: Destination Y coordinate within drawable. + * @width: Width of region to render, in pixels. + * @height: Height of region to render, in pixels. + * @dither: Dithering mode for XlibRGB. + * @x_dither: X offset for dither. + * @y_dither: Y offset for dither. + * + * Renders a rectangular portion of a pixbuf to a drawable while using the + * specified GC. This is done using XlibRGB, so the specified drawable must + * have the XlibRGB visual and colormap. Note that this function will ignore + * the opacity information for images with an alpha channel; the GC must already + * have the clipping mask set if you want transparent regions to show through. + * + * For an explanation of dither offsets, see the XlibRGB documentation. In + * brief, the dither offset is important when re-rendering partial regions of an + * image to a rendered version of the full image, or for when the offsets to a + * base position change, as in scrolling. The dither matrix has to be shifted + * for consistent visual results. If you do not have any of these cases, the + * dither offsets can be both zero. + **/ +void +gdk_pixbuf_xlib_render_to_drawable (GdkPixbuf *pixbuf, + Drawable drawable, GC gc, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + XlibRgbDither dither, + int x_dither, int y_dither) +{ + guchar *buf; + int rowstride; + + g_return_if_fail (pixbuf != NULL); + g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); + g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); + g_return_if_fail (pixbuf->bits_per_sample == 8); + + g_return_if_fail (drawable != 0); + g_return_if_fail (gc != 0); + + g_return_if_fail (width >= 0 && height >= 0); + g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width); + g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height); + + if (width == 0 || height == 0) + return; + + /* This will have to be modified once we support other image types. + * Also, GdkRGB does not have gdk_draw_rgb_32_image_dithalign(), so we + * have to pack the buffer first. Sigh. + */ + + if (pixbuf->has_alpha) + buf = remove_alpha (pixbuf, src_x, src_y, width, height, &rowstride); + else { + buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3; + rowstride = pixbuf->rowstride; + } + + xlib_draw_rgb_image_dithalign (drawable, gc, + dest_x, dest_y, + width, height, + dither, + buf, rowstride, + x_dither, y_dither); + + if (pixbuf->has_alpha) + g_free (buf); +} + + + +/** + * gdk_pixbuf_xlib_render_to_drawable_alpha: + * @pixbuf: A pixbuf. + * @drawable: Destination drawable. + * @src_x: Source X coordinate within pixbuf. + * @src_y: Source Y coordinates within pixbuf. + * @dest_x: Destination X coordinate within drawable. + * @dest_y: Destination Y coordinate within drawable. + * @width: Width of region to render, in pixels. + * @height: Height of region to render, in pixels. + * @alpha_mode: If the image does not have opacity information, this is ignored. + * Otherwise, specifies how to handle transparency when rendering. + * @alpha_threshold: If the image does have opacity information and @alpha_mode + * is GDK_PIXBUF_ALPHA_BILEVEL, specifies the threshold value for opacity + * values. + * @dither: Dithering mode for XlibRGB. + * @x_dither: X offset for dither. + * @y_dither: Y offset for dither. + * + * Renders a rectangular portion of a pixbuf to a drawable. This is done using + * XlibRGB, so the specified drawable must have the XlibRGB visual and colormap. + * + * When used with #GDK_PIXBUF_ALPHA_BILEVEL, this function has to create a bitmap + * out of the thresholded alpha channel of the image and, it has to set this + * bitmap as the clipping mask for the GC used for drawing. This can be a + * significant performance penalty depending on the size and the complexity of + * the alpha channel of the image. If performance is crucial, consider handling + * the alpha channel yourself (possibly by caching it in your application) and + * using gdk_pixbuf_xlib_render_to_drawable() or GdkRGB directly instead. + **/ +void +gdk_pixbuf_xlib_render_to_drawable_alpha (GdkPixbuf *pixbuf, Drawable drawable, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + GdkPixbufAlphaMode alpha_mode, + int alpha_threshold, + XlibRgbDither dither, + int x_dither, int y_dither) +{ + Pixmap bitmap = 0; + GC gc; + XGCValues gcv; + + g_return_if_fail (pixbuf != NULL); + g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); + g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); + g_return_if_fail (pixbuf->bits_per_sample == 8); + + g_return_if_fail (drawable != 0); + g_return_if_fail (width >= 0 && height >= 0); + g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width); + g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height); + + if (width == 0 || height == 0) + return; + + gc = XCreateGC (gdk_pixbuf_dpy, drawable, 0, &gcv); + + if (pixbuf->has_alpha) { + /* Right now we only support GDK_PIXBUF_ALPHA_BILEVEL, so we + * unconditionally create the clipping mask. + */ + + bitmap = XCreatePixmap (gdk_pixbuf_dpy, + RootWindow (gdk_pixbuf_dpy, + gdk_pixbuf_screen), + width, height, 1); + gdk_pixbuf_xlib_render_threshold_alpha (pixbuf, bitmap, + src_x, src_y, + 0, 0, + width, height, + alpha_threshold); + + XSetClipMask (gdk_pixbuf_dpy, gc, bitmap); + XSetClipOrigin (gdk_pixbuf_dpy, gc, dest_x, dest_y); + } + + gdk_pixbuf_xlib_render_to_drawable (pixbuf, drawable, gc, + src_x, src_y, + dest_x, dest_y, + width, height, + dither, + x_dither, y_dither); + + if (bitmap) + XFreePixmap (gdk_pixbuf_dpy, bitmap); + + XFreeGC (gdk_pixbuf_dpy, gc); +} + +/** + * gdk_pixbuf_xlib_render_pixmap_and_mask: + * @pixbuf: A pixbuf. + * @pixmap_return: Return value for the created pixmap. + * @mask_return: Return value for the created mask. + * @alpha_threshold: Threshold value for opacity values. + * + * Creates a pixmap and a mask bitmap which are returned in the @pixmap_return + * and @mask_return arguments, respectively, and renders a pixbuf and its + * corresponding tresholded alpha mask to them. This is merely a convenience + * function; applications that need to render pixbufs with dither offsets or to + * given drawables should use gdk_pixbuf_xlib_render_to_drawable_alpha() or + * gdk_pixbuf_xlib_render_to_drawable(), and + * gdk_pixbuf_xlib_render_threshold_alpha(). + * + * If the pixbuf does not have an alpha channel, then *@mask_return will be set + * to None. + **/ +void +gdk_pixbuf_xlib_render_pixmap_and_mask (GdkPixbuf *pixbuf, + Pixmap *pixmap_return, + Pixmap *mask_return, + int alpha_threshold) +{ + g_return_if_fail (pixbuf != NULL); + + if (pixmap_return) { + GC gc; + XGCValues gcv; + + *pixmap_return = XCreatePixmap (gdk_pixbuf_dpy, + RootWindow (gdk_pixbuf_dpy, + gdk_pixbuf_screen), + pixbuf->width, + pixbuf->height, + xlib_rgb_get_depth ()); + gc = XCreateGC (gdk_pixbuf_dpy, *pixmap_return, 0, &gcv); + gdk_pixbuf_xlib_render_to_drawable (pixbuf, *pixmap_return, gc, + 0, 0, 0, 0, + pixbuf->width, + pixbuf->height, + XLIB_RGB_DITHER_NORMAL, + 0, 0); + XFreeGC (gdk_pixbuf_dpy, gc); + } + + if (mask_return) { + if (pixbuf->has_alpha) { + *mask_return = XCreatePixmap (gdk_pixbuf_dpy, + RootWindow (gdk_pixbuf_dpy, + gdk_pixbuf_screen), + pixbuf->width, + pixbuf->height, 1); + gdk_pixbuf_xlib_render_threshold_alpha (pixbuf, + *mask_return, + 0, 0, 0, 0, + pixbuf->width, + pixbuf->height, + alpha_threshold); + } else + *mask_return = 0; + } +} diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.c b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.c new file mode 100644 index 000000000..340dd31ec --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.c @@ -0,0 +1,63 @@ +/* GdkPixbuf library - Initialization functions + * + * Author: John Harper <john@dcs.warwick.ac.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <X11/Xlib.h> +#include <gdk-pixbuf/gdk-pixbuf-private.h> +#include "gdk-pixbuf-xlib-private.h" + +Display *gdk_pixbuf_dpy = NULL; +int gdk_pixbuf_screen = -1; + +/** + * gdk_pixbuf_xlib_init: + * @display: X display to use. + * @screen_num: Screen number. + * + * Initializes the gdk-pixbuf Xlib machinery by calling xlib_rgb_init(). This + * function should be called near the beginning of your program, or before using + * any of the gdk-pixbuf-xlib functions. + **/ +void +gdk_pixbuf_xlib_init (Display *display, int screen_num) +{ + xlib_rgb_init (display, ScreenOfDisplay (display, screen_num)); + gdk_pixbuf_dpy = display; + gdk_pixbuf_screen = screen_num; +} + +/** + * gdk_pixbuf_xlib_init_with_depth: + * @display: X display to use. + * @screen_num: Screen number. + * @prefDepth: Preferred depth for XlibRGB. + * + * Similar to gdk_pixbuf_xlib_init(), but also lets you specify the preferred + * depth for XlibRGB if you do not want it to use the default depth it picks. + **/ +void +gdk_pixbuf_xlib_init_with_depth (Display *display, + int screen_num, int prefDepth) +{ + xlib_rgb_init_with_depth (display, ScreenOfDisplay (display, screen_num), + prefDepth); + gdk_pixbuf_dpy = display; + gdk_pixbuf_screen = screen_num; +} diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.h b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.h new file mode 100644 index 000000000..b19748671 --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlib.h @@ -0,0 +1,82 @@ +/* GdkPixbuf library - Xlib header file + * + * Authors: John Harper <john@dcs.warwick.ac.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GDK_PIXBUF_XLIB_H +#define GDK_PIXBUF_XLIB_H + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.h> +#include <X11/Xlib.h> + + + +/* init */ + +void gdk_pixbuf_xlib_init (Display *display, int screen_num); + +void gdk_pixbuf_xlib_init_with_depth (Display *display, int screen_num, + int prefDepth); + + + +/* render */ + +void gdk_pixbuf_xlib_render_threshold_alpha (GdkPixbuf *pixbuf, Pixmap bitmap, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + int alpha_threshold); + +void gdk_pixbuf_xlib_render_to_drawable (GdkPixbuf *pixbuf, + Drawable drawable, GC gc, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + XlibRgbDither dither, + int x_dither, int y_dither); + + +void gdk_pixbuf_xlib_render_to_drawable_alpha (GdkPixbuf *pixbuf, + Drawable drawable, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height, + GdkPixbufAlphaMode alpha_mode, + int alpha_threshold, + XlibRgbDither dither, + int x_dither, int y_dither); + +void gdk_pixbuf_xlib_render_pixmap_and_mask (GdkPixbuf *pixbuf, + Pixmap *pixmap_return, + Pixmap *mask_return, + int alpha_threshold); + + + +/* drawable */ + +GdkPixbuf *gdk_pixbuf_xlib_get_from_drawable (GdkPixbuf *dest, + Drawable src, + Colormap cmap, Visual *visual, + int src_x, int src_y, + int dest_x, int dest_y, + int width, int height); + +#endif /* GDK_PIXBUF_XLIB_H */ diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.c b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.c new file mode 100644 index 000000000..97e6d71fa --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.c @@ -0,0 +1,3706 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Library General Public License (the "LGPL"), in + * which case the provisions of the LGPL are applicable instead of + * those above. If you wish to allow use of your version of this file + * only under the terms of the LGPL and not to allow others to use + * your version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the LGPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the LGPL. + */ + +/* + * This code is derived from GdkRgb. + * For more information on GdkRgb, see http://www.levien.com/gdkrgb/ + * Raph Levien <raph@acm.org> + */ + +/* Ported by Christopher Blizzard to Xlib. With permission from the + * original authors and the copyright holders of this file, the + * contents of this file are also redistributable under the terms of + * the Mozilla Public license. For information about the Mozilla + * Public License, please see the license information at + * http://www.mozilla.org/MPL/ */ + +/* This code is copyright the following authors: + * Raph Levien <raph@acm.org> + * Manish Singh <manish@gtk.org> + * Tim Janik <timj@gtk.org> + * Peter Mattis <petm@xcf.berkeley.edu> + * Spencer Kimball <spencer@xcf.berkeley.edu> + * Josh MacDonald <jmacd@xcf.berkeley.edu> + * Christopher Blizzard <blizzard@redhat.com> + * Owen Taylor <otaylor@redhat.com> + * Shawn T. Amundson <amundson@gtk.org> +*/ + +#include <math.h> + +#if HAVE_CONFIG_H +# include <config.h> +# if STDC_HEADERS +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +#endif + +#define ENABLE_GRAYSCALE + +/* include this before so that we can get endian definitions if + they are there... */ + +#include "gdk-pixbuf-xlibrgb.h" + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +typedef enum { + LSB_FIRST, + MSB_FIRST +} ByteOrder; + + +typedef struct _XlibRgbInfo XlibRgbInfo; + +typedef void (*XlibRgbConvFunc) (XImage *image, + int ax, int ay, + int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap); + +/* Some of these fields should go, as they're not being used at all. + Globals should generally migrate into here - it's very likely that + we'll want to run more than one GdkRgbInfo context at the same time + (i.e. some but not all windows have privately installed + colormaps). */ + +struct _XlibRgbInfo +{ + Display *display; + Screen *screen; + int screen_num; + XVisualInfo *x_visual_info; + Colormap cmap; + XColor *cmap_colors; + Visual *default_visualid; + Colormap default_colormap; + + unsigned long *color_pixels; + unsigned long *gray_pixels; + unsigned long *reserved_pixels; + + unsigned long red_shift; + unsigned long red_prec; + unsigned long blue_shift; + unsigned long blue_prec; + unsigned long green_shift; + unsigned long green_prec; + + unsigned int nred_shades; + unsigned int ngreen_shades; + unsigned int nblue_shades; + unsigned int ngray_shades; + unsigned int nreserved; + + unsigned int bpp; + unsigned int cmap_alloced; + double gamma_val; + + /* Generally, the stage buffer is used to convert 32bit RGB, gray, + and indexed images into 24 bit packed RGB. */ + unsigned char *stage_buf; + + XlibRgbCmap *gray_cmap; + + Bool dith_default; + + Bool bitmap; /* set true if in 1 bit per pixel mode */ + GC own_gc; + + /* Convert functions */ + XlibRgbConvFunc conv; + XlibRgbConvFunc conv_d; + + XlibRgbConvFunc conv_32; + XlibRgbConvFunc conv_32_d; + + XlibRgbConvFunc conv_gray; + XlibRgbConvFunc conv_gray_d; + + XlibRgbConvFunc conv_indexed; + XlibRgbConvFunc conv_indexed_d; +}; + +static Bool xlib_rgb_install_cmap = FALSE; +static int xlib_rgb_min_colors = 5 * 5 * 5; +static Bool xlib_rgb_verbose = FALSE; + +#define IMAGE_WIDTH 256 +#define STAGE_ROWSTRIDE (IMAGE_WIDTH * 3) +#define IMAGE_HEIGHT 64 +#define N_IMAGES 6 + +static XlibRgbInfo *image_info = NULL; +static XImage *static_image[N_IMAGES]; +static int static_image_idx; + +static unsigned char *colorcube; +static unsigned char *colorcube_d; + +static unsigned long +xlib_get_prec_from_mask(unsigned long val) +{ + unsigned long retval = 0; + unsigned int cur_bit = 0; + /* walk through the number, incrementing the value if + the bit in question is set. */ + while (cur_bit < (sizeof(unsigned long) * 8)) { + if ((val >> cur_bit) & 0x1) { + retval++; + } + cur_bit++; + } + return retval; +} + +static unsigned long +xlib_get_shift_from_mask(unsigned long val) +{ + unsigned long cur_bit = 0; + /* walk through the number, looking for the first 1 */ + while (cur_bit < (sizeof(unsigned long) * 8)) { + if ((val >> cur_bit) & 0x1) { + return cur_bit; + } + cur_bit++; + } + return cur_bit; +} + + +static int +xlib_rgb_cmap_fail (const char *msg, Colormap cmap, unsigned long *pixels) +{ + unsigned long free_pixels[256]; + int n_free; + int i; + +#ifdef VERBOSE + printf ("%s", msg); +#endif + n_free = 0; + for (i = 0; i < 256; i++) + if (pixels[i] < 256) + free_pixels[n_free++] = pixels[i]; + + if (n_free) + XFreeColors(image_info->display, + cmap, + free_pixels, + n_free, + 0); + return 0; +} + +static void +xlib_rgb_make_colorcube (unsigned long *pixels, int nr, int ng, int nb) +{ + unsigned char rt[16], gt[16], bt[16]; + int i; + + colorcube = malloc(sizeof(unsigned char) * 4096); + memset(colorcube, 0, (sizeof(unsigned char) * 4096)); + for (i = 0; i < 16; i++) + { + rt[i] = ng * nb * ((i * 17 * (nr - 1) + 128) >> 8); + gt[i] = nb * ((i * 17 * (ng - 1) + 128) >> 8); + bt[i] = ((i * 17 * (nb - 1) + 128) >> 8); + } + + for (i = 0; i < 4096; i++) + { + colorcube[i] = pixels[rt[i >> 8] + gt[(i >> 4) & 0x0f] + bt[i & 0x0f]]; +#ifdef VERBOSE + printf ("%03x %02x %x %x %x\n", i, colorcube[i], rt[i >> 8], gt[(i >> 4) & 0x0f], bt[i & 0x0f]); +#endif + } +} + +/* this is the colorcube suitable for dithering */ +static void +xlib_rgb_make_colorcube_d (unsigned long *pixels, int nr, int ng, int nb) +{ + int r, g, b; + int i; + + colorcube_d = malloc(sizeof(unsigned char) * 512); + memset(colorcube_d, 0, (sizeof(unsigned char) * 512)); + for (i = 0; i < 512; i++) + { + r = MIN (nr - 1, i >> 6); + g = MIN (ng - 1, (i >> 3) & 7); + b = MIN (nb - 1, i & 7); + colorcube_d[i] = pixels[(r * ng + g) * nb + b]; + } +} + +/* Try installing a color cube of the specified size. + Make the colorcube and return TRUE on success */ +static int +xlib_rgb_try_colormap (int nr, int ng, int nb) +{ + int r, g, b; + int ri, gi, bi; + int r0, g0, b0; + Colormap cmap; + XVisualInfo *visual; + XColor *colors = NULL; + XColor color; + unsigned long pixels[256]; + unsigned long junk[256]; + int i; + int d2; + unsigned int colors_needed; + int idx; + int best[256]; + + if (nr * ng * nb < xlib_rgb_min_colors) + return FALSE; + + if (image_info->cmap_alloced) { + cmap = image_info->cmap; + visual = image_info->x_visual_info; + } + else { + cmap = image_info->default_colormap; + visual = image_info->x_visual_info; + } + colors_needed = nr * ng * nb; + for (i = 0; i < 256; i++) + { + best[i] = 192; + pixels[i] = 256; + } + +#ifndef GAMMA + if (!xlib_rgb_install_cmap) { + /* go out and get the colors for this colormap. */ + colors = malloc(sizeof(XColor) * visual->colormap_size); + for (i=0; i < visual->colormap_size; i++){ + colors[i].pixel = i; + } + XQueryColors (image_info->display, + cmap, + colors, visual->colormap_size); + /* find color cube colors that are already present */ + for (i = 0; i < MIN (256, visual->colormap_size); i++) + { + r = colors[i].red >> 8; + g = colors[i].green >> 8; + b = colors[i].blue >> 8; + ri = (r * (nr - 1) + 128) >> 8; + gi = (g * (ng - 1) + 128) >> 8; + bi = (b * (nb - 1) + 128) >> 8; + r0 = ri * 255 / (nr - 1); + g0 = gi * 255 / (ng - 1); + b0 = bi * 255 / (nb - 1); + idx = ((ri * nr) + gi) * nb + bi; + d2 = (r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0); + if (d2 < best[idx]) { + if (pixels[idx] < 256) + XFreeColors(image_info->display, + cmap, + pixels + idx, + 1, 0); + else + colors_needed--; + color.pixel = colors[i].pixel; + color.red = colors[i].red; + color.green = colors[i].green; + color.blue = colors[i].blue; + color.flags = 0; + if (!XAllocColor(image_info->display, cmap, &color)) + return xlib_rgb_cmap_fail ("error allocating system color\n", + cmap, pixels); + pixels[idx] = color.pixel; /* which is almost certainly i */ + best[idx] = d2; + } + } + } + +#endif + + if (colors_needed) + { + if (!XAllocColorCells(image_info->display, cmap, 0, NULL, 0, junk, colors_needed)) + { + char tmp_str[80]; + + sprintf (tmp_str, + "%d %d %d colormap failed (in XAllocColorCells)\n", + nr, ng, nb); + return xlib_rgb_cmap_fail (tmp_str, cmap, pixels); + } + XFreeColors(image_info->display, cmap, junk, (int)colors_needed, 0); + } + + for (r = 0, i = 0; r < nr; r++) + for (g = 0; g < ng; g++) + for (b = 0; b < nb; b++, i++) + { + if (pixels[i] == 256) + { + color.red = r * 65535 / (nr - 1); + color.green = g * 65535 / (ng - 1); + color.blue = b * 65535 / (nb - 1); + +#ifdef GAMMA + color.red = 65535 * pow (color.red / 65535.0, 0.5); + color.green = 65535 * pow (color.green / 65535.0, 0.5); + color.blue = 65535 * pow (color.blue / 65535.0, 0.5); +#endif + + /* This should be a raw XAllocColor call */ + if (!XAllocColor(image_info->display, cmap, &color)) + { + char tmp_str[80]; + + sprintf (tmp_str, "%d %d %d colormap failed\n", + nr, ng, nb); + return xlib_rgb_cmap_fail (tmp_str, + cmap, pixels); + } + pixels[i] = color.pixel; + } +#ifdef VERBOSE + printf ("%d: %lx\n", i, pixels[i]); +#endif + } + + image_info->nred_shades = nr; + image_info->ngreen_shades = ng; + image_info->nblue_shades = nb; + xlib_rgb_make_colorcube (pixels, nr, ng, nb); + xlib_rgb_make_colorcube_d (pixels, nr, ng, nb); + if (colors) + free(colors); + return TRUE; +} + +/* Return TRUE on success. */ +static Bool +xlib_rgb_do_colormaps (void) +{ + static const int sizes[][3] = { + /* { 6, 7, 6 }, */ + { 6, 6, 6 }, + { 6, 6, 5 }, + { 6, 6, 4 }, + { 5, 5, 5 }, + { 5, 5, 4 }, + { 4, 4, 4 }, + { 4, 4, 3 }, + { 3, 3, 3 }, + { 2, 2, 2 } + }; + static const int n_sizes = sizeof(sizes) / (3 * sizeof(int)); + int i; + + for (i = 0; i < n_sizes; i++) + if (xlib_rgb_try_colormap (sizes[i][0], sizes[i][1], sizes[i][2])) + return TRUE; + return FALSE; +} + +/* Make a 2 x 2 x 2 colorcube */ +static void +xlib_rgb_colorcube_222 (void) +{ + int i; + XColor color; + Colormap cmap; + + if (image_info->cmap_alloced) + cmap = image_info->cmap; + else + cmap = image_info->default_colormap; + + colorcube_d = malloc(sizeof(unsigned char) * 512); + + for (i = 0; i < 8; i++) + { + color.red = ((i & 4) >> 2) * 65535; + color.green = ((i & 2) >> 1) * 65535; + color.blue = (i & 1) * 65535; + XAllocColor (image_info->display, cmap, &color); + colorcube_d[((i & 4) << 4) | ((i & 2) << 2) | (i & 1)] = color.pixel; + } +} + +void +xlib_rgb_set_verbose (Bool verbose) +{ + xlib_rgb_verbose = verbose; +} + +void +xlib_rgb_set_install (Bool install) +{ + xlib_rgb_install_cmap = install; +} + +void +xlib_rgb_set_min_colors (int min_colors) +{ + xlib_rgb_min_colors = min_colors; +} + +/* Return a "score" based on the following criteria (in hex): + + x000 is the quality - 1 is 1bpp, 2 is 4bpp, + 4 is 8bpp, + 7 is 15bpp truecolor, 8 is 16bpp truecolor, + 9 is 24bpp truecolor. + 0x00 is the speed - 1 is the normal case, + 2 means faster than normal + 00x0 gets a point for being the system visual + 000x gets a point for being pseudocolor + + A caveat: in the 8bpp modes, being the system visual seems to be + quite important. Thus, all of the 8bpp modes should be ranked at + the same speed. +*/ + +static guint32 +xlib_rgb_score_visual (XVisualInfo *visual) +{ + guint32 quality, speed, pseudo, sys; + static const char* visual_names[] = + { + "static gray", + "grayscale", + "static color", + "pseudo color", + "true color", + "direct color", + }; + + + quality = 0; + speed = 1; + sys = 0; + if (visual->class == TrueColor || + visual->class == DirectColor) + { + if (visual->depth == 24) + { + quality = 9; + /* Should test for MSB visual here, and set speed if so. */ + } + else if (visual->depth == 16) + quality = 8; + else if (visual->depth == 15) + quality = 7; + else if (visual->depth == 8) + quality = 4; + } + else if (visual->class == PseudoColor || + visual->class == StaticColor) + { + if (visual->depth == 8) + quality = 4; + else if (visual->depth == 4) + quality = 2; + else if (visual->depth == 1) + quality = 1; + } + else if (visual->class == StaticGray +#ifdef ENABLE_GRAYSCALE + || visual->class == GrayScale +#endif + ) + { + if (visual->depth == 8) + quality = 4; + else if (visual->depth == 4) + quality = 2; + else if (visual->depth == 1) + quality = 1; + } + + if (quality == 0) + return 0; + + sys = (visual->visualid == image_info->default_visualid->visualid); + + pseudo = (visual->class == PseudoColor || visual->class == TrueColor); + + if (xlib_rgb_verbose) + printf ("Visual 0x%x, type = %s, depth = %d, %ld:%ld:%ld%s; score=%x\n", + (int)visual->visualid, + visual_names[visual->class], + visual->depth, + visual->red_mask, + visual->green_mask, + visual->blue_mask, + sys ? " (system)" : "", + (quality << 12) | (speed << 8) | (sys << 4) | pseudo); + + return (quality << 12) | (speed << 8) | (sys << 4) | pseudo; +} + +static void +xlib_rgb_choose_visual (void) +{ + XVisualInfo *visuals; + XVisualInfo *visual; + XVisualInfo *best_visual; + XVisualInfo *final_visual; + XVisualInfo template; + int num_visuals; + guint32 score, best_score; + int cur_visual = 1; + int i; + + template.screen = image_info->screen_num; + visuals = XGetVisualInfo(image_info->display, VisualScreenMask, + &template, &num_visuals); + + best_visual = visuals; + best_score = xlib_rgb_score_visual (best_visual); + + for (i = cur_visual; i < num_visuals; i++) + { + visual = &visuals[i]; + score = xlib_rgb_score_visual (visual); + if (score > best_score) + { + best_score = score; + best_visual = visual; + } + } + /* make a copy of the visual so that we can free + the allocated visual list above. */ + final_visual = malloc(sizeof(XVisualInfo)); + memcpy(final_visual, best_visual, sizeof(XVisualInfo)); + image_info->x_visual_info = final_visual; + XFree(visuals); + /* set up the shift and the precision for the red, green and blue. + this only applies to cool visuals like true color and direct color. */ + if (image_info->x_visual_info->class == TrueColor || + image_info->x_visual_info->class == DirectColor) { + image_info->red_shift = xlib_get_shift_from_mask(image_info->x_visual_info->red_mask); + image_info->red_prec = xlib_get_prec_from_mask(image_info->x_visual_info->red_mask); + image_info->green_shift = xlib_get_shift_from_mask(image_info->x_visual_info->green_mask); + image_info->green_prec = xlib_get_prec_from_mask(image_info->x_visual_info->green_mask); + image_info->blue_shift = xlib_get_shift_from_mask(image_info->x_visual_info->blue_mask); + image_info->blue_prec = xlib_get_prec_from_mask(image_info->x_visual_info->blue_mask); + } +} + +static void +xlib_rgb_choose_visual_for_xprint (int aDepth) +{ + XVisualInfo *visuals; + XVisualInfo *visual; + XVisualInfo *best_visual; + XVisualInfo *final_visual; + XVisualInfo template; + int num_visuals; + int cur_visual = 1; + int i; + + XWindowAttributes win_att; + Status ret_stat; + Visual *root_visual; + + ret_stat = XGetWindowAttributes(image_info->display, + RootWindow(image_info->display, image_info->screen_num), + &win_att); + root_visual = win_att.visual; + template.screen = image_info->screen_num; + visuals = XGetVisualInfo(image_info->display, VisualScreenMask, + &template, &num_visuals); + + best_visual = visuals; + if (best_visual->visual != root_visual) { + for (i = cur_visual; i < num_visuals; i++) { + visual = &visuals[i]; + if (visual->visual == root_visual) { + best_visual = visual; + break; + } + } + } + /* make a copy of the visual so that we can free + the allocated visual list above. */ + final_visual = malloc(sizeof(XVisualInfo)); + memcpy(final_visual, best_visual, sizeof(XVisualInfo)); + image_info->x_visual_info = final_visual; + XFree(visuals); + /* set up the shift and the precision for the red, green and blue. + this only applies to cool visuals like true color and direct color. */ + if (image_info->x_visual_info->class == TrueColor || + image_info->x_visual_info->class == DirectColor) { + image_info->red_shift = xlib_get_shift_from_mask(image_info->x_visual_info->red_mask); + image_info->red_prec = xlib_get_prec_from_mask(image_info->x_visual_info->red_mask); + image_info->green_shift = xlib_get_shift_from_mask(image_info->x_visual_info->green_mask); + image_info->green_prec = xlib_get_prec_from_mask(image_info->x_visual_info->green_mask); + image_info->blue_shift = xlib_get_shift_from_mask(image_info->x_visual_info->blue_mask); + image_info->blue_prec = xlib_get_prec_from_mask(image_info->x_visual_info->blue_mask); + } +} + +static void xlib_rgb_select_conv (XImage *image, ByteOrder byte_order); + +static void +xlib_rgb_set_gray_cmap (Colormap cmap) +{ + int i; + XColor color; + int status; + unsigned long pixels[256]; + int r, g, b, gray; + + for (i = 0; i < 256; i++) + { + color.pixel = i; + color.red = i * 257; + color.green = i * 257; + color.blue = i * 257; + status = XAllocColor(image_info->display, cmap, &color); + pixels[i] = color.pixel; +#ifdef VERBOSE + printf ("allocating pixel %d, %x %x %x, result %d\n", + color.pixel, color.red, color.green, color.blue, status); +#endif + } + + /* Now, we make fake colorcubes - we ultimately just use the pseudocolor + methods. */ + + colorcube = malloc(sizeof(unsigned char) * 4096); + + for (i = 0; i < 4096; i++) + { + r = (i >> 4) & 0xf0; + r = r | r >> 4; + g = i & 0xf0; + g = g | g >> 4; + b = (i << 4 & 0xf0); + b = b | b >> 4; + gray = (g + ((r + b) >> 1)) >> 1; + colorcube[i] = pixels[gray]; + } +} + +/** + * xlib_rgb_init: + * @display: X Display to use. + * @screen: Screen to use. + * + * Initializes the XlibRGB machinery with the default depth. If you use this + * function XlibRGB will automatically pick the best visual available on your + * display. This function or xlib_rgb_init_with_depth() must be called before + * using any of the other functions in XlibRGB. + **/ +void +xlib_rgb_init (Display *display, Screen *screen) +{ + int prefDepth = -1; // let the function do the visual scoring + xlib_rgb_init_with_depth(display, screen, prefDepth); +} + +/** + * xlib_rgb_init_with_depth: + * @display: X display to use. + * @screen: Screen to use. + * @prefDepth: Visual depth to use for color substitution tables. This must + * be one of the supported visual depths in the specified @display. + * + * Initializes the XlibRGB machinery with a particular depth you specify, + * instead of automatically picking the best depth in the display. This + * function or xlib_rgb_init() must be called before using any of the other + * functions in XlibRGB. + **/ +void +xlib_rgb_init_with_depth (Display *display, Screen *screen, int prefDepth) +{ + int i; + static const int byte_order[1] = { 1 }; + + static int initialized = 0; + + if (initialized) + { + return; + } + + initialized = 1; + + /* check endian sanity */ +#if G_BYTE_ORDER == G_BIG_ENDIAN + if (((char *)byte_order)[0] == 1) { + printf ("xlib_rgb_init: compiled for big endian, but this is a little endian machine.\n\n"); + exit(1); + } +#else + if (((char *)byte_order)[0] != 1) { + printf ("xlib_rgb_init: compiled for little endian, but this is a big endian machine.\n\n"); + exit(1); + } +#endif + + if (image_info == NULL) + { + image_info = malloc(sizeof(XlibRgbInfo)); + memset(image_info, 0, sizeof(XlibRgbInfo)); + + image_info->display = display; + image_info->screen = screen; + image_info->screen_num = XScreenNumberOfScreen(screen); + image_info->x_visual_info = NULL; + image_info->cmap = 0; + image_info->default_visualid = DefaultVisual(display, image_info->screen_num); + image_info->default_colormap = DefaultColormap(display, image_info->screen_num); + + image_info->color_pixels = NULL; + image_info->gray_pixels = NULL; + image_info->reserved_pixels = NULL; + + image_info->nred_shades = 6; + image_info->ngreen_shades = 6; + image_info->nblue_shades = 4; + image_info->ngray_shades = 24; + image_info->nreserved = 0; + + image_info->bpp = 0; + image_info->cmap_alloced = FALSE; + image_info->gamma_val = 1.0; + + image_info->stage_buf = NULL; + + image_info->own_gc = 0; + + image_info->red_shift = 0; + image_info->red_prec = 0; + image_info->green_shift = 0; + image_info->green_prec = 0; + image_info->blue_shift = 0; + image_info->blue_prec = 0; + + if (prefDepth != -1) + xlib_rgb_choose_visual_for_xprint (prefDepth); + else + xlib_rgb_choose_visual (); + + if ((image_info->x_visual_info->class == PseudoColor || + image_info->x_visual_info->class == StaticColor) && + image_info->x_visual_info->depth < 8 && + image_info->x_visual_info->depth >= 3) + { + image_info->cmap = image_info->default_colormap; + xlib_rgb_colorcube_222 (); + } + else if (image_info->x_visual_info->class == PseudoColor) + { + if (xlib_rgb_install_cmap || + image_info->x_visual_info->visualid != image_info->default_visualid->visualid) + { + image_info->cmap = XCreateColormap(image_info->display, + RootWindow(image_info->display, image_info->screen_num), + image_info->x_visual_info->visual, + AllocNone); + image_info->cmap_alloced = TRUE; + } + if (!xlib_rgb_do_colormaps ()) + { + image_info->cmap = XCreateColormap(image_info->display, + RootWindow(image_info->display, image_info->screen_num), + image_info->x_visual_info->visual, + AllocNone); + image_info->cmap_alloced = TRUE; + xlib_rgb_do_colormaps (); + } + if (xlib_rgb_verbose) + printf ("color cube: %d x %d x %d\n", + image_info->nred_shades, + image_info->ngreen_shades, + image_info->nblue_shades); + + if (!image_info->cmap_alloced) + image_info->cmap = image_info->default_colormap; + } +#ifdef ENABLE_GRAYSCALE + else if (image_info->x_visual_info->class == GrayScale) + { + image_info->cmap = XCreateColormap(image_info->display, + RootWindow(image_info->display, image_info->screen_num), + image_info->x_visual_info->visual, + AllocNone); + xlib_rgb_set_gray_cmap (image_info->cmap); + image_info->cmap_alloced = TRUE; + } +#endif + else + { + /* Always install colormap in direct color. */ + if (image_info->x_visual_info->class != DirectColor && + image_info->x_visual_info->visualid == image_info->default_visualid->visualid) + image_info->cmap = image_info->default_colormap; + else + { + image_info->cmap = XCreateColormap(image_info->display, + RootWindow(image_info->display, image_info->screen_num), + image_info->x_visual_info->visual, + AllocNone); + image_info->cmap_alloced = TRUE; + } + } + + image_info->bitmap = (image_info->x_visual_info->depth == 1); + + for (i = 0; i < N_IMAGES; i++) { + if (image_info->bitmap) { + /* Use malloc() instead of g_malloc since X will free() this mem */ + static_image[i] = XCreateImage(image_info->display, + image_info->x_visual_info->visual, + 1, + XYBitmap, + 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, + 8, + 0); + static_image[i]->data = malloc(IMAGE_WIDTH * IMAGE_HEIGHT >> 3); + static_image[i]->bitmap_bit_order = MSBFirst; + static_image[i]->byte_order = MSBFirst; + } + else { + static_image[i] = XCreateImage(image_info->display, + image_info->x_visual_info->visual, + (unsigned int)image_info->x_visual_info->depth, + ZPixmap, + 0, 0, + IMAGE_WIDTH, + IMAGE_HEIGHT, + 32, 0); + /* remove this when we are using shared memory.. */ + static_image[i]->data = malloc((size_t)IMAGE_WIDTH * IMAGE_HEIGHT * image_info->x_visual_info->depth); + static_image[i]->bitmap_bit_order = MSBFirst; + static_image[i]->byte_order = MSBFirst; + } + } + /* ok, so apparently, image_info->bpp is actually + BYTES per pixel. What fun! */ + switch (static_image[0]->bits_per_pixel) { + case 1: + case 8: + image_info->bpp = 1; + break; + case 16: + image_info->bpp = 2; + break; + case 24: + image_info->bpp = 3; + break; + case 32: + image_info->bpp = 4; + break; + } + xlib_rgb_select_conv (static_image[0], MSB_FIRST); + } +} + +/** + * xlib_rgb_xpixel_from_rgb: + * @rgb: 32-bit representation of an RGB value, specified as 0x00RRGGBB. + * + * Converts an RGB triplet into the closest color that XlibRGB visual can + * handle. + * + * Return value: X pixel value that corresponds to the closest color in the + * XlibRGB visual and colormap. + **/ +unsigned long +xlib_rgb_xpixel_from_rgb (guint32 rgb) +{ + unsigned long pixel = 0; + + if (image_info->bitmap) + { + return ((rgb & 0xff0000) >> 16) + + ((rgb & 0xff00) >> 7) + + (rgb & 0xff) > 510; + } + else if (image_info->x_visual_info->class == PseudoColor) + pixel = colorcube[((rgb & 0xf00000) >> 12) | + ((rgb & 0xf000) >> 8) | + ((rgb & 0xf0) >> 4)]; + else if (image_info->x_visual_info->depth < 8 && + image_info->x_visual_info->class == StaticColor) + { + pixel = colorcube_d[((rgb & 0x800000) >> 17) | + ((rgb & 0x8000) >> 12) | + ((rgb & 0x80) >> 7)]; + } + else if (image_info->x_visual_info->class == TrueColor || + image_info->x_visual_info->class == DirectColor) + { +#ifdef VERBOSE + printf ("shift, prec: r %d %d g %d %d b %d %d\n", + image_info->red_shift, + image_info->red_prec, + image_info->green_shift, + image_info->green_prec, + image_info->blue_shift, + image_info->blue_prec); +#endif + + pixel = (((((rgb & 0xff0000) >> 16) >> + (8 - image_info->red_prec)) << + image_info->red_shift) + + ((((rgb & 0xff00) >> 8) >> + (8 - image_info->green_prec)) << + image_info->green_shift) + + (((rgb & 0xff) >> + (8 - image_info->blue_prec)) << + image_info->blue_shift)); + } + else if (image_info->x_visual_info->class == StaticGray || + image_info->x_visual_info->class == GrayScale) + { + int gray = ((rgb & 0xff0000) >> 16) + + ((rgb & 0xff00) >> 7) + + (rgb & 0xff); + + return gray >> (10 - image_info->x_visual_info->depth); + } + + return pixel; +} + +/** + * xlib_rgb_gc_set_foreground: + * @gc: A graphic context. + * @rgb: 32-bit representation of an RGB value, specified as 0x00RRGGBB. + * + * This is a convenience function to set the foreground of a GC from an RGB + * triplet. It calls xlib_rgb_xpixel_from_rgb() internally and uses the + * returned pixel value to set the GC's foreground. + **/ +void +xlib_rgb_gc_set_foreground (GC gc, guint32 rgb) +{ + unsigned long color; + + color = xlib_rgb_xpixel_from_rgb (rgb); + XSetForeground(image_info->display, gc, color); +} + +/** + * xlib_rgb_gc_set_foreground: + * @gc: A graphic context. + * @rgb: 32-bit representation of an RGB value, specified as 0x00RRGGBB. + * + * This is a convenience function to set the background of a GC from an RGB + * triplet. It calls xlib_rgb_xpixel_from_rgb() internally and uses the + * returned pixel value to set the GC's background. + **/ +void +xlib_rgb_gc_set_background (GC gc, guint32 rgb) +{ + unsigned long color; + + color = xlib_rgb_xpixel_from_rgb (rgb); + XSetBackground(image_info->display, gc, color); +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define HAIRY_CONVERT_8 +#endif + +#ifdef HAIRY_CONVERT_8 +static void +xlib_rgb_convert_8 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + if (((unsigned long)obuf | (unsigned long) bp2) & 3) + { + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + obptr[0] = colorcube[((r & 0xf0) << 4) | + (g & 0xf0) | + (b >> 4)]; + obptr++; + } + } + else + { + for (x = 0; x < width - 3; x += 4) + { + guint32 r1b0g0r0; + guint32 g2r2b1g1; + guint32 b3g3r3b2; + + r1b0g0r0 = ((guint32 *)bp2)[0]; + g2r2b1g1 = ((guint32 *)bp2)[1]; + b3g3r3b2 = ((guint32 *)bp2)[2]; + ((guint32 *)obptr)[0] = + colorcube[((r1b0g0r0 & 0xf0) << 4) | + ((r1b0g0r0 & 0xf000) >> 8) | + ((r1b0g0r0 & 0xf00000) >> 20)] | + (colorcube[((r1b0g0r0 & 0xf0000000) >> 20) | + (g2r2b1g1 & 0xf0) | + ((g2r2b1g1 & 0xf000) >> 12)] << 8) | + (colorcube[((g2r2b1g1 & 0xf00000) >> 12) | + ((g2r2b1g1 & 0xf0000000) >> 24) | + ((b3g3r3b2 & 0xf0) >> 4)] << 16) | + (colorcube[((b3g3r3b2 & 0xf000) >> 4) | + ((b3g3r3b2 & 0xf00000) >> 16) | + (b3g3r3b2 >> 28)] << 24); + bp2 += 12; + obptr += 4; + } + for (; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + obptr[0] = colorcube[((r & 0xf0) << 4) | + (g & 0xf0) | + (b >> 4)]; + obptr++; + } + } + bptr += rowstride; + obuf += bpl; + } +} +#else +static void +xlib_rgb_convert_8 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + obptr[0] = colorcube[((r & 0xf0) << 4) | + (g & 0xf0) | + (b >> 4)]; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} +#endif + +#if 1 + +/* This dither table was generated by Raph Levien using patented + technology (US Patent 5,276,535). The dither table itself is in the + public domain. */ + +#define DM_WIDTH 128 +#define DM_WIDTH_SHIFT 7 +#define DM_HEIGHT 128 +static const unsigned char DM[128][128] = +{ + { 0, 41, 23, 5, 17, 39, 7, 15, 62, 23, 40, 51, 31, 47, 9, 32, 52, 27, 57, 25, 6, 61, 27, 52, 37, 7, 40, 63, 18, 36, 10, 42, 25, 62, 45, 34, 20, 42, 37, 14, 35, 29, 50, 10, 61, 2, 40, 8, 37, 12, 58, 22, 5, 41, 10, 39, 0, 60, 11, 46, 2, 55, 38, 17, 36, 59, 13, 54, 37, 56, 8, 29, 16, 13, 63, 22, 41, 55, 7, 20, 49, 14, 23, 55, 37, 23, 19, 36, 15, 49, 23, 63, 30, 14, 38, 27, 53, 13, 22, 41, 19, 31, 7, 19, 50, 30, 49, 16, 3, 32, 56, 40, 29, 34, 8, 48, 19, 45, 4, 51, 12, 46, 35, 49, 16, 42, 12, 62 }, + { 30, 57, 36, 54, 47, 34, 52, 27, 43, 4, 28, 7, 17, 36, 62, 13, 44, 7, 18, 48, 33, 21, 44, 14, 30, 47, 12, 33, 5, 55, 31, 58, 13, 30, 4, 17, 52, 10, 60, 26, 46, 0, 39, 27, 42, 22, 47, 25, 60, 32, 9, 38, 48, 17, 59, 30, 49, 18, 34, 25, 51, 19, 5, 48, 21, 8, 28, 46, 1, 32, 41, 19, 54, 47, 37, 18, 28, 11, 44, 30, 39, 56, 2, 33, 8, 42, 61, 28, 58, 8, 46, 9, 41, 4, 58, 7, 21, 48, 59, 10, 52, 14, 42, 57, 12, 25, 7, 53, 42, 24, 11, 50, 17, 59, 42, 2, 36, 60, 32, 17, 63, 29, 21, 7, 59, 32, 24, 39 }, + { 22, 8, 16, 32, 3, 25, 13, 57, 18, 45, 58, 39, 55, 20, 5, 42, 23, 34, 63, 1, 51, 10, 58, 4, 60, 23, 53, 27, 44, 21, 3, 48, 8, 50, 43, 54, 27, 32, 5, 55, 21, 58, 12, 53, 6, 36, 14, 50, 17, 29, 53, 15, 24, 52, 7, 36, 13, 42, 4, 53, 9, 35, 61, 26, 56, 32, 49, 15, 62, 23, 6, 60, 2, 31, 4, 48, 58, 38, 15, 61, 5, 25, 47, 28, 50, 15, 7, 40, 3, 32, 33, 52, 25, 50, 35, 42, 61, 3, 28, 36, 23, 63, 4, 33, 46, 62, 36, 23, 60, 6, 54, 28, 4, 37, 23, 55, 25, 8, 42, 54, 14, 6, 56, 38, 19, 52, 4, 46 }, + { 48, 53, 43, 12, 45, 63, 30, 37, 9, 34, 21, 1, 25, 47, 29, 58, 3, 54, 15, 39, 29, 17, 38, 35, 20, 43, 1, 49, 15, 59, 29, 39, 22, 35, 16, 23, 1, 47, 39, 18, 8, 44, 25, 31, 57, 19, 63, 4, 45, 3, 42, 61, 1, 31, 45, 20, 57, 29, 62, 21, 32, 41, 14, 44, 3, 39, 5, 34, 10, 43, 51, 35, 23, 52, 40, 10, 21, 1, 53, 18, 51, 43, 12, 62, 18, 54, 26, 51, 20, 57, 14, 1, 62, 16, 11, 18, 32, 39, 17, 44, 1, 48, 26, 37, 18, 2, 51, 14, 28, 45, 35, 18, 57, 13, 47, 11, 51, 20, 2, 39, 31, 47, 25, 1, 50, 11, 60, 7 }, + { 18, 28, 1, 56, 21, 10, 51, 2, 46, 54, 14, 61, 11, 50, 13, 38, 19, 31, 45, 9, 55, 24, 47, 5, 54, 9, 62, 11, 35, 8, 51, 14, 57, 6, 63, 40, 58, 14, 51, 28, 62, 34, 15, 48, 1, 41, 30, 35, 55, 21, 34, 11, 49, 37, 8, 52, 4, 23, 15, 43, 1, 58, 11, 23, 53, 16, 55, 26, 58, 18, 27, 12, 45, 14, 25, 63, 42, 33, 27, 35, 9, 31, 21, 38, 1, 44, 34, 12, 48, 38, 21, 44, 29, 47, 26, 53, 1, 46, 54, 8, 59, 29, 11, 55, 22, 41, 33, 20, 39, 1, 48, 9, 44, 32, 5, 62, 29, 44, 57, 23, 10, 58, 34, 43, 15, 37, 26, 33 }, + { 51, 38, 59, 24, 35, 42, 19, 60, 5, 32, 41, 26, 43, 33, 7, 53, 48, 11, 59, 23, 42, 2, 61, 30, 16, 40, 32, 24, 56, 41, 19, 33, 37, 26, 47, 9, 31, 22, 2, 45, 9, 54, 4, 37, 21, 52, 11, 23, 7, 57, 16, 25, 55, 18, 63, 27, 46, 39, 56, 10, 50, 37, 29, 47, 19, 63, 24, 9, 46, 2, 39, 60, 9, 57, 30, 7, 49, 11, 59, 3, 45, 57, 5, 60, 29, 22, 5, 60, 30, 9, 59, 18, 40, 6, 57, 36, 30, 12, 24, 34, 15, 40, 52, 6, 49, 9, 58, 4, 63, 12, 26, 61, 22, 53, 38, 16, 35, 14, 28, 50, 42, 17, 5, 28, 62, 20, 54, 12 }, + { 26, 6, 31, 15, 49, 6, 38, 27, 22, 49, 16, 56, 2, 62, 30, 21, 0, 36, 28, 6, 49, 32, 13, 52, 26, 50, 19, 46, 3, 26, 62, 0, 53, 12, 29, 3, 53, 41, 60, 24, 38, 13, 58, 16, 43, 9, 59, 39, 46, 28, 44, 40, 2, 33, 13, 41, 16, 6, 47, 31, 26, 17, 57, 6, 38, 0, 42, 36, 29, 52, 20, 31, 48, 0, 34, 56, 20, 36, 23, 54, 14, 41, 24, 37, 10, 55, 46, 25, 16, 45, 36, 4, 55, 23, 15, 8, 50, 62, 5, 56, 44, 20, 13, 28, 59, 31, 24, 47, 31, 52, 37, 17, 40, 0, 26, 49, 3, 60, 7, 33, 0, 61, 53, 40, 8, 45, 2, 41 }, + { 16, 63, 43, 4, 61, 24, 56, 13, 53, 8, 36, 12, 24, 41, 16, 46, 60, 26, 52, 39, 14, 57, 21, 37, 0, 45, 7, 59, 38, 17, 43, 10, 45, 20, 61, 43, 19, 11, 33, 17, 50, 32, 23, 61, 28, 49, 26, 0, 18, 51, 5, 60, 22, 58, 29, 0, 59, 34, 19, 62, 3, 52, 7, 44, 30, 59, 13, 50, 15, 62, 7, 17, 38, 22, 44, 15, 40, 4, 47, 28, 33, 17, 49, 16, 51, 40, 10, 56, 0, 53, 13, 49, 28, 38, 60, 21, 43, 19, 37, 27, 3, 51, 34, 39, 0, 45, 15, 43, 10, 21, 3, 55, 8, 33, 59, 10, 41, 18, 52, 24, 46, 20, 30, 13, 58, 22, 36, 57 }, + { 50, 34, 11, 47, 29, 17, 44, 0, 33, 63, 28, 46, 52, 5, 57, 10, 42, 18, 4, 63, 20, 8, 44, 10, 56, 34, 14, 29, 5, 54, 23, 59, 32, 49, 7, 34, 49, 27, 56, 0, 42, 7, 46, 3, 40, 6, 54, 32, 62, 13, 36, 10, 47, 8, 35, 49, 24, 51, 12, 40, 22, 35, 60, 12, 22, 51, 33, 4, 40, 25, 43, 55, 5, 54, 12, 61, 26, 51, 8, 62, 0, 53, 7, 63, 2, 32, 19, 34, 42, 24, 31, 63, 2, 10, 45, 33, 0, 48, 9, 61, 22, 47, 8, 62, 18, 56, 7, 54, 27, 57, 46, 30, 50, 19, 45, 30, 56, 36, 22, 47, 11, 38, 3, 51, 32, 48, 18, 9 }, + { 0, 21, 40, 19, 52, 9, 37, 48, 20, 40, 3, 18, 27, 38, 35, 22, 31, 56, 13, 35, 46, 28, 60, 40, 27, 18, 61, 50, 41, 30, 7, 36, 2, 25, 16, 57, 5, 15, 47, 29, 55, 19, 30, 52, 15, 34, 20, 12, 43, 30, 20, 54, 25, 44, 53, 12, 38, 5, 55, 27, 48, 15, 33, 27, 45, 8, 19, 28, 56, 11, 33, 49, 18, 36, 29, 2, 45, 16, 39, 19, 31, 43, 27, 35, 20, 52, 26, 6, 61, 11, 41, 17, 29, 51, 20, 56, 25, 32, 41, 17, 53, 31, 25, 14, 42, 23, 35, 16, 38, 6, 34, 12, 15, 62, 6, 21, 13, 1, 63, 9, 55, 27, 43, 25, 14, 4, 31, 55 }, + { 44, 29, 61, 2, 35, 58, 26, 15, 60, 10, 51, 59, 14, 55, 8, 50, 2, 44, 25, 51, 1, 33, 16, 4, 48, 36, 2, 21, 12, 57, 48, 13, 51, 55, 40, 28, 37, 62, 8, 39, 12, 63, 36, 10, 59, 24, 56, 47, 9, 50, 41, 1, 32, 17, 6, 21, 61, 30, 9, 43, 1, 54, 41, 2, 54, 37, 48, 61, 1, 46, 21, 3, 58, 24, 50, 32, 60, 10, 57, 25, 46, 12, 59, 4, 45, 13, 57, 47, 27, 39, 5, 58, 47, 14, 35, 4, 52, 13, 60, 6, 36, 10, 45, 55, 4, 50, 29, 2, 61, 50, 25, 58, 44, 24, 36, 42, 54, 28, 40, 32, 16, 56, 6, 62, 46, 39, 60, 23 }, + { 7, 48, 14, 54, 23, 40, 4, 45, 30, 22, 42, 32, 1, 44, 20, 29, 58, 8, 37, 19, 41, 54, 24, 58, 9, 53, 25, 46, 34, 16, 23, 38, 27, 11, 18, 1, 52, 21, 35, 22, 48, 5, 25, 45, 18, 38, 2, 27, 35, 4, 57, 15, 62, 39, 57, 28, 42, 16, 36, 60, 24, 18, 10, 63, 20, 5, 16, 23, 37, 14, 59, 27, 41, 8, 13, 42, 21, 35, 6, 50, 3, 38, 15, 48, 30, 39, 17, 3, 49, 14, 53, 33, 24, 7, 61, 44, 11, 39, 23, 49, 19, 58, 1, 32, 36, 12, 60, 41, 20, 13, 41, 4, 39, 1, 48, 8, 18, 51, 14, 44, 5, 37, 21, 34, 1, 26, 10, 37 }, + { 53, 36, 27, 9, 50, 12, 32, 55, 2, 57, 7, 17, 48, 34, 63, 15, 40, 26, 62, 11, 49, 6, 31, 39, 22, 42, 6, 63, 1, 39, 60, 4, 42, 61, 32, 45, 24, 44, 2, 60, 16, 41, 53, 1, 33, 61, 49, 17, 63, 23, 45, 26, 33, 3, 23, 46, 2, 50, 20, 4, 45, 34, 49, 30, 39, 58, 44, 31, 53, 34, 6, 52, 30, 47, 63, 1, 53, 22, 42, 31, 58, 23, 54, 22, 61, 8, 36, 59, 22, 35, 21, 1, 55, 40, 27, 16, 30, 54, 2, 29, 43, 16, 39, 63, 21, 46, 26, 10, 48, 32, 19, 53, 30, 56, 26, 60, 33, 4, 61, 23, 49, 59, 15, 53, 19, 58, 42, 16 }, + { 20, 5, 59, 46, 25, 62, 7, 19, 43, 25, 37, 61, 11, 24, 4, 54, 12, 52, 3, 32, 17, 61, 12, 47, 15, 55, 18, 31, 53, 28, 9, 50, 21, 6, 55, 9, 58, 14, 54, 26, 33, 7, 31, 58, 13, 21, 8, 42, 29, 6, 37, 11, 48, 52, 14, 60, 11, 39, 56, 32, 14, 58, 7, 26, 17, 4, 42, 8, 11, 47, 19, 38, 10, 17, 26, 37, 9, 55, 28, 13, 18, 40, 6, 33, 1, 43, 25, 11, 51, 7, 62, 43, 18, 37, 3, 57, 45, 9, 38, 58, 5, 52, 27, 7, 17, 53, 5, 57, 37, 2, 63, 9, 22, 15, 11, 38, 25, 45, 35, 0, 28, 10, 41, 30, 50, 8, 31, 57 }, + { 49, 33, 16, 38, 1, 42, 51, 34, 53, 14, 28, 49, 30, 56, 36, 23, 43, 20, 38, 56, 22, 45, 28, 0, 62, 35, 26, 44, 11, 19, 52, 35, 44, 15, 30, 38, 10, 31, 40, 4, 46, 50, 20, 40, 27, 44, 51, 14, 56, 53, 19, 59, 7, 29, 41, 19, 35, 25, 8, 52, 22, 44, 13, 53, 50, 32, 61, 24, 56, 25, 63, 0, 45, 57, 33, 59, 16, 46, 4, 62, 50, 11, 60, 37, 52, 19, 55, 29, 37, 46, 13, 26, 48, 10, 50, 34, 21, 63, 26, 13, 42, 33, 22, 55, 35, 28, 43, 15, 24, 51, 27, 34, 46, 49, 58, 3, 52, 9, 57, 19, 48, 55, 3, 35, 12, 45, 24, 3 }, + { 41, 11, 56, 28, 18, 31, 22, 10, 37, 6, 47, 13, 3, 41, 9, 46, 0, 48, 29, 6, 34, 10, 55, 37, 20, 8, 49, 3, 41, 59, 14, 25, 0, 63, 19, 47, 27, 51, 17, 57, 23, 10, 61, 6, 54, 3, 38, 31, 0, 22, 34, 43, 20, 55, 31, 0, 49, 63, 29, 38, 3, 62, 28, 40, 0, 22, 14, 35, 2, 48, 15, 43, 23, 14, 3, 29, 49, 20, 39, 34, 0, 44, 29, 9, 15, 47, 5, 42, 0, 31, 58, 5, 31, 61, 23, 15, 0, 47, 19, 50, 24, 3, 59, 11, 44, 0, 31, 59, 6, 42, 17, 60, 0, 39, 20, 31, 43, 17, 29, 40, 12, 25, 60, 22, 52, 15, 63, 29 }, + { 20, 52, 8, 44, 62, 4, 59, 49, 17, 63, 21, 39, 60, 18, 52, 27, 33, 59, 14, 51, 59, 43, 24, 5, 51, 30, 57, 17, 32, 5, 37, 56, 48, 34, 42, 3, 60, 5, 36, 13, 43, 37, 18, 34, 25, 12, 59, 24, 47, 36, 11, 50, 3, 38, 9, 58, 16, 5, 43, 18, 47, 10, 37, 18, 59, 46, 29, 52, 40, 12, 34, 28, 56, 36, 53, 7, 43, 8, 24, 52, 26, 17, 56, 43, 24, 32, 63, 20, 57, 16, 22, 52, 36, 8, 41, 56, 29, 32, 54, 7, 35, 57, 14, 48, 20, 62, 13, 39, 53, 29, 8, 45, 13, 29, 7, 61, 14, 54, 6, 63, 38, 32, 18, 43, 2, 39, 6, 47 }, + { 0, 58, 23, 35, 13, 46, 12, 39, 0, 31, 55, 24, 5, 35, 15, 61, 17, 5, 39, 25, 18, 2, 50, 33, 41, 13, 39, 23, 62, 46, 29, 12, 22, 8, 56, 25, 20, 49, 32, 62, 0, 56, 11, 46, 63, 42, 9, 16, 55, 5, 60, 15, 62, 26, 45, 21, 36, 51, 13, 57, 31, 24, 55, 6, 35, 9, 57, 5, 20, 60, 7, 51, 5, 19, 40, 25, 61, 32, 56, 12, 36, 48, 21, 2, 58, 12, 39, 28, 9, 50, 40, 12, 44, 18, 25, 49, 6, 38, 11, 62, 18, 46, 30, 9, 40, 25, 49, 19, 10, 36, 55, 22, 33, 52, 41, 18, 37, 27, 49, 21, 2, 46, 7, 53, 33, 61, 27, 35 }, + { 41, 31, 5, 39, 51, 26, 33, 57, 27, 41, 9, 44, 54, 29, 48, 7, 44, 36, 57, 10, 31, 63, 16, 45, 11, 60, 1, 47, 7, 20, 43, 3, 58, 36, 13, 52, 39, 7, 15, 28, 22, 48, 30, 21, 1, 29, 49, 44, 27, 17, 40, 30, 24, 42, 12, 53, 33, 7, 47, 20, 1, 42, 11, 49, 25, 43, 17, 32, 45, 27, 41, 21, 31, 62, 11, 49, 2, 15, 42, 5, 63, 7, 41, 27, 49, 6, 54, 23, 46, 34, 2, 28, 54, 3, 59, 12, 46, 17, 42, 28, 40, 1, 37, 51, 5, 55, 2, 34, 47, 16, 3, 62, 47, 5, 23, 56, 1, 44, 12, 34, 51, 16, 57, 11, 25, 17, 54, 13 }, + { 60, 26, 55, 18, 3, 60, 20, 6, 52, 15, 50, 19, 32, 11, 23, 53, 26, 21, 1, 47, 42, 27, 8, 58, 21, 27, 53, 36, 26, 54, 31, 50, 17, 30, 45, 1, 29, 59, 44, 53, 41, 4, 35, 58, 51, 19, 32, 4, 52, 34, 48, 8, 51, 5, 56, 2, 25, 61, 27, 38, 54, 27, 62, 21, 51, 1, 39, 62, 10, 50, 1, 58, 13, 47, 38, 18, 35, 54, 22, 51, 30, 19, 59, 34, 14, 32, 44, 4, 60, 15, 52, 62, 20, 43, 30, 35, 21, 60, 4, 52, 12, 24, 61, 18, 30, 42, 23, 61, 25, 50, 27, 38, 11, 59, 12, 35, 50, 30, 59, 24, 8, 42, 28, 37, 48, 9, 44, 21 }, + { 10, 47, 15, 50, 30, 43, 8, 45, 29, 2, 36, 59, 1, 58, 41, 3, 63, 31, 54, 20, 13, 55, 35, 38, 4, 44, 15, 9, 61, 2, 14, 38, 61, 10, 23, 54, 18, 12, 24, 2, 14, 55, 16, 8, 38, 14, 41, 60, 10, 23, 1, 58, 32, 17, 28, 37, 41, 15, 3, 60, 15, 33, 4, 36, 16, 59, 28, 14, 23, 55, 37, 18, 44, 28, 2, 57, 30, 10, 27, 46, 14, 38, 3, 53, 21, 61, 17, 35, 10, 41, 26, 7, 33, 9, 57, 1, 53, 37, 26, 20, 56, 48, 9, 33, 58, 16, 37, 7, 45, 1, 57, 15, 32, 26, 42, 23, 7, 20, 4, 54, 31, 62, 22, 1, 59, 30, 4, 51 }, + { 36, 2, 38, 11, 24, 36, 54, 22, 62, 47, 25, 8, 28, 45, 16, 38, 12, 43, 9, 37, 49, 3, 23, 52, 18, 30, 50, 33, 19, 42, 49, 26, 6, 40, 47, 35, 63, 38, 50, 33, 60, 26, 36, 47, 24, 57, 6, 26, 39, 63, 19, 44, 14, 46, 61, 9, 50, 30, 45, 23, 10, 50, 44, 8, 31, 54, 6, 46, 36, 4, 30, 54, 8, 52, 22, 41, 4, 60, 40, 0, 58, 24, 45, 10, 37, 1, 48, 30, 56, 17, 38, 48, 24, 47, 19, 39, 14, 8, 45, 32, 2, 34, 27, 44, 4, 52, 11, 56, 31, 21, 40, 19, 44, 51, 2, 63, 46, 58, 36, 43, 14, 5, 50, 38, 14, 56, 40, 23 }, + { 61, 46, 32, 63, 54, 1, 14, 34, 12, 40, 18, 49, 37, 10, 61, 30, 51, 24, 60, 7, 29, 40, 62, 11, 46, 58, 6, 56, 24, 10, 34, 52, 21, 59, 16, 3, 27, 5, 20, 46, 9, 40, 7, 62, 2, 30, 53, 15, 48, 10, 28, 35, 54, 6, 21, 34, 18, 55, 7, 40, 57, 19, 26, 60, 41, 13, 24, 51, 19, 61, 9, 25, 34, 15, 63, 11, 45, 17, 20, 47, 33, 8, 31, 62, 43, 26, 53, 7, 24, 59, 0, 13, 55, 4, 62, 27, 51, 31, 63, 15, 58, 7, 54, 14, 46, 22, 28, 43, 12, 63, 8, 54, 5, 17, 39, 33, 15, 10, 27, 17, 47, 34, 19, 45, 27, 12, 33, 17 }, + { 5, 28, 21, 7, 17, 48, 42, 58, 23, 4, 63, 14, 55, 21, 34, 5, 19, 0, 45, 17, 52, 15, 25, 32, 0, 22, 40, 13, 45, 62, 18, 0, 43, 11, 33, 55, 30, 42, 57, 19, 51, 31, 22, 43, 18, 45, 34, 0, 43, 31, 56, 3, 23, 40, 59, 0, 44, 13, 48, 35, 2, 32, 46, 0, 21, 48, 35, 3, 40, 32, 43, 59, 0, 48, 33, 26, 53, 36, 55, 12, 51, 16, 55, 5, 18, 29, 11, 39, 51, 19, 45, 31, 42, 21, 35, 6, 22, 47, 10, 38, 23, 50, 20, 36, 0, 60, 38, 4, 50, 35, 48, 34, 24, 57, 9, 53, 28, 48, 61, 0, 56, 24, 53, 3, 63, 6, 42, 57 }, + { 13, 53, 45, 40, 58, 27, 6, 16, 38, 51, 33, 30, 43, 2, 47, 56, 40, 50, 33, 57, 27, 5, 47, 42, 60, 36, 16, 54, 28, 4, 37, 57, 28, 51, 22, 8, 45, 14, 6, 39, 0, 54, 11, 59, 28, 12, 50, 21, 61, 13, 19, 38, 49, 11, 25, 37, 58, 29, 22, 63, 14, 56, 12, 53, 30, 63, 9, 57, 26, 12, 47, 16, 23, 39, 50, 6, 31, 2, 25, 6, 28, 41, 36, 22, 50, 57, 42, 3, 34, 8, 28, 61, 11, 50, 16, 54, 41, 0, 55, 43, 5, 29, 41, 63, 25, 16, 53, 18, 26, 10, 21, 0, 61, 30, 41, 22, 3, 38, 20, 39, 29, 8, 41, 16, 36, 52, 22, 19 }, + { 55, 34, 0, 25, 10, 32, 56, 44, 28, 0, 57, 7, 26, 53, 23, 8, 13, 35, 22, 12, 36, 60, 20, 8, 14, 29, 48, 2, 41, 49, 23, 13, 39, 7, 48, 58, 25, 53, 34, 62, 28, 16, 48, 4, 37, 56, 27, 5, 36, 52, 46, 7, 62, 33, 52, 11, 17, 53, 5, 28, 41, 24, 38, 17, 5, 39, 20, 45, 15, 56, 5, 38, 60, 8, 14, 57, 21, 48, 62, 39, 59, 13, 1, 60, 9, 32, 16, 63, 44, 25, 52, 15, 36, 2, 60, 29, 12, 33, 25, 17, 59, 45, 13, 8, 49, 32, 6, 40, 59, 29, 45, 37, 13, 47, 6, 55, 30, 45, 9, 52, 13, 59, 25, 47, 32, 1, 49, 30 }, + { 9, 39, 14, 61, 49, 37, 3, 20, 50, 13, 41, 19, 46, 17, 38, 59, 28, 62, 4, 44, 54, 1, 34, 51, 55, 7, 63, 32, 21, 8, 56, 31, 62, 19, 36, 1, 41, 17, 24, 12, 42, 35, 25, 52, 20, 8, 44, 59, 25, 2, 22, 42, 16, 29, 4, 46, 20, 36, 43, 9, 51, 8, 49, 26, 58, 33, 54, 1, 37, 29, 52, 20, 27, 45, 19, 35, 42, 16, 10, 32, 20, 49, 46, 27, 40, 4, 47, 22, 13, 55, 4, 47, 26, 44, 23, 40, 58, 19, 48, 13, 31, 2, 57, 34, 42, 19, 61, 32, 14, 55, 5, 51, 26, 19, 58, 16, 49, 14, 62, 5, 33, 44, 21, 7, 60, 26, 11, 41 }, + { 62, 24, 47, 29, 8, 19, 53, 11, 60, 24, 32, 61, 4, 55, 31, 2, 49, 16, 39, 9, 31, 24, 43, 17, 26, 38, 11, 25, 58, 43, 12, 35, 3, 46, 15, 32, 63, 4, 49, 56, 2, 60, 10, 32, 63, 17, 39, 12, 55, 30, 57, 9, 48, 55, 39, 24, 60, 2, 58, 31, 19, 61, 34, 3, 42, 11, 22, 46, 7, 61, 10, 42, 3, 55, 32, 1, 58, 28, 44, 54, 4, 34, 23, 15, 56, 20, 37, 58, 6, 30, 38, 18, 63, 9, 32, 5, 51, 3, 62, 37, 52, 18, 39, 23, 3, 51, 9, 47, 1, 23, 43, 15, 60, 35, 11, 40, 1, 36, 31, 26, 57, 2, 37, 54, 18, 44, 58, 16 }, + { 5, 51, 3, 33, 43, 62, 21, 42, 35, 9, 48, 15, 36, 10, 22, 42, 20, 46, 26, 56, 50, 12, 59, 3, 48, 19, 45, 53, 1, 27, 47, 17, 52, 24, 56, 11, 51, 21, 37, 30, 20, 46, 14, 41, 1, 47, 33, 7, 41, 17, 35, 27, 20, 1, 14, 54, 26, 33, 18, 47, 1, 44, 14, 59, 16, 52, 28, 18, 49, 31, 25, 34, 63, 13, 51, 24, 9, 50, 3, 23, 38, 63, 7, 52, 29, 46, 11, 33, 50, 22, 57, 36, 1, 57, 49, 17, 39, 28, 9, 35, 6, 27, 53, 15, 55, 30, 24, 58, 36, 41, 11, 52, 32, 3, 44, 25, 62, 23, 51, 15, 42, 22, 50, 10, 39, 4, 31, 35 }, + { 46, 22, 57, 17, 12, 39, 26, 5, 31, 59, 1, 45, 27, 62, 52, 7, 58, 33, 6, 18, 39, 22, 33, 41, 57, 5, 35, 18, 40, 16, 60, 5, 29, 42, 7, 39, 27, 44, 9, 47, 8, 26, 54, 22, 51, 29, 24, 49, 15, 61, 4, 51, 31, 63, 43, 6, 50, 8, 39, 12, 53, 37, 23, 30, 40, 6, 62, 43, 14, 53, 2, 49, 7, 36, 17, 41, 61, 37, 18, 56, 11, 18, 44, 35, 2, 19, 61, 0, 41, 14, 8, 30, 43, 12, 24, 46, 14, 54, 42, 21, 44, 61, 10, 46, 37, 11, 44, 7, 18, 63, 20, 29, 7, 49, 28, 54, 8, 43, 4, 48, 18, 63, 12, 29, 48, 24, 59, 20 }, + { 13, 36, 28, 54, 35, 2, 56, 46, 16, 49, 22, 40, 11, 34, 14, 43, 29, 12, 63, 48, 2, 61, 7, 15, 28, 30, 50, 9, 61, 33, 38, 23, 54, 13, 61, 33, 3, 59, 16, 35, 58, 40, 5, 38, 13, 57, 3, 58, 37, 21, 45, 12, 39, 7, 35, 30, 13, 56, 22, 62, 27, 6, 55, 10, 48, 21, 33, 2, 38, 23, 40, 20, 44, 29, 59, 4, 26, 12, 33, 47, 28, 53, 31, 13, 59, 41, 27, 49, 26, 54, 45, 16, 53, 21, 35, 7, 59, 26, 11, 56, 1, 24, 33, 4, 28, 62, 21, 49, 31, 2, 56, 39, 24, 58, 13, 17, 37, 21, 56, 10, 38, 0, 34, 55, 15, 43, 1, 52 }, + { 42, 9, 50, 6, 25, 60, 14, 38, 10, 29, 53, 18, 57, 3, 25, 51, 0, 53, 25, 17, 29, 37, 52, 46, 0, 62, 14, 37, 4, 50, 10, 44, 0, 46, 20, 25, 50, 19, 55, 0, 23, 31, 62, 34, 11, 45, 19, 32, 0, 53, 10, 59, 23, 47, 18, 60, 42, 28, 37, 3, 50, 15, 35, 44, 0, 51, 27, 60, 9, 57, 16, 58, 11, 22, 46, 15, 53, 48, 7, 42, 0, 60, 5, 49, 24, 54, 9, 17, 39, 5, 34, 62, 3, 40, 60, 31, 0, 47, 29, 16, 49, 39, 59, 17, 50, 0, 40, 13, 53, 38, 16, 46, 0, 42, 34, 60, 2, 53, 29, 31, 58, 46, 27, 6, 61, 8, 37, 28 }, + { 0, 63, 21, 40, 45, 18, 51, 23, 63, 34, 6, 43, 28, 38, 55, 19, 40, 35, 8, 41, 54, 10, 21, 32, 39, 23, 53, 26, 55, 28, 22, 63, 30, 34, 9, 48, 6, 38, 29, 43, 49, 6, 18, 52, 27, 61, 9, 43, 28, 42, 33, 26, 56, 3, 51, 23, 0, 48, 16, 45, 32, 25, 63, 20, 57, 17, 42, 12, 35, 47, 5, 31, 39, 56, 6, 30, 34, 21, 61, 25, 14, 40, 22, 38, 15, 6, 36, 56, 20, 60, 25, 12, 51, 27, 10, 56, 42, 20, 36, 63, 32, 6, 21, 41, 12, 34, 60, 26, 5, 48, 27, 10, 62, 19, 6, 47, 39, 14, 45, 7, 24, 17, 41, 32, 23, 51, 19, 56 }, + { 45, 31, 15, 59, 4, 33, 7, 47, 0, 41, 13, 61, 4, 47, 9, 23, 60, 14, 57, 31, 4, 45, 59, 6, 58, 10, 44, 20, 8, 42, 15, 6, 55, 17, 58, 31, 53, 12, 61, 10, 15, 57, 43, 2, 23, 35, 48, 14, 54, 6, 18, 49, 15, 38, 11, 34, 62, 9, 21, 58, 11, 41, 4, 31, 38, 8, 29, 55, 19, 36, 27, 52, 0, 25, 50, 43, 1, 39, 8, 55, 35, 51, 10, 30, 45, 62, 29, 2, 46, 10, 32, 48, 18, 38, 5, 22, 33, 8, 51, 3, 14, 44, 54, 25, 57, 30, 18, 52, 33, 22, 59, 28, 36, 52, 32, 21, 26, 50, 5, 55, 35, 60, 14, 54, 4, 40, 16, 33 }, + { 27, 3, 49, 10, 30, 40, 55, 27, 57, 24, 52, 21, 32, 17, 60, 30, 5, 44, 27, 49, 19, 34, 13, 24, 43, 36, 3, 49, 31, 59, 37, 48, 26, 41, 2, 41, 14, 36, 21, 32, 40, 26, 13, 49, 55, 5, 16, 40, 25, 60, 36, 1, 63, 29, 17, 44, 25, 40, 52, 5, 29, 47, 54, 13, 46, 24, 60, 4, 51, 22, 63, 14, 45, 18, 12, 62, 17, 57, 19, 42, 3, 26, 58, 48, 1, 21, 40, 52, 23, 37, 44, 1, 29, 58, 43, 50, 15, 61, 19, 45, 58, 28, 7, 48, 2, 46, 8, 42, 3, 55, 8, 50, 12, 4, 55, 10, 63, 33, 20, 40, 11, 3, 46, 20, 48, 26, 61, 11 }, + { 44, 56, 24, 36, 53, 19, 12, 37, 16, 44, 7, 36, 49, 54, 11, 37, 48, 21, 15, 1, 62, 25, 47, 56, 16, 18, 51, 12, 40, 1, 24, 11, 52, 16, 23, 59, 28, 1, 45, 53, 4, 60, 37, 21, 39, 30, 63, 20, 52, 10, 30, 45, 8, 41, 54, 4, 57, 7, 34, 55, 36, 18, 23, 59, 2, 48, 11, 32, 44, 1, 41, 8, 33, 54, 38, 23, 30, 46, 6, 29, 62, 18, 32, 16, 55, 34, 14, 11, 61, 7, 55, 16, 53, 13, 23, 2, 55, 37, 26, 10, 33, 23, 36, 16, 38, 22, 56, 15, 24, 43, 35, 17, 44, 40, 25, 46, 16, 1, 57, 25, 49, 36, 28, 62, 9, 35, 7, 53 }, + { 17, 38, 8, 61, 1, 50, 26, 62, 3, 31, 56, 15, 1, 26, 40, 2, 34, 51, 56, 36, 42, 9, 38, 2, 29, 60, 32, 57, 19, 62, 34, 47, 4, 57, 39, 7, 44, 63, 24, 18, 46, 28, 8, 54, 1, 34, 7, 46, 3, 37, 50, 23, 57, 21, 13, 46, 31, 20, 43, 15, 1, 61, 8, 33, 37, 17, 56, 26, 15, 49, 24, 59, 28, 3, 56, 9, 52, 32, 13, 49, 10, 43, 5, 45, 8, 25, 59, 42, 28, 33, 19, 40, 8, 63, 35, 47, 25, 4, 40, 52, 1, 60, 12, 53, 63, 9, 29, 60, 37, 19, 1, 62, 31, 20, 58, 12, 41, 30, 43, 9, 18, 52, 22, 1, 39, 30, 58, 21 }, + { 13, 47, 29, 18, 43, 34, 5, 48, 20, 42, 10, 45, 30, 58, 20, 63, 24, 11, 6, 28, 54, 14, 22, 52, 41, 7, 26, 5, 45, 15, 53, 13, 35, 27, 18, 50, 12, 33, 5, 56, 10, 17, 45, 24, 59, 15, 50, 26, 56, 13, 19, 5, 32, 52, 27, 36, 2, 61, 12, 26, 49, 40, 27, 52, 13, 50, 6, 39, 61, 34, 10, 37, 48, 20, 41, 27, 2, 36, 59, 24, 54, 33, 63, 20, 38, 50, 3, 17, 52, 4, 58, 27, 45, 21, 32, 11, 48, 17, 57, 20, 46, 38, 25, 43, 4, 34, 51, 6, 13, 45, 57, 26, 6, 48, 2, 35, 53, 23, 61, 34, 59, 6, 42, 56, 13, 51, 2, 41 }, + { 32, 5, 55, 23, 58, 14, 22, 52, 29, 15, 61, 25, 51, 8, 43, 13, 53, 41, 46, 20, 3, 33, 63, 11, 48, 21, 54, 38, 28, 3, 30, 43, 21, 62, 9, 31, 55, 22, 51, 29, 37, 62, 32, 12, 42, 29, 41, 9, 33, 44, 62, 28, 43, 1, 59, 19, 48, 30, 51, 39, 24, 4, 58, 19, 42, 29, 22, 43, 3, 18, 53, 5, 13, 50, 16, 60, 45, 21, 7, 40, 15, 0, 26, 53, 13, 31, 43, 24, 47, 31, 15, 49, 2, 41, 6, 59, 29, 42, 9, 30, 14, 7, 49, 18, 31, 47, 20, 39, 49, 32, 11, 41, 54, 15, 61, 18, 7, 38, 4, 13, 44, 28, 15, 32, 45, 19, 27, 49 }, + { 63, 34, 11, 39, 2, 45, 37, 8, 59, 39, 33, 4, 36, 17, 48, 5, 29, 18, 32, 61, 39, 50, 5, 27, 35, 0, 46, 12, 22, 49, 60, 6, 54, 0, 38, 49, 2, 42, 15, 40, 0, 47, 20, 51, 3, 57, 18, 61, 22, 0, 39, 16, 55, 12, 35, 8, 41, 22, 6, 59, 16, 45, 10, 36, 0, 62, 9, 54, 30, 58, 21, 43, 63, 31, 7, 35, 12, 48, 58, 28, 47, 37, 41, 9, 57, 20, 61, 0, 36, 11, 57, 35, 23, 52, 37, 18, 0, 62, 22, 55, 35, 62, 27, 54, 0, 15, 61, 28, 2, 59, 22, 9, 37, 27, 33, 51, 29, 48, 19, 50, 25, 37, 10, 57, 5, 37, 60, 8 }, + { 20, 25, 46, 52, 31, 60, 12, 55, 0, 19, 11, 46, 62, 35, 23, 38, 57, 0, 55, 10, 16, 30, 58, 44, 17, 59, 29, 63, 42, 8, 36, 20, 33, 46, 16, 61, 25, 35, 8, 54, 26, 7, 58, 22, 34, 6, 47, 14, 53, 31, 48, 9, 37, 25, 49, 63, 16, 55, 45, 14, 34, 63, 21, 53, 25, 33, 46, 16, 35, 7, 46, 29, 0, 39, 25, 55, 22, 34, 18, 4, 56, 11, 23, 51, 28, 6, 39, 14, 62, 44, 19, 8, 60, 12, 56, 28, 50, 34, 39, 5, 51, 3, 41, 12, 57, 35, 10, 53, 25, 17, 52, 30, 47, 0, 43, 14, 5, 57, 31, 55, 0, 63, 47, 23, 54, 24, 14, 43 }, + { 0, 57, 16, 6, 26, 19, 35, 28, 49, 42, 54, 26, 21, 1, 59, 27, 9, 47, 26, 44, 50, 22, 13, 40, 8, 37, 10, 34, 17, 56, 25, 58, 13, 27, 44, 9, 20, 58, 31, 17, 60, 36, 10, 41, 53, 25, 36, 39, 4, 24, 58, 17, 60, 4, 22, 38, 10, 32, 0, 50, 31, 7, 28, 47, 12, 57, 5, 26, 52, 23, 14, 40, 57, 17, 47, 5, 53, 1, 44, 31, 19, 60, 46, 2, 35, 48, 30, 54, 22, 5, 51, 39, 25, 31, 4, 43, 14, 9, 45, 16, 24, 44, 19, 29, 40, 23, 44, 7, 38, 42, 4, 63, 12, 54, 23, 59, 22, 42, 8, 15, 40, 21, 8, 34, 3, 41, 30, 50 }, + { 39, 10, 48, 33, 41, 54, 5, 47, 23, 13, 32, 7, 52, 44, 14, 39, 58, 18, 35, 6, 37, 2, 60, 24, 55, 19, 53, 2, 51, 32, 1, 41, 51, 4, 40, 29, 47, 3, 52, 44, 13, 49, 28, 16, 1, 62, 11, 27, 52, 35, 5, 42, 29, 47, 14, 56, 28, 53, 26, 38, 9, 56, 40, 3, 38, 15, 41, 60, 1, 37, 50, 25, 11, 28, 61, 19, 42, 62, 10, 52, 39, 6, 32, 14, 58, 17, 7, 26, 42, 34, 27, 10, 54, 40, 20, 63, 26, 53, 21, 61, 32, 7, 59, 48, 3, 56, 18, 31, 58, 14, 49, 21, 36, 16, 45, 9, 36, 24, 62, 45, 27, 31, 53, 17, 49, 12, 62, 18 }, + { 28, 59, 21, 58, 2, 16, 38, 9, 62, 3, 56, 41, 10, 31, 50, 4, 32, 52, 12, 63, 23, 46, 33, 31, 4, 48, 25, 43, 14, 23, 47, 11, 22, 55, 14, 60, 23, 37, 11, 39, 23, 2, 45, 56, 31, 43, 19, 55, 16, 46, 21, 51, 11, 33, 44, 2, 41, 18, 5, 52, 23, 44, 17, 60, 27, 49, 11, 32, 44, 10, 54, 2, 56, 33, 8, 38, 13, 29, 36, 16, 24, 63, 27, 51, 21, 43, 56, 12, 49, 3, 59, 48, 1, 15, 46, 7, 36, 2, 47, 11, 50, 27, 37, 13, 33, 8, 51, 46, 1, 34, 28, 40, 3, 33, 60, 29, 47, 1, 35, 11, 59, 42, 2, 60, 26, 46, 6, 35 }, + { 4, 43, 9, 29, 36, 63, 24, 44, 20, 50, 30, 17, 60, 22, 16, 43, 25, 3, 42, 19, 51, 15, 8, 54, 42, 15, 61, 5, 39, 57, 18, 61, 31, 48, 34, 2, 50, 19, 57, 5, 63, 33, 19, 38, 13, 27, 48, 7, 32, 61, 2, 26, 58, 6, 24, 50, 13, 61, 42, 20, 62, 2, 35, 20, 51, 4, 62, 18, 23, 58, 20, 31, 43, 15, 51, 45, 26, 50, 4, 55, 45, 3, 35, 9, 38, 1, 32, 61, 20, 45, 17, 33, 24, 57, 29, 51, 22, 58, 38, 30, 15, 1, 54, 21, 63, 43, 26, 12, 24, 56, 8, 60, 50, 19, 5, 52, 13, 54, 17, 50, 4, 16, 36, 12, 32, 56, 22, 54 }, + { 51, 25, 40, 53, 12, 49, 15, 57, 34, 7, 38, 47, 2, 36, 55, 8, 61, 30, 56, 7, 28, 59, 48, 11, 27, 35, 21, 45, 28, 36, 9, 38, 6, 16, 24, 63, 10, 32, 28, 43, 21, 53, 5, 60, 8, 57, 3, 45, 11, 37, 15, 54, 40, 20, 62, 36, 27, 34, 11, 48, 30, 15, 54, 8, 30, 42, 22, 34, 48, 13, 35, 63, 4, 37, 22, 2, 59, 9, 41, 23, 13, 41, 49, 18, 59, 24, 40, 5, 37, 30, 9, 61, 44, 6, 37, 11, 33, 17, 5, 55, 41, 60, 23, 39, 17, 5, 30, 62, 41, 16, 46, 25, 11, 56, 39, 26, 20, 38, 29, 39, 22, 52, 44, 20, 48, 1, 38, 14 }, + { 15, 33, 2, 18, 44, 6, 27, 0, 32, 61, 25, 12, 58, 28, 40, 20, 47, 13, 34, 43, 38, 1, 23, 62, 40, 0, 51, 10, 63, 3, 52, 26, 44, 30, 45, 6, 41, 54, 0, 51, 12, 30, 46, 24, 49, 22, 40, 33, 63, 23, 43, 30, 9, 47, 0, 17, 54, 7, 57, 3, 37, 47, 24, 46, 13, 55, 7, 52, 2, 42, 6, 26, 49, 18, 60, 34, 16, 57, 33, 20, 61, 30, 8, 54, 14, 46, 12, 53, 16, 55, 38, 13, 22, 53, 18, 59, 46, 27, 43, 19, 32, 10, 45, 6, 49, 36, 52, 2, 20, 55, 6, 39, 32, 15, 44, 3, 58, 10, 63, 6, 56, 30, 7, 58, 9, 40, 19, 63 }, + { 10, 47, 61, 23, 55, 31, 52, 42, 17, 45, 4, 51, 27, 6, 15, 53, 0, 49, 26, 10, 56, 18, 36, 6, 20, 58, 32, 30, 13, 49, 19, 56, 0, 59, 12, 53, 27, 17, 38, 25, 48, 9, 15, 36, 14, 30, 59, 17, 0, 50, 8, 58, 18, 56, 31, 45, 21, 41, 29, 19, 60, 6, 32, 59, 0, 36, 29, 39, 19, 59, 46, 12, 55, 30, 10, 47, 24, 3, 28, 48, 0, 55, 44, 27, 33, 4, 63, 29, 49, 0, 26, 50, 34, 2, 42, 14, 0, 62, 9, 56, 3, 52, 28, 34, 58, 9, 20, 48, 37, 32, 22, 53, 0, 62, 27, 49, 34, 46, 21, 33, 41, 14, 25, 37, 53, 29, 31, 45 }, + { 56, 28, 7, 37, 11, 36, 20, 9, 54, 14, 39, 19, 34, 63, 45, 37, 24, 17, 60, 31, 21, 45, 53, 29, 47, 15, 7, 55, 40, 23, 34, 14, 42, 20, 37, 35, 15, 59, 7, 62, 34, 40, 59, 1, 51, 42, 10, 28, 54, 21, 35, 5, 38, 13, 36, 4, 59, 12, 39, 53, 15, 43, 9, 21, 39, 62, 16, 56, 25, 9, 32, 38, 0, 41, 14, 51, 40, 53, 43, 11, 37, 17, 5, 22, 57, 39, 19, 7, 42, 21, 60, 10, 31, 63, 25, 52, 30, 49, 36, 25, 48, 17, 61, 14, 22, 42, 29, 13, 60, 11, 47, 18, 35, 41, 7, 23, 4, 16, 51, 11, 0, 48, 61, 3, 17, 50, 5, 24 }, + { 0, 42, 21, 49, 60, 3, 57, 40, 29, 48, 23, 56, 42, 11, 22, 5, 59, 39, 4, 50, 3, 41, 12, 57, 25, 50, 44, 18, 4, 46, 7, 62, 33, 50, 4, 56, 21, 32, 43, 18, 3, 23, 55, 34, 20, 4, 53, 38, 12, 46, 29, 52, 25, 61, 23, 51, 26, 46, 1, 34, 25, 57, 28, 51, 26, 11, 50, 3, 44, 28, 53, 21, 57, 27, 62, 6, 31, 19, 8, 63, 26, 59, 36, 47, 15, 29, 50, 25, 35, 47, 18, 41, 4, 48, 8, 40, 12, 23, 6, 44, 13, 40, 1, 31, 55, 0, 61, 43, 4, 50, 26, 58, 9, 53, 24, 61, 42, 55, 31, 43, 57, 20, 34, 27, 43, 8, 59, 39 }, + { 18, 51, 30, 13, 26, 16, 46, 22, 2, 59, 8, 30, 1, 48, 33, 51, 29, 9, 46, 16, 62, 14, 33, 2, 38, 9, 27, 60, 37, 26, 53, 17, 28, 10, 24, 46, 2, 49, 8, 57, 29, 45, 6, 26, 62, 44, 18, 25, 61, 3, 42, 14, 49, 10, 43, 6, 17, 32, 63, 10, 49, 4, 40, 14, 45, 33, 22, 37, 12, 61, 5, 17, 43, 7, 23, 37, 15, 58, 49, 13, 39, 21, 10, 52, 1, 62, 9, 56, 12, 2, 58, 28, 36, 16, 56, 28, 56, 35, 20, 63, 24, 37, 51, 8, 45, 25, 16, 33, 27, 38, 2, 44, 13, 30, 17, 36, 12, 26, 5, 18, 28, 47, 13, 60, 23, 45, 13, 33 }, + { 55, 4, 62, 34, 52, 38, 7, 63, 32, 37, 13, 53, 25, 62, 18, 12, 55, 41, 27, 35, 24, 49, 31, 52, 17, 63, 34, 1, 56, 12, 41, 2, 48, 58, 39, 16, 61, 27, 41, 52, 13, 19, 50, 39, 11, 31, 57, 6, 32, 40, 20, 55, 1, 28, 33, 57, 48, 8, 37, 22, 44, 18, 53, 1, 61, 5, 54, 16, 47, 36, 50, 24, 55, 34, 48, 45, 1, 30, 33, 46, 2, 50, 32, 42, 25, 34, 43, 21, 38, 52, 23, 45, 14, 54, 21, 4, 44, 16, 53, 29, 10, 47, 19, 57, 12, 54, 39, 10, 51, 15, 63, 21, 57, 40, 51, 1, 48, 57, 37, 62, 2, 38, 9, 52, 1, 35, 58, 22 }, + { 36, 46, 10, 42, 1, 27, 43, 15, 50, 21, 45, 16, 41, 3, 35, 44, 20, 1, 57, 11, 55, 7, 43, 8, 22, 42, 13, 46, 21, 39, 31, 60, 22, 5, 29, 44, 11, 35, 20, 4, 36, 58, 32, 15, 47, 2, 36, 48, 16, 60, 8, 35, 44, 63, 16, 2, 40, 26, 55, 14, 58, 35, 24, 31, 19, 42, 31, 58, 1, 29, 10, 40, 2, 19, 12, 54, 22, 61, 7, 24, 56, 5, 28, 16, 54, 3, 15, 58, 6, 30, 8, 62, 1, 43, 31, 47, 7, 59, 1, 38, 58, 4, 34, 27, 38, 5, 31, 59, 7, 46, 30, 3, 34, 6, 28, 59, 20, 8, 32, 15, 53, 24, 55, 31, 19, 49, 11, 26 }, + { 2, 24, 16, 58, 19, 55, 5, 35, 10, 61, 4, 28, 57, 24, 58, 7, 31, 47, 22, 38, 19, 28, 61, 36, 54, 5, 59, 29, 6, 52, 15, 11, 43, 36, 8, 54, 52, 1, 62, 25, 47, 9, 1, 60, 28, 53, 24, 14, 46, 27, 51, 22, 12, 24, 38, 53, 20, 11, 51, 3, 29, 7, 48, 63, 8, 49, 9, 21, 52, 14, 63, 32, 46, 60, 35, 4, 41, 16, 52, 35, 18, 42, 59, 7, 36, 61, 45, 27, 33, 51, 19, 39, 34, 11, 61, 18, 33, 41, 28, 15, 54, 22, 42, 3, 49, 21, 47, 18, 36, 23, 55, 19, 48, 24, 45, 10, 33, 44, 50, 40, 7, 35, 15, 41, 63, 6, 40, 54 }, + { 62, 41, 32, 8, 47, 28, 60, 24, 44, 30, 38, 49, 9, 33, 14, 40, 50, 14, 60, 2, 54, 40, 0, 20, 25, 39, 16, 49, 24, 35, 57, 47, 19, 61, 33, 18, 23, 37, 13, 55, 31, 43, 22, 41, 17, 8, 42, 58, 0, 37, 5, 56, 31, 54, 7, 30, 60, 33, 42, 17, 59, 39, 12, 27, 38, 17, 35, 41, 27, 45, 20, 7, 25, 15, 29, 58, 27, 47, 11, 40, 14, 54, 23, 46, 19, 31, 11, 40, 13, 49, 5, 58, 24, 51, 26, 6, 50, 20, 49, 9, 32, 46, 17, 60, 14, 63, 24, 1, 57, 41, 9, 43, 14, 62, 16, 52, 3, 27, 14, 22, 61, 45, 4, 28, 9, 47, 29, 17 }, + { 5, 50, 12, 53, 38, 18, 11, 51, 0, 55, 17, 6, 47, 54, 19, 63, 5, 26, 34, 45, 13, 30, 47, 58, 10, 48, 32, 3, 62, 9, 26, 0, 25, 14, 50, 3, 47, 30, 42, 16, 6, 63, 12, 49, 33, 55, 21, 10, 34, 63, 18, 41, 3, 47, 19, 43, 0, 49, 8, 28, 46, 20, 52, 0, 56, 24, 60, 3, 59, 5, 39, 57, 48, 52, 9, 38, 3, 21, 26, 60, 0, 32, 12, 38, 4, 48, 53, 0, 60, 15, 29, 44, 18, 10, 38, 57, 13, 60, 2, 26, 62, 7, 50, 29, 35, 8, 40, 53, 28, 12, 60, 33, 38, 5, 37, 29, 60, 39, 56, 0, 30, 18, 50, 34, 59, 25, 14, 44 }, + { 20, 31, 60, 22, 3, 49, 33, 25, 40, 13, 34, 59, 22, 36, 0, 28, 37, 56, 8, 18, 51, 16, 4, 45, 27, 12, 53, 42, 18, 44, 51, 31, 55, 40, 28, 58, 7, 60, 10, 51, 27, 37, 24, 56, 5, 26, 44, 29, 50, 23, 45, 11, 34, 15, 59, 27, 13, 23, 62, 37, 4, 57, 15, 32, 42, 6, 47, 11, 30, 43, 23, 13, 0, 36, 18, 44, 63, 51, 37, 29, 49, 20, 57, 27, 62, 9, 24, 35, 23, 53, 37, 3, 42, 55, 0, 36, 23, 39, 31, 43, 17, 37, 24, 11, 52, 43, 19, 32, 5, 50, 26, 0, 56, 21, 54, 11, 19, 6, 47, 25, 59, 42, 12, 54, 21, 3, 38, 57 }, + { 48, 0, 35, 27, 44, 14, 59, 7, 57, 46, 26, 2, 42, 12, 52, 43, 10, 27, 53, 42, 32, 62, 37, 21, 34, 61, 7, 23, 36, 4, 38, 12, 41, 5, 17, 45, 22, 27, 39, 21, 59, 0, 45, 18, 39, 62, 3, 38, 14, 7, 54, 26, 61, 39, 9, 52, 45, 36, 18, 50, 10, 34, 44, 22, 50, 14, 36, 55, 17, 34, 53, 62, 33, 26, 56, 6, 31, 12, 6, 53, 9, 44, 2, 50, 20, 40, 55, 17, 47, 7, 26, 63, 22, 32, 48, 16, 46, 8, 52, 12, 57, 41, 0, 56, 25, 3, 61, 14, 45, 35, 18, 44, 12, 46, 23, 42, 32, 51, 35, 10, 17, 36, 23, 1, 45, 52, 32, 10 }, + { 37, 15, 43, 8, 63, 39, 21, 31, 16, 37, 19, 62, 30, 46, 17, 60, 21, 48, 1, 23, 6, 25, 11, 56, 1, 40, 30, 58, 15, 54, 21, 59, 9, 63, 35, 56, 11, 51, 2, 46, 34, 14, 53, 7, 30, 11, 51, 19, 60, 40, 30, 1, 24, 50, 20, 32, 3, 56, 5, 25, 31, 13, 61, 2, 29, 60, 25, 20, 51, 2, 27, 8, 18, 42, 10, 45, 21, 34, 43, 17, 62, 29, 41, 14, 34, 6, 30, 43, 2, 57, 33, 13, 45, 12, 27, 62, 4, 55, 21, 35, 5, 27, 45, 33, 16, 47, 30, 54, 22, 10, 51, 27, 63, 7, 49, 1, 58, 22, 15, 43, 53, 7, 57, 39, 27, 12, 61, 24 }, + { 56, 51, 26, 56, 19, 2, 41, 54, 5, 52, 9, 48, 6, 23, 39, 4, 32, 15, 63, 35, 59, 49, 43, 15, 52, 19, 50, 9, 46, 33, 1, 29, 48, 20, 32, 1, 38, 33, 19, 54, 9, 32, 24, 48, 58, 35, 16, 48, 4, 52, 13, 57, 33, 5, 45, 59, 15, 29, 41, 55, 47, 39, 23, 53, 9, 40, 4, 57, 10, 44, 48, 40, 50, 14, 61, 24, 55, 1, 59, 22, 33, 8, 51, 25, 58, 46, 11, 59, 20, 41, 17, 51, 6, 56, 35, 25, 42, 30, 15, 58, 48, 18, 61, 9, 58, 39, 13, 2, 37, 59, 40, 2, 31, 16, 34, 41, 8, 30, 62, 3, 29, 48, 33, 5, 63, 16, 41, 7 }, + { 22, 4, 46, 11, 33, 51, 29, 10, 62, 24, 43, 27, 15, 58, 50, 25, 54, 44, 9, 38, 18, 3, 29, 57, 32, 5, 26, 43, 17, 61, 24, 52, 8, 42, 23, 53, 15, 61, 7, 28, 57, 43, 4, 40, 20, 2, 43, 25, 32, 35, 21, 43, 17, 48, 10, 22, 38, 54, 11, 21, 1, 58, 16, 30, 48, 18, 46, 32, 38, 13, 22, 4, 59, 35, 2, 51, 30, 39, 15, 47, 4, 56, 13, 37, 1, 28, 16, 52, 32, 9, 61, 29, 38, 19, 3, 52, 10, 48, 1, 32, 11, 40, 20, 36, 6, 22, 49, 29, 55, 6, 20, 56, 36, 52, 19, 60, 26, 46, 18, 54, 40, 13, 20, 46, 35, 19, 49, 29 }, + { 61, 17, 34, 53, 23, 6, 48, 35, 20, 40, 1, 56, 36, 29, 11, 34, 7, 41, 14, 30, 55, 20, 46, 8, 24, 38, 63, 2, 37, 10, 45, 14, 34, 49, 6, 13, 44, 25, 49, 41, 21, 12, 61, 15, 54, 29, 63, 12, 56, 8, 49, 2, 62, 36, 28, 61, 0, 25, 41, 63, 35, 8, 44, 6, 37, 62, 7, 21, 63, 28, 55, 31, 16, 24, 41, 19, 9, 57, 27, 36, 18, 42, 31, 62, 22, 55, 38, 4, 27, 47, 1, 40, 14, 54, 43, 20, 60, 23, 38, 63, 25, 51, 2, 53, 26, 63, 10, 42, 17, 34, 47, 25, 13, 5, 44, 11, 55, 2, 38, 27, 6, 60, 52, 25, 9, 55, 1, 40 }, + { 8, 30, 58, 3, 42, 61, 17, 38, 13, 59, 32, 10, 54, 3, 51, 20, 61, 26, 57, 2, 46, 33, 12, 60, 41, 13, 48, 29, 55, 20, 39, 27, 57, 18, 62, 29, 55, 2, 31, 16, 37, 50, 26, 36, 6, 46, 9, 41, 27, 57, 23, 39, 26, 6, 51, 12, 31, 46, 7, 16, 27, 52, 19, 56, 26, 12, 33, 53, 1, 41, 8, 57, 46, 7, 54, 32, 47, 5, 49, 11, 60, 23, 5, 48, 10, 43, 19, 63, 35, 24, 49, 21, 59, 5, 31, 37, 14, 44, 7, 42, 6, 30, 46, 13, 44, 32, 19, 50, 4, 58, 8, 30, 62, 38, 28, 53, 21, 36, 13, 50, 21, 33, 15, 2, 44, 31, 14, 47 }, + { 37, 13, 39, 16, 28, 9, 57, 0, 25, 49, 21, 45, 18, 47, 12, 42, 0, 49, 22, 39, 16, 53, 25, 36, 0, 52, 22, 16, 6, 60, 4, 51, 0, 26, 37, 47, 10, 36, 63, 5, 57, 0, 18, 59, 23, 33, 51, 19, 0, 44, 15, 11, 54, 17, 42, 35, 53, 18, 58, 33, 49, 4, 34, 42, 0, 50, 43, 25, 16, 49, 34, 20, 37, 28, 12, 63, 16, 38, 25, 44, 0, 40, 52, 17, 35, 3, 50, 14, 8, 53, 11, 36, 25, 45, 9, 62, 0, 54, 28, 17, 50, 55, 15, 24, 57, 0, 53, 34, 23, 41, 15, 45, 0, 49, 16, 4, 48, 9, 63, 45, 0, 42, 58, 37, 61, 22, 54, 26 }, + { 0, 50, 21, 47, 54, 36, 27, 45, 52, 4, 34, 15, 63, 29, 37, 59, 17, 31, 6, 61, 28, 5, 48, 18, 59, 27, 34, 56, 44, 31, 35, 12, 41, 59, 16, 3, 40, 20, 50, 22, 30, 40, 52, 10, 45, 3, 59, 22, 37, 61, 29, 46, 31, 58, 2, 22, 9, 43, 3, 39, 14, 61, 24, 54, 15, 29, 11, 60, 39, 17, 5, 61, 0, 44, 50, 3, 31, 14, 58, 21, 54, 28, 15, 45, 60, 26, 33, 58, 44, 22, 60, 2, 57, 34, 49, 27, 18, 34, 21, 59, 29, 4, 36, 41, 8, 39, 28, 11, 62, 26, 53, 20, 35, 24, 59, 32, 29, 39, 24, 31, 57, 23, 11, 28, 5, 36, 11, 59 }, + { 44, 32, 63, 5, 20, 12, 41, 7, 30, 61, 42, 8, 39, 5, 33, 8, 24, 53, 45, 11, 37, 58, 7, 44, 10, 50, 3, 40, 8, 22, 53, 19, 46, 9, 33, 52, 24, 58, 8, 44, 13, 47, 8, 34, 38, 30, 14, 47, 7, 34, 4, 55, 9, 19, 40, 49, 56, 26, 60, 21, 30, 45, 10, 19, 40, 58, 23, 36, 3, 52, 45, 23, 54, 13, 22, 42, 53, 45, 7, 33, 10, 36, 57, 6, 29, 12, 41, 0, 30, 15, 41, 30, 17, 7, 16, 53, 40, 56, 2, 39, 12, 61, 10, 52, 31, 60, 16, 45, 1, 37, 7, 61, 40, 10, 43, 17, 58, 7, 54, 14, 4, 51, 39, 49, 18, 56, 42, 20 }, + { 14, 6, 24, 36, 56, 49, 22, 60, 18, 14, 23, 51, 26, 57, 21, 52, 41, 14, 35, 50, 19, 31, 40, 23, 33, 14, 63, 17, 32, 47, 7, 62, 23, 30, 56, 11, 42, 27, 14, 60, 35, 19, 28, 61, 17, 55, 25, 39, 53, 17, 42, 21, 38, 63, 25, 5, 14, 36, 12, 50, 1, 37, 59, 32, 2, 51, 6, 56, 27, 32, 11, 30, 38, 26, 60, 8, 26, 19, 62, 39, 50, 2, 21, 39, 53, 23, 56, 19, 49, 39, 5, 46, 55, 23, 42, 4, 31, 11, 47, 26, 45, 22, 48, 18, 21, 5, 48, 25, 57, 14, 47, 30, 3, 56, 12, 50, 1, 42, 19, 47, 35, 17, 8, 30, 45, 25, 4, 51 }, + { 28, 58, 43, 1, 31, 8, 33, 2, 44, 55, 32, 1, 60, 12, 46, 27, 4, 62, 23, 1, 56, 13, 62, 2, 54, 36, 25, 51, 1, 57, 26, 42, 3, 49, 17, 38, 1, 48, 31, 4, 54, 3, 50, 24, 1, 49, 5, 63, 13, 27, 52, 1, 48, 13, 45, 33, 52, 30, 46, 20, 55, 28, 6, 48, 24, 38, 20, 47, 14, 62, 48, 9, 58, 4, 36, 30, 56, 1, 34, 12, 18, 63, 25, 48, 4, 16, 37, 7, 62, 10, 52, 28, 13, 50, 36, 63, 24, 51, 15, 58, 8, 33, 1, 38, 56, 35, 42, 9, 33, 51, 22, 18, 48, 32, 27, 37, 23, 61, 33, 11, 59, 29, 62, 1, 53, 10, 60, 33 }, + { 12, 39, 17, 52, 26, 46, 53, 38, 25, 11, 48, 36, 16, 43, 2, 35, 55, 17, 39, 29, 43, 9, 28, 45, 20, 5, 46, 12, 42, 28, 13, 52, 36, 6, 60, 22, 54, 17, 62, 39, 25, 42, 15, 55, 44, 20, 31, 10, 35, 57, 24, 32, 29, 6, 59, 18, 7, 62, 3, 41, 10, 44, 16, 54, 13, 62, 31, 9, 41, 1, 21, 43, 18, 47, 15, 40, 11, 49, 28, 55, 46, 30, 8, 43, 32, 61, 28, 47, 25, 34, 21, 61, 32, 1, 20, 9, 46, 6, 35, 19, 41, 54, 27, 63, 14, 3, 51, 20, 62, 2, 38, 55, 8, 21, 63, 6, 46, 9, 26, 51, 3, 24, 43, 34, 16, 41, 18, 48 }, + { 62, 23, 55, 9, 15, 62, 19, 13, 58, 40, 6, 30, 54, 19, 50, 31, 10, 44, 6, 59, 21, 47, 51, 15, 60, 39, 30, 54, 21, 61, 19, 33, 14, 29, 43, 11, 34, 45, 7, 21, 10, 56, 36, 6, 38, 11, 58, 42, 2, 47, 11, 60, 50, 16, 41, 28, 38, 23, 47, 17, 35, 63, 22, 33, 42, 5, 45, 17, 53, 35, 25, 56, 33, 6, 51, 19, 60, 23, 43, 15, 5, 40, 58, 13, 51, 1, 45, 11, 54, 3, 43, 8, 37, 48, 59, 29, 39, 21, 61, 43, 3, 31, 10, 44, 24, 29, 60, 12, 28, 40, 11, 25, 43, 52, 14, 41, 16, 57, 44, 20, 40, 55, 12, 21, 57, 27, 35, 2 }, + { 37, 6, 31, 42, 40, 4, 29, 50, 0, 20, 63, 28, 9, 58, 14, 24, 63, 26, 48, 16, 34, 4, 32, 38, 23, 11, 58, 4, 37, 9, 45, 5, 63, 48, 26, 57, 2, 28, 32, 51, 46, 29, 13, 62, 27, 46, 28, 18, 50, 15, 40, 4, 19, 34, 54, 0, 53, 9, 26, 58, 28, 5, 49, 0, 57, 27, 19, 60, 29, 8, 59, 12, 37, 63, 24, 46, 3, 37, 6, 52, 26, 32, 20, 36, 9, 22, 59, 18, 35, 51, 14, 57, 17, 24, 12, 44, 56, 0, 30, 13, 59, 20, 49, 17, 54, 43, 6, 34, 46, 17, 58, 36, 0, 34, 29, 54, 25, 2, 36, 15, 60, 6, 37, 46, 4, 50, 9, 45 }, + { 19, 59, 48, 3, 24, 60, 44, 22, 34, 51, 15, 45, 41, 5, 33, 47, 0, 37, 12, 55, 25, 54, 8, 57, 0, 47, 18, 34, 49, 15, 55, 24, 40, 20, 8, 35, 53, 13, 41, 18, 0, 59, 22, 33, 4, 52, 8, 60, 24, 36, 31, 56, 45, 26, 10, 43, 15, 56, 36, 4, 51, 14, 39, 30, 12, 55, 36, 2, 39, 49, 4, 44, 17, 0, 32, 13, 53, 35, 59, 17, 62, 0, 55, 24, 52, 38, 31, 6, 42, 19, 29, 40, 4, 54, 33, 5, 16, 27, 52, 37, 23, 55, 7, 37, 0, 39, 23, 49, 4, 53, 31, 15, 59, 10, 50, 4, 60, 34, 48, 7, 31, 49, 27, 14, 62, 22, 53, 29 }, + { 46, 21, 14, 51, 36, 17, 7, 57, 10, 32, 3, 37, 22, 60, 39, 18, 56, 20, 42, 3, 36, 10, 44, 26, 41, 29, 53, 27, 2, 39, 30, 52, 0, 59, 15, 48, 23, 61, 6, 58, 37, 12, 40, 49, 16, 39, 20, 44, 0, 62, 8, 21, 3, 59, 23, 32, 49, 31, 12, 44, 22, 59, 18, 50, 24, 7, 43, 52, 15, 23, 41, 26, 51, 28, 55, 39, 21, 27, 10, 42, 12, 45, 27, 47, 3, 15, 63, 26, 55, 0, 60, 26, 45, 18, 62, 38, 58, 49, 8, 47, 4, 33, 46, 29, 57, 13, 56, 16, 59, 21, 5, 47, 23, 39, 18, 44, 13, 22, 28, 53, 19, 0, 58, 32, 41, 7, 26, 13 }, + { 0, 56, 34, 28, 11, 55, 31, 47, 26, 41, 56, 13, 53, 28, 11, 49, 7, 52, 32, 61, 50, 22, 63, 17, 13, 56, 7, 19, 43, 62, 10, 21, 37, 32, 43, 4, 38, 19, 44, 25, 31, 54, 5, 23, 61, 30, 53, 12, 35, 22, 43, 53, 37, 48, 7, 62, 20, 2, 61, 41, 8, 34, 47, 9, 63, 34, 28, 10, 55, 33, 14, 57, 7, 47, 9, 61, 4, 49, 31, 50, 21, 38, 8, 16, 57, 44, 33, 5, 49, 36, 12, 50, 7, 34, 10, 25, 2, 22, 36, 15, 26, 61, 18, 9, 22, 46, 32, 8, 27, 37, 44, 30, 55, 3, 62, 24, 38, 56, 5, 45, 38, 24, 43, 10, 19, 54, 39, 61 }, + { 41, 30, 8, 63, 43, 23, 38, 3, 62, 19, 8, 49, 25, 1, 58, 30, 23, 40, 9, 28, 18, 40, 6, 38, 49, 22, 35, 59, 8, 27, 50, 5, 56, 17, 11, 50, 30, 9, 55, 2, 51, 19, 34, 47, 9, 41, 6, 26, 48, 57, 14, 28, 17, 12, 39, 13, 37, 46, 25, 19, 54, 27, 1, 37, 16, 45, 20, 60, 1, 48, 20, 38, 31, 22, 42, 15, 19, 44, 1, 61, 6, 34, 56, 40, 29, 10, 20, 46, 13, 22, 41, 23, 59, 42, 30, 51, 45, 13, 63, 53, 42, 12, 51, 38, 62, 2, 26, 41, 50, 1, 61, 10, 19, 42, 31, 8, 49, 32, 12, 63, 9, 52, 16, 56, 36, 2, 31, 16 }, + { 52, 5, 47, 20, 1, 53, 12, 50, 16, 35, 43, 21, 33, 43, 16, 44, 3, 59, 14, 46, 1, 30, 60, 33, 2, 45, 12, 42, 31, 47, 14, 33, 46, 25, 55, 27, 60, 36, 16, 42, 14, 46, 26, 1, 55, 15, 63, 32, 2, 38, 5, 47, 33, 61, 30, 52, 4, 57, 6, 38, 11, 43, 61, 24, 52, 3, 31, 22, 42, 10, 62, 3, 59, 11, 35, 57, 33, 54, 24, 14, 29, 48, 18, 2, 60, 41, 53, 24, 32, 62, 3, 53, 15, 1, 55, 17, 32, 40, 6, 31, 1, 40, 28, 5, 35, 52, 19, 63, 13, 33, 17, 41, 52, 26, 15, 57, 1, 20, 42, 17, 35, 27, 48, 5, 25, 50, 44, 11 }, + { 35, 25, 38, 57, 33, 17, 40, 6, 59, 27, 54, 5, 61, 10, 52, 26, 36, 19, 51, 35, 57, 48, 11, 20, 54, 25, 61, 16, 1, 58, 24, 61, 3, 39, 7, 47, 1, 22, 49, 28, 63, 10, 58, 32, 17, 36, 45, 19, 51, 29, 59, 10, 50, 1, 23, 42, 18, 29, 51, 21, 56, 32, 14, 5, 40, 58, 47, 13, 54, 35, 29, 45, 18, 52, 26, 2, 38, 8, 46, 36, 58, 11, 52, 35, 17, 28, 1, 58, 9, 39, 17, 28, 37, 48, 20, 9, 57, 24, 50, 19, 58, 16, 48, 25, 43, 11, 35, 6, 45, 24, 56, 4, 36, 7, 47, 35, 52, 28, 59, 30, 2, 61, 21, 33, 63, 12, 18, 59 }, + { 3, 49, 15, 10, 27, 61, 25, 45, 30, 0, 14, 47, 31, 38, 17, 62, 7, 55, 27, 4, 15, 24, 42, 52, 10, 34, 5, 51, 36, 18, 41, 11, 35, 21, 62, 13, 33, 57, 8, 35, 5, 40, 21, 43, 52, 3, 24, 56, 11, 16, 33, 25, 41, 20, 55, 8, 60, 35, 15, 48, 2, 57, 30, 49, 18, 25, 6, 39, 17, 57, 7, 25, 43, 5, 49, 16, 62, 22, 55, 4, 25, 43, 23, 7, 50, 11, 37, 48, 14, 51, 33, 57, 7, 27, 39, 46, 4, 29, 11, 43, 34, 56, 7, 60, 20, 54, 30, 57, 22, 49, 9, 33, 54, 14, 63, 23, 6, 43, 10, 40, 50, 13, 44, 8, 38, 33, 46, 23 }, + { 55, 39, 22, 50, 44, 4, 36, 9, 52, 23, 37, 59, 21, 2, 46, 13, 31, 41, 11, 45, 62, 29, 6, 37, 19, 48, 30, 23, 44, 7, 53, 28, 54, 16, 41, 29, 44, 18, 52, 24, 60, 15, 48, 7, 27, 59, 9, 34, 42, 54, 7, 63, 4, 46, 31, 27, 45, 0, 40, 26, 34, 17, 37, 10, 53, 29, 36, 50, 2, 27, 51, 11, 61, 37, 23, 41, 30, 7, 18, 50, 39, 14, 63, 32, 45, 61, 19, 30, 25, 44, 2, 47, 23, 63, 11, 34, 59, 37, 60, 3, 22, 14, 44, 30, 15, 0, 47, 15, 3, 38, 61, 20, 27, 45, 11, 39, 51, 16, 55, 3, 22, 54, 29, 58, 1, 57, 6, 29 }, + { 9, 17, 60, 2, 34, 56, 20, 62, 39, 12, 49, 6, 29, 56, 34, 48, 0, 58, 22, 38, 18, 43, 56, 0, 63, 14, 55, 3, 59, 31, 15, 45, 0, 49, 6, 58, 3, 38, 12, 45, 0, 37, 29, 57, 13, 39, 30, 49, 0, 23, 44, 36, 16, 57, 13, 54, 11, 24, 63, 9, 53, 7, 62, 42, 0, 59, 15, 23, 63, 34, 40, 16, 32, 0, 53, 12, 48, 28, 59, 33, 0, 53, 9, 27, 3, 22, 54, 5, 56, 9, 61, 13, 42, 14, 52, 19, 0, 21, 47, 27, 53, 36, 3, 50, 39, 58, 25, 40, 53, 28, 12, 50, 0, 59, 32, 2, 21, 34, 26, 46, 37, 7, 18, 47, 24, 14, 53, 42 }, + { 61, 32, 13, 54, 29, 7, 46, 13, 28, 57, 18, 41, 53, 15, 9, 39, 24, 49, 33, 3, 53, 9, 26, 32, 40, 28, 46, 39, 25, 9, 56, 21, 63, 37, 26, 22, 51, 27, 17, 56, 31, 53, 4, 43, 22, 46, 12, 18, 60, 40, 20, 26, 50, 21, 39, 5, 49, 33, 16, 44, 22, 46, 20, 32, 24, 45, 8, 43, 12, 46, 4, 48, 56, 20, 29, 58, 3, 40, 10, 42, 31, 21, 47, 41, 56, 38, 15, 42, 36, 27, 20, 33, 55, 3, 26, 44, 31, 54, 12, 35, 9, 63, 28, 10, 21, 32, 9, 60, 17, 8, 43, 29, 40, 16, 36, 48, 60, 7, 57, 14, 62, 31, 42, 15, 36, 40, 20, 26 }, + { 0, 37, 47, 23, 41, 18, 32, 48, 1, 35, 8, 25, 4, 26, 63, 20, 54, 8, 16, 61, 35, 23, 51, 15, 58, 7, 12, 20, 50, 34, 42, 4, 38, 10, 32, 47, 8, 60, 41, 20, 9, 25, 50, 19, 62, 1, 37, 56, 28, 8, 53, 11, 3, 58, 34, 43, 19, 60, 38, 4, 58, 31, 3, 51, 11, 55, 38, 30, 21, 58, 19, 26, 9, 44, 36, 13, 46, 20, 62, 24, 13, 60, 5, 28, 12, 34, 7, 59, 0, 53, 45, 6, 38, 30, 50, 7, 62, 16, 41, 5, 46, 18, 55, 42, 51, 5, 45, 23, 34, 48, 19, 58, 5, 25, 54, 19, 13, 41, 28, 21, 0, 49, 10, 60, 4, 51, 9, 45 }, + { 19, 28, 6, 58, 10, 51, 4, 22, 55, 42, 60, 45, 34, 51, 42, 5, 30, 45, 27, 40, 13, 47, 4, 49, 21, 38, 60, 29, 2, 57, 17, 27, 52, 19, 61, 14, 30, 34, 2, 44, 63, 33, 11, 35, 16, 51, 25, 6, 14, 47, 31, 61, 37, 29, 18, 8, 52, 2, 28, 54, 13, 41, 15, 62, 35, 18, 2, 60, 6, 33, 41, 61, 31, 6, 56, 17, 34, 50, 6, 52, 44, 35, 16, 51, 59, 24, 48, 18, 31, 40, 16, 49, 21, 60, 17, 39, 10, 49, 32, 57, 24, 39, 1, 25, 18, 62, 37, 12, 56, 1, 37, 11, 52, 44, 9, 30, 47, 4, 51, 40, 55, 25, 34, 27, 56, 30, 32, 54 }, + { 63, 40, 49, 15, 43, 26, 63, 38, 16, 20, 30, 12, 57, 14, 19, 60, 36, 12, 59, 2, 57, 17, 42, 31, 1, 44, 16, 35, 47, 11, 32, 48, 13, 43, 1, 39, 51, 12, 57, 23, 6, 40, 53, 3, 55, 31, 39, 60, 35, 44, 5, 15, 45, 1, 62, 41, 26, 14, 47, 22, 36, 27, 50, 9, 26, 47, 52, 28, 54, 16, 1, 13, 51, 39, 23, 63, 1, 30, 15, 26, 2, 57, 19, 37, 1, 44, 21, 50, 13, 63, 8, 24, 56, 1, 35, 25, 58, 20, 2, 28, 14, 51, 33, 59, 13, 30, 4, 49, 31, 24, 63, 26, 33, 3, 58, 38, 62, 24, 32, 8, 17, 45, 5, 48, 18, 3, 43, 11 }, + { 21, 4, 24, 34, 59, 1, 37, 11, 53, 5, 47, 2, 22, 40, 32, 1, 24, 50, 21, 29, 38, 25, 63, 8, 55, 24, 53, 6, 62, 23, 59, 3, 54, 20, 58, 24, 5, 46, 15, 38, 48, 14, 27, 42, 23, 7, 46, 10, 17, 58, 25, 52, 23, 32, 49, 12, 55, 30, 40, 7, 59, 1, 56, 21, 39, 4, 23, 15, 37, 46, 55, 42, 21, 4, 48, 8, 45, 54, 37, 55, 32, 8, 46, 10, 30, 54, 4, 41, 25, 29, 36, 48, 11, 43, 14, 47, 5, 43, 53, 36, 61, 10, 45, 6, 41, 54, 27, 43, 16, 55, 6, 46, 18, 42, 23, 15, 1, 45, 12, 60, 37, 22, 62, 12, 39, 59, 16, 52 }, + { 47, 35, 56, 7, 19, 46, 31, 50, 33, 24, 61, 35, 50, 7, 53, 44, 55, 6, 46, 10, 52, 5, 21, 43, 36, 10, 18, 41, 26, 37, 8, 29, 40, 36, 9, 49, 34, 26, 61, 21, 7, 59, 18, 62, 29, 54, 20, 32, 51, 0, 40, 10, 55, 6, 20, 36, 9, 61, 5, 51, 44, 19, 33, 43, 13, 57, 40, 63, 8, 24, 29, 10, 60, 34, 27, 40, 25, 18, 10, 42, 21, 49, 26, 62, 38, 12, 33, 61, 5, 57, 2, 19, 54, 28, 62, 22, 38, 31, 16, 7, 22, 47, 29, 17, 35, 8, 20, 51, 2, 40, 22, 50, 13, 61, 28, 53, 35, 20, 56, 30, 2, 53, 14, 41, 23, 34, 8, 31 }, + { 12, 2, 42, 29, 52, 13, 21, 8, 55, 14, 41, 17, 28, 58, 23, 11, 17, 36, 31, 62, 17, 34, 50, 14, 28, 61, 33, 52, 2, 51, 17, 45, 7, 25, 62, 30, 18, 55, 0, 42, 30, 35, 45, 1, 12, 48, 3, 63, 21, 36, 30, 48, 19, 59, 43, 27, 46, 17, 34, 25, 12, 29, 53, 6, 48, 31, 11, 34, 49, 3, 36, 50, 19, 47, 14, 61, 11, 36, 58, 4, 60, 14, 39, 22, 6, 52, 15, 35, 17, 46, 31, 42, 9, 34, 3, 52, 12, 60, 26, 56, 40, 2, 53, 23, 57, 38, 62, 14, 36, 59, 10, 31, 39, 6, 49, 9, 41, 26, 5, 48, 43, 27, 33, 58, 1, 50, 25, 57 }, + { 61, 37, 15, 61, 3, 39, 58, 43, 26, 0, 44, 10, 47, 3, 37, 63, 28, 43, 13, 39, 3, 57, 30, 59, 0, 48, 5, 43, 13, 22, 60, 33, 55, 15, 42, 4, 52, 10, 45, 13, 54, 4, 24, 49, 37, 26, 41, 14, 42, 9, 61, 13, 38, 23, 3, 53, 0, 58, 21, 42, 63, 10, 17, 61, 25, 0, 58, 28, 17, 44, 57, 12, 27, 0, 55, 5, 52, 28, 23, 47, 29, 0, 43, 17, 58, 28, 47, 23, 55, 10, 58, 23, 51, 40, 18, 33, 45, 0, 49, 8, 32, 61, 19, 48, 0, 26, 7, 47, 29, 18, 44, 0, 56, 34, 20, 59, 15, 51, 37, 18, 10, 52, 7, 20, 46, 9, 38, 17 }, + { 6, 27, 48, 23, 45, 29, 5, 18, 38, 62, 27, 56, 20, 32, 15, 9, 48, 0, 54, 22, 45, 20, 7, 41, 23, 39, 19, 27, 58, 31, 44, 0, 12, 50, 23, 56, 20, 39, 32, 59, 16, 52, 33, 9, 57, 22, 6, 58, 28, 50, 24, 2, 56, 35, 16, 45, 32, 38, 15, 54, 2, 38, 46, 22, 35, 45, 20, 5, 52, 25, 7, 35, 59, 32, 22, 43, 38, 3, 51, 16, 34, 53, 32, 50, 3, 40, 8, 43, 0, 39, 27, 4, 14, 61, 8, 55, 15, 41, 20, 44, 27, 13, 39, 11, 46, 42, 54, 33, 4, 52, 23, 61, 14, 25, 43, 2, 33, 11, 63, 29, 61, 17, 40, 55, 22, 62, 28, 44 }, + { 20, 54, 8, 56, 35, 10, 63, 31, 52, 12, 48, 6, 59, 41, 52, 33, 19, 58, 25, 49, 11, 37, 47, 12, 54, 15, 56, 35, 7, 47, 16, 53, 28, 34, 5, 37, 28, 8, 48, 3, 28, 38, 18, 61, 16, 43, 53, 32, 4, 17, 47, 27, 44, 8, 63, 10, 25, 49, 6, 37, 24, 52, 32, 3, 50, 12, 41, 56, 38, 14, 62, 20, 40, 16, 53, 31, 18, 63, 41, 9, 59, 7, 13, 25, 57, 20, 63, 26, 53, 18, 48, 62, 30, 46, 21, 25, 58, 29, 36, 4, 55, 34, 6, 60, 31, 16, 21, 12, 58, 38, 9, 29, 47, 7, 52, 30, 57, 44, 22, 0, 35, 45, 3, 31, 14, 36, 0, 51 }, + { 42, 14, 33, 24, 16, 49, 40, 2, 22, 33, 16, 36, 25, 1, 21, 61, 38, 8, 33, 4, 62, 26, 29, 60, 6, 46, 30, 11, 63, 4, 36, 40, 19, 57, 46, 11, 41, 63, 22, 25, 58, 10, 46, 2, 34, 27, 11, 38, 56, 34, 12, 53, 18, 33, 41, 51, 13, 28, 60, 20, 47, 14, 29, 59, 16, 62, 8, 22, 32, 47, 9, 49, 2, 44, 7, 12, 45, 6, 20, 27, 45, 24, 62, 42, 36, 11, 33, 15, 37, 7, 32, 10, 37, 1, 35, 50, 6, 11, 63, 24, 52, 15, 50, 24, 3, 37, 56, 27, 34, 22, 49, 16, 36, 62, 17, 39, 4, 15, 54, 24, 50, 8, 58, 26, 49, 54, 11, 30 }, + { 4, 59, 41, 1, 53, 12, 25, 45, 59, 7, 51, 39, 54, 14, 46, 4, 27, 53, 16, 44, 18, 51, 1, 32, 25, 2, 50, 40, 20, 54, 24, 9, 62, 2, 27, 60, 1, 17, 36, 50, 6, 40, 30, 55, 41, 19, 49, 1, 21, 60, 40, 5, 62, 1, 22, 30, 57, 4, 43, 31, 1, 55, 40, 7, 27, 37, 30, 54, 1, 19, 42, 30, 56, 26, 62, 49, 24, 57, 37, 56, 2, 39, 16, 5, 30, 55, 3, 49, 60, 23, 56, 44, 17, 52, 13, 42, 28, 48, 18, 45, 9, 37, 21, 41, 58, 10, 48, 1, 63, 5, 41, 57, 2, 24, 12, 48, 27, 42, 32, 46, 13, 38, 19, 34, 5, 41, 25, 60 }, + { 39, 28, 21, 46, 32, 57, 36, 9, 19, 42, 4, 29, 11, 43, 30, 49, 13, 42, 35, 56, 9, 39, 15, 52, 36, 61, 18, 26, 45, 14, 31, 48, 21, 43, 14, 33, 49, 54, 14, 44, 21, 62, 13, 23, 8, 62, 15, 51, 44, 7, 30, 37, 20, 42, 56, 7, 39, 18, 50, 11, 61, 9, 19, 43, 57, 2, 48, 11, 39, 60, 28, 4, 37, 17, 35, 1, 33, 11, 31, 14, 48, 19, 35, 51, 46, 21, 44, 29, 12, 41, 2, 22, 58, 26, 54, 4, 59, 38, 2, 33, 57, 1, 63, 13, 28, 51, 15, 40, 18, 45, 8, 30, 43, 37, 54, 19, 8, 59, 21, 6, 60, 29, 55, 10, 63, 15, 47, 17 }, + { 3, 50, 10, 62, 18, 5, 27, 49, 60, 23, 55, 18, 62, 24, 56, 10, 59, 28, 2, 23, 34, 59, 43, 20, 10, 42, 8, 49, 1, 37, 57, 6, 51, 29, 53, 7, 23, 31, 5, 32, 51, 0, 35, 54, 45, 31, 5, 26, 36, 24, 55, 15, 48, 29, 14, 48, 26, 60, 21, 41, 36, 26, 50, 33, 14, 44, 17, 24, 52, 15, 46, 23, 54, 6, 47, 21, 60, 50, 4, 53, 29, 61, 8, 23, 1, 60, 19, 6, 53, 16, 47, 34, 6, 39, 16, 31, 12, 20, 53, 22, 30, 43, 25, 46, 35, 6, 44, 32, 53, 26, 55, 19, 11, 59, 5, 33, 51, 1, 35, 53, 25, 3, 42, 23, 44, 32, 7, 53 }, + { 22, 44, 37, 6, 26, 51, 38, 0, 34, 13, 31, 46, 3, 37, 6, 19, 40, 21, 47, 63, 12, 5, 29, 55, 22, 58, 34, 28, 60, 22, 11, 41, 17, 38, 9, 44, 59, 39, 56, 19, 11, 47, 25, 15, 3, 39, 57, 17, 61, 11, 46, 3, 58, 9, 54, 35, 2, 34, 8, 45, 15, 56, 5, 23, 53, 33, 63, 35, 4, 59, 10, 51, 13, 61, 29, 41, 15, 25, 43, 19, 40, 10, 54, 33, 41, 12, 38, 51, 31, 26, 61, 9, 30, 45, 24, 62, 49, 40, 10, 61, 14, 49, 5, 17, 54, 20, 60, 23, 3, 13, 35, 50, 32, 23, 46, 27, 38, 63, 16, 12, 39, 48, 18, 51, 1, 27, 56, 35 }, + { 63, 15, 30, 55, 43, 14, 57, 17, 53, 44, 7, 48, 26, 50, 32, 60, 0, 53, 14, 31, 50, 24, 46, 0, 38, 13, 4, 52, 16, 45, 30, 59, 0, 25, 55, 35, 16, 10, 26, 42, 58, 29, 60, 38, 50, 22, 28, 47, 0, 50, 28, 19, 33, 39, 11, 44, 16, 52, 24, 59, 3, 38, 27, 51, 0, 21, 7, 42, 26, 34, 21, 40, 33, 18, 39, 3, 54, 38, 8, 59, 0, 44, 27, 15, 58, 28, 57, 9, 43, 0, 36, 50, 20, 59, 8, 34, 0, 27, 47, 7, 36, 19, 56, 32, 0, 38, 11, 29, 62, 47, 6, 61, 0, 41, 14, 56, 10, 23, 45, 31, 57, 8, 36, 13, 58, 38, 11, 19 }, + { 0, 34, 12, 47, 21, 2, 40, 30, 11, 25, 61, 20, 40, 15, 35, 22, 45, 36, 7, 41, 17, 57, 9, 48, 32, 62, 44, 24, 35, 3, 54, 13, 33, 63, 19, 4, 48, 22, 62, 2, 37, 8, 33, 6, 20, 52, 9, 32, 43, 13, 39, 63, 25, 4, 49, 23, 62, 32, 9, 30, 48, 18, 63, 12, 46, 29, 58, 13, 48, 8, 57, 31, 0, 51, 9, 58, 12, 22, 47, 29, 35, 22, 49, 5, 46, 4, 34, 20, 63, 24, 56, 11, 41, 3, 51, 19, 56, 35, 17, 58, 28, 42, 9, 45, 59, 26, 51, 42, 17, 36, 25, 15, 53, 21, 44, 3, 30, 55, 5, 50, 21, 28, 61, 32, 6, 49, 28, 46 }, + { 58, 42, 60, 4, 31, 59, 22, 63, 35, 38, 9, 54, 1, 57, 8, 51, 16, 58, 27, 53, 3, 38, 30, 15, 27, 6, 19, 56, 10, 50, 21, 36, 47, 5, 43, 28, 51, 32, 13, 46, 18, 54, 16, 43, 63, 12, 36, 59, 22, 34, 5, 52, 17, 59, 27, 41, 0, 19, 55, 37, 13, 43, 6, 34, 41, 10, 36, 55, 19, 44, 3, 16, 58, 27, 49, 25, 32, 62, 17, 55, 13, 63, 18, 52, 25, 37, 17, 48, 13, 32, 5, 46, 28, 37, 14, 43, 25, 5, 51, 39, 3, 52, 33, 22, 8, 40, 12, 4, 57, 9, 46, 39, 28, 58, 13, 62, 17, 42, 19, 36, 0, 47, 16, 43, 24, 21, 54, 13 }, + { 25, 9, 23, 50, 36, 8, 45, 14, 3, 51, 16, 28, 44, 12, 42, 29, 4, 26, 10, 47, 22, 61, 18, 54, 51, 39, 46, 13, 41, 26, 58, 7, 18, 39, 12, 57, 15, 1, 52, 27, 41, 23, 48, 1, 27, 45, 18, 2, 57, 26, 55, 8, 43, 31, 6, 58, 14, 51, 40, 5, 61, 31, 24, 54, 17, 60, 22, 1, 39, 30, 53, 45, 36, 13, 43, 5, 45, 2, 37, 6, 34, 42, 2, 39, 10, 62, 7, 54, 40, 18, 60, 15, 52, 21, 63, 8, 55, 46, 15, 30, 23, 13, 62, 16, 50, 24, 58, 31, 48, 21, 34, 2, 49, 7, 31, 37, 26, 48, 9, 61, 40, 11, 52, 2, 60, 40, 4, 37 }, + { 52, 28, 39, 16, 54, 19, 29, 55, 42, 20, 58, 33, 24, 63, 18, 55, 39, 62, 43, 34, 12, 40, 6, 35, 2, 25, 8, 62, 34, 1, 31, 42, 61, 27, 53, 24, 40, 61, 34, 8, 59, 4, 30, 56, 40, 6, 53, 42, 10, 48, 16, 37, 12, 46, 21, 36, 47, 11, 28, 45, 22, 10, 57, 2, 49, 31, 14, 44, 61, 11, 25, 6, 23, 63, 18, 36, 28, 56, 20, 51, 11, 48, 27, 56, 32, 22, 45, 30, 2, 42, 27, 39, 1, 44, 23, 31, 38, 22, 11, 61, 43, 54, 4, 47, 35, 2, 44, 16, 28, 54, 12, 62, 18, 43, 10, 52, 1, 58, 33, 15, 29, 56, 20, 34, 9, 30, 48, 17 }, + { 46, 2, 56, 11, 41, 1, 49, 6, 27, 47, 2, 48, 5, 32, 37, 3, 13, 19, 32, 1, 55, 28, 60, 17, 43, 59, 32, 20, 49, 16, 55, 23, 14, 46, 2, 36, 6, 30, 20, 49, 12, 47, 35, 14, 21, 60, 29, 14, 35, 24, 46, 1, 56, 29, 53, 8, 33, 23, 56, 1, 35, 46, 20, 39, 26, 4, 53, 28, 17, 38, 60, 34, 48, 9, 55, 15, 46, 7, 41, 31, 60, 24, 16, 36, 1, 59, 19, 52, 35, 6, 55, 11, 59, 33, 7, 57, 4, 29, 48, 1, 19, 26, 37, 30, 18, 63, 37, 6, 59, 1, 40, 24, 56, 33, 46, 22, 35, 7, 24, 53, 39, 5, 26, 45, 55, 18, 62, 7 }, + { 20, 60, 29, 34, 20, 62, 33, 52, 10, 36, 13, 60, 41, 21, 50, 27, 56, 49, 8, 51, 21, 45, 11, 48, 8, 23, 53, 3, 29, 44, 5, 52, 9, 32, 50, 17, 43, 56, 3, 38, 24, 10, 62, 25, 51, 9, 33, 49, 61, 7, 30, 62, 22, 19, 2, 42, 63, 5, 49, 18, 60, 15, 52, 7, 43, 56, 23, 50, 5, 50, 2, 20, 41, 30, 1, 52, 22, 61, 14, 26, 3, 43, 53, 7, 47, 28, 11, 14, 23, 58, 33, 25, 47, 13, 50, 17, 40, 54, 34, 60, 41, 6, 59, 14, 50, 7, 25, 55, 20, 42, 51, 8, 27, 4, 16, 60, 28, 50, 44, 3, 22, 49, 63, 12, 33, 1, 43, 31 }, + { 36, 5, 46, 8, 44, 24, 13, 39, 25, 57, 31, 18, 8, 52, 10, 45, 6, 30, 36, 24, 63, 4, 33, 26, 57, 40, 15, 56, 37, 12, 40, 25, 37, 58, 11, 63, 21, 45, 16, 60, 31, 53, 18, 33, 3, 45, 23, 0, 20, 54, 40, 15, 50, 38, 60, 16, 25, 42, 29, 38, 7, 41, 25, 62, 18, 33, 8, 35, 42, 16, 32, 56, 12, 39, 59, 19, 34, 9, 49, 38, 57, 12, 21, 50, 14, 40, 61, 44, 50, 9, 49, 19, 3, 29, 35, 62, 12, 24, 7, 18, 52, 32, 10, 46, 21, 41, 32, 11, 36, 29, 14, 34, 60, 38, 54, 11, 41, 14, 19, 57, 32, 16, 7, 41, 51, 25, 14, 57 }, + { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 63, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 }, + { 23, 39, 61, 3, 37, 28, 48, 31, 0, 34, 51, 23, 2, 26, 58, 0, 53, 11, 46, 1, 57, 29, 52, 14, 37, 61, 21, 35, 2, 49, 7, 34, 47, 55, 4, 33, 54, 13, 58, 52, 19, 50, 22, 7, 13, 29, 36, 11, 51, 17, 60, 25, 55, 4, 34, 51, 0, 35, 20, 48, 32, 3, 51, 30, 59, 28, 40, 3, 46, 29, 54, 43, 7, 62, 47, 11, 39, 4, 23, 46, 55, 8, 63, 5, 25, 37, 18, 46, 21, 56, 31, 5, 36, 8, 45, 58, 26, 15, 2, 36, 47, 21, 29, 44, 25, 34, 3, 27, 43, 10, 52, 0, 45, 30, 24, 36, 43, 18, 34, 59, 0, 52, 61, 15, 44, 19, 30, 49 }, + { 0, 27, 12, 43, 54, 9, 22, 53, 21, 46, 15, 55, 29, 47, 20, 33, 39, 28, 59, 35, 9, 44, 5, 24, 47, 7, 52, 17, 56, 22, 30, 42, 14, 26, 45, 18, 49, 1, 24, 34, 11, 27, 55, 32, 61, 47, 2, 56, 6, 44, 13, 47, 36, 27, 58, 22, 16, 47, 40, 4, 57, 38, 21, 45, 16, 9, 56, 26, 11, 38, 0, 22, 36, 17, 33, 57, 16, 30, 62, 15, 35, 40, 20, 45, 59, 10, 54, 8, 63, 13, 52, 27, 22, 57, 28, 12, 32, 51, 55, 22, 63, 4, 16, 54, 12, 62, 45, 19, 58, 13, 32, 40, 20, 56, 7, 57, 9, 54, 6, 29, 42, 21, 8, 55, 35, 47, 6, 41 }, + { 56, 33, 58, 32, 19, 35, 42, 6, 59, 11, 38, 5, 49, 12, 62, 7, 52, 17, 5, 25, 54, 20, 61, 31, 54, 27, 41, 11, 44, 5, 59, 12, 36, 51, 10, 61, 28, 41, 48, 9, 43, 63, 5, 40, 20, 8, 49, 26, 34, 21, 58, 1, 18, 45, 7, 39, 61, 26, 8, 50, 23, 10, 63, 5, 55, 37, 19, 49, 52, 15, 59, 47, 13, 54, 1, 25, 42, 58, 10, 48, 3, 27, 50, 1, 17, 48, 34, 41, 16, 40, 2, 45, 10, 39, 17, 61, 5, 38, 19, 9, 41, 31, 60, 38, 5, 23, 36, 8, 30, 55, 24, 63, 12, 48, 14, 51, 31, 20, 45, 25, 12, 50, 32, 2, 28, 11, 62, 14 }, + { 44, 16, 7, 48, 1, 62, 16, 50, 27, 33, 61, 25, 17, 44, 31, 14, 22, 43, 32, 48, 18, 40, 8, 36, 3, 16, 33, 62, 23, 38, 25, 53, 2, 21, 41, 6, 22, 15, 59, 29, 16, 37, 26, 15, 52, 42, 23, 15, 54, 39, 10, 30, 53, 11, 49, 24, 2, 43, 55, 17, 34, 44, 15, 31, 24, 44, 2, 32, 7, 35, 25, 5, 40, 45, 29, 51, 6, 21, 37, 52, 24, 60, 13, 31, 53, 23, 2, 28, 49, 24, 31, 60, 20, 51, 1, 34, 48, 14, 59, 33, 50, 1, 18, 33, 48, 60, 17, 51, 39, 6, 38, 2, 35, 29, 40, 23, 1, 62, 15, 53, 37, 17, 46, 57, 40, 51, 24, 22 }, + { 5, 37, 52, 24, 45, 13, 40, 3, 45, 9, 19, 42, 56, 4, 37, 46, 56, 2, 63, 11, 51, 1, 49, 13, 59, 45, 39, 1, 48, 15, 58, 9, 46, 31, 54, 35, 57, 38, 3, 46, 56, 4, 47, 57, 1, 30, 38, 63, 3, 46, 28, 63, 41, 14, 33, 62, 19, 32, 13, 28, 61, 1, 53, 42, 11, 60, 22, 62, 27, 42, 61, 31, 19, 8, 61, 12, 32, 55, 2, 18, 33, 12, 43, 36, 9, 62, 30, 55, 6, 58, 35, 7, 43, 29, 54, 23, 43, 30, 3, 25, 11, 45, 52, 28, 7, 14, 42, 1, 22, 50, 16, 53, 19, 59, 4, 46, 33, 41, 4, 35, 58, 5, 26, 13, 20, 2, 34, 54 }, + { 30, 63, 21, 10, 26, 55, 29, 59, 23, 39, 53, 1, 36, 24, 59, 27, 10, 34, 23, 38, 30, 60, 22, 42, 28, 19, 9, 57, 30, 19, 43, 33, 13, 63, 3, 19, 11, 50, 31, 20, 14, 34, 10, 35, 17, 59, 7, 31, 19, 25, 50, 5, 20, 57, 29, 6, 52, 41, 4, 46, 20, 37, 26, 17, 49, 6, 39, 18, 53, 14, 3, 49, 57, 23, 34, 48, 14, 41, 28, 38, 56, 6, 58, 25, 39, 19, 43, 15, 37, 11, 47, 18, 53, 4, 37, 9, 62, 21, 53, 40, 57, 24, 13, 40, 56, 26, 47, 31, 59, 25, 45, 27, 10, 43, 21, 61, 13, 27, 48, 9, 23, 43, 31, 62, 38, 59, 9, 47 }, + { 25, 4, 40, 60, 34, 6, 18, 36, 8, 57, 12, 30, 49, 14, 6, 54, 41, 16, 50, 6, 43, 15, 34, 4, 53, 24, 50, 35, 4, 51, 7, 55, 28, 24, 39, 44, 60, 7, 25, 62, 42, 53, 24, 61, 28, 45, 52, 12, 48, 37, 9, 35, 43, 3, 37, 48, 12, 58, 30, 52, 9, 59, 6, 57, 33, 29, 48, 4, 37, 45, 20, 34, 10, 39, 0, 60, 22, 45, 8, 63, 21, 42, 14, 49, 3, 56, 11, 46, 21, 61, 0, 42, 25, 13, 63, 17, 36, 8, 46, 16, 6, 35, 63, 0, 21, 37, 4, 57, 9, 34, 5, 61, 48, 32, 8, 37, 54, 17, 56, 30, 60, 0, 50, 16, 7, 29, 42, 17 }, + { 32, 50, 15, 48, 2, 43, 52, 25, 47, 16, 32, 63, 21, 52, 40, 19, 0, 61, 29, 58, 20, 56, 26, 46, 12, 55, 6, 22, 62, 32, 17, 40, 0, 49, 34, 8, 27, 32, 48, 0, 21, 39, 5, 44, 12, 6, 22, 40, 0, 57, 16, 60, 23, 17, 54, 22, 36, 15, 24, 39, 19, 34, 47, 23, 0, 54, 13, 51, 24, 9, 55, 16, 52, 27, 44, 20, 4, 54, 26, 49, 0, 30, 46, 16, 29, 51, 34, 4, 52, 28, 33, 15, 57, 39, 26, 49, 0, 56, 27, 31, 48, 20, 43, 29, 53, 11, 46, 19, 41, 13, 55, 18, 0, 57, 26, 51, 2, 44, 6, 38, 14, 40, 22, 45, 36, 53, 3, 57 }, + { 44, 12, 37, 28, 22, 57, 11, 38, 0, 51, 9, 41, 4, 29, 11, 47, 33, 45, 12, 26, 3, 36, 9, 63, 31, 16, 38, 44, 14, 47, 25, 61, 20, 58, 15, 47, 17, 57, 13, 36, 9, 51, 18, 29, 50, 36, 54, 20, 61, 27, 32, 13, 53, 44, 9, 27, 0, 63, 45, 2, 56, 10, 14, 43, 41, 28, 58, 11, 35, 60, 30, 41, 6, 63, 11, 51, 37, 32, 15, 10, 35, 53, 5, 61, 22, 7, 26, 59, 23, 9, 44, 48, 21, 3, 51, 32, 24, 41, 12, 61, 2, 55, 9, 15, 35, 58, 28, 15, 62, 30, 37, 23, 42, 29, 11, 17, 35, 24, 63, 20, 52, 28, 8, 55, 11, 23, 47, 19 }, + { 0, 56, 8, 53, 14, 31, 61, 20, 55, 28, 62, 18, 35, 60, 25, 57, 7, 23, 39, 54, 47, 17, 43, 0, 40, 59, 29, 2, 56, 10, 37, 5, 43, 11, 29, 52, 1, 23, 54, 41, 59, 30, 55, 1, 62, 15, 33, 4, 43, 10, 47, 39, 1, 31, 40, 60, 49, 33, 7, 55, 26, 50, 31, 61, 8, 18, 21, 32, 44, 1, 25, 47, 18, 36, 30, 23, 59, 7, 40, 59, 27, 19, 38, 32, 44, 54, 40, 17, 38, 60, 27, 6, 35, 55, 10, 14, 44, 5, 50, 17, 38, 26, 42, 50, 18, 3, 44, 52, 2, 49, 7, 52, 15, 46, 62, 39, 55, 10, 31, 48, 3, 58, 33, 18, 61, 34, 13, 59 }, + { 39, 27, 63, 20, 35, 41, 4, 45, 26, 5, 38, 13, 44, 2, 50, 17, 37, 52, 2, 13, 28, 58, 24, 51, 21, 8, 34, 48, 27, 42, 18, 51, 31, 56, 5, 36, 38, 44, 4, 17, 26, 11, 38, 23, 42, 8, 56, 39, 24, 51, 5, 56, 21, 59, 14, 6, 18, 42, 22, 35, 16, 37, 3, 25, 39, 46, 63, 5, 50, 17, 58, 8, 55, 3, 50, 12, 43, 17, 47, 2, 51, 9, 62, 12, 1, 35, 13, 50, 1, 37, 12, 51, 19, 29, 46, 59, 22, 58, 33, 45, 22, 60, 10, 32, 61, 39, 8, 33, 25, 36, 20, 60, 38, 4, 21, 5, 28, 45, 12, 18, 42, 11, 49, 1, 27, 40, 6, 30 }, + { 24, 16, 42, 1, 50, 10, 48, 17, 33, 43, 24, 48, 21, 55, 31, 42, 10, 21, 63, 35, 49, 6, 33, 13, 41, 53, 10, 20, 60, 6, 53, 26, 12, 41, 22, 60, 14, 28, 63, 33, 49, 3, 45, 16, 48, 26, 14, 46, 18, 30, 35, 26, 8, 50, 29, 51, 25, 57, 12, 47, 53, 9, 62, 20, 54, 2, 36, 15, 40, 28, 33, 13, 38, 24, 46, 1, 29, 56, 33, 20, 44, 24, 41, 26, 57, 20, 63, 8, 30, 55, 5, 41, 62, 8, 34, 2, 37, 10, 19, 6, 37, 1, 53, 23, 5, 27, 58, 22, 43, 12, 50, 26, 9, 34, 54, 32, 49, 1, 59, 37, 22, 46, 25, 36, 51, 15, 54, 46 }, + { 52, 7, 45, 33, 26, 58, 14, 60, 7, 54, 3, 58, 8, 34, 14, 5, 59, 30, 18, 44, 8, 22, 48, 62, 3, 26, 55, 38, 23, 16, 39, 1, 62, 24, 49, 9, 53, 19, 46, 7, 19, 60, 31, 58, 2, 34, 53, 7, 59, 2, 62, 42, 46, 19, 36, 11, 44, 4, 38, 28, 1, 43, 32, 51, 12, 29, 56, 22, 52, 2, 62, 49, 22, 60, 14, 35, 63, 5, 25, 57, 14, 53, 4, 46, 18, 31, 42, 22, 47, 20, 58, 31, 16, 43, 23, 54, 30, 42, 52, 57, 29, 49, 30, 13, 45, 48, 16, 55, 6, 63, 1, 44, 14, 58, 19, 47, 15, 24, 51, 34, 6, 55, 5, 63, 20, 41, 21, 9 }, + { 30, 62, 18, 55, 5, 23, 39, 29, 49, 30, 15, 36, 28, 46, 60, 25, 39, 46, 4, 32, 61, 40, 15, 30, 36, 45, 14, 2, 49, 33, 57, 45, 18, 32, 3, 45, 30, 2, 35, 52, 40, 27, 13, 21, 38, 63, 20, 28, 37, 23, 16, 10, 13, 55, 2, 62, 21, 32, 60, 17, 58, 23, 5, 40, 16, 48, 7, 45, 10, 26, 43, 19, 6, 31, 52, 21, 39, 16, 48, 9, 37, 28, 36, 55, 7, 48, 3, 59, 15, 45, 25, 1, 53, 13, 47, 7, 62, 15, 4, 25, 12, 41, 18, 60, 38, 11, 34, 19, 39, 31, 29, 56, 23, 42, 3, 27, 60, 41, 8, 16, 61, 29, 43, 9, 32, 2, 60, 34 }, + { 3, 38, 13, 37, 52, 44, 2, 19, 12, 42, 63, 19, 40, 1, 20, 50, 12, 55, 15, 56, 27, 1, 54, 11, 57, 18, 32, 63, 44, 4, 29, 13, 37, 61, 35, 16, 42, 57, 12, 22, 6, 55, 43, 10, 50, 5, 44, 11, 48, 52, 34, 58, 28, 41, 38, 30, 7, 52, 11, 49, 30, 14, 45, 27, 59, 34, 21, 38, 32, 58, 11, 36, 56, 42, 9, 41, 3, 54, 31, 42, 0, 60, 16, 11, 39, 24, 52, 33, 6, 36, 10, 40, 32, 60, 26, 20, 39, 28, 47, 34, 63, 8, 54, 3, 24, 56, 0, 51, 13, 47, 16, 40, 7, 35, 52, 11, 36, 4, 57, 30, 39, 13, 18, 50, 58, 28, 12, 48 }, + { 57, 24, 49, 21, 10, 31, 61, 36, 56, 0, 22, 53, 11, 56, 32, 7, 36, 27, 41, 9, 46, 19, 34, 42, 25, 7, 50, 9, 28, 21, 54, 8, 50, 7, 27, 59, 10, 25, 48, 62, 37, 0, 33, 58, 25, 18, 32, 61, 0, 15, 45, 5, 50, 3, 23, 55, 47, 17, 40, 6, 60, 34, 53, 8, 41, 0, 61, 13, 54, 4, 46, 28, 0, 17, 48, 27, 58, 13, 23, 61, 33, 21, 50, 30, 62, 8, 14, 29, 56, 27, 61, 49, 17, 2, 44, 11, 51, 0, 59, 17, 40, 20, 32, 47, 36, 21, 42, 28, 60, 4, 54, 10, 59, 17, 30, 62, 21, 43, 26, 48, 0, 56, 36, 25, 8, 44, 39, 17 }, + { 10, 42, 4, 59, 27, 47, 8, 23, 51, 32, 45, 6, 37, 26, 48, 43, 62, 0, 21, 53, 38, 12, 51, 5, 60, 47, 24, 37, 59, 15, 35, 47, 22, 55, 0, 50, 21, 40, 6, 29, 15, 52, 24, 8, 41, 55, 13, 29, 40, 56, 24, 31, 19, 33, 61, 15, 0, 35, 24, 42, 21, 2, 19, 57, 24, 15, 30, 50, 20, 25, 40, 16, 57, 34, 61, 8, 29, 45, 6, 49, 11, 47, 2, 44, 19, 57, 38, 50, 12, 42, 21, 4, 35, 52, 28, 56, 23, 36, 13, 45, 4, 52, 27, 14, 6, 62, 9, 45, 21, 37, 25, 46, 33, 49, 0, 44, 7, 53, 13, 19, 53, 31, 3, 47, 15, 56, 22, 51 }, + { 35, 28, 53, 32, 1, 16, 54, 40, 9, 17, 25, 58, 14, 59, 3, 22, 16, 51, 31, 5, 23, 58, 28, 17, 35, 20, 0, 42, 11, 52, 3, 31, 41, 17, 43, 13, 32, 54, 18, 60, 32, 45, 17, 49, 2, 36, 51, 22, 7, 36, 9, 63, 48, 12, 46, 26, 43, 28, 63, 13, 48, 37, 51, 33, 5, 47, 55, 9, 42, 63, 7, 51, 24, 12, 37, 19, 55, 34, 18, 38, 15, 28, 54, 34, 5, 43, 22, 0, 48, 14, 54, 24, 58, 9, 38, 5, 32, 55, 21, 30, 49, 9, 59, 43, 30, 51, 35, 26, 7, 53, 2, 22, 14, 27, 57, 18, 38, 24, 33, 45, 10, 41, 20, 60, 37, 5, 32, 0 }, + { 63, 19, 15, 40, 62, 35, 14, 28, 46, 61, 4, 49, 35, 10, 29, 54, 33, 8, 45, 62, 37, 1, 43, 55, 10, 52, 61, 30, 19, 40, 25, 62, 11, 38, 27, 58, 36, 3, 46, 8, 39, 4, 62, 28, 47, 20, 4, 54, 47, 27, 43, 1, 21, 38, 8, 58, 10, 54, 4, 56, 9, 26, 12, 39, 60, 27, 18, 37, 1, 31, 35, 5, 45, 50, 2, 43, 26, 1, 59, 23, 56, 40, 7, 26, 58, 17, 32, 63, 25, 39, 7, 31, 45, 19, 63, 15, 48, 8, 37, 61, 16, 34, 1, 56, 18, 3, 15, 58, 49, 32, 63, 41, 55, 5, 40, 22, 50, 6, 59, 2, 63, 23, 52, 11, 26, 61, 44, 23 }, + { 11, 56, 46, 6, 22, 43, 58, 3, 34, 21, 38, 30, 18, 44, 52, 13, 41, 57, 17, 28, 14, 49, 25, 7, 33, 39, 26, 6, 56, 48, 1, 20, 56, 5, 46, 9, 19, 51, 30, 25, 56, 21, 35, 14, 57, 42, 16, 33, 10, 57, 17, 59, 41, 25, 53, 37, 20, 40, 30, 18, 31, 62, 44, 22, 3, 44, 11, 48, 23, 53, 18, 60, 29, 22, 62, 15, 53, 47, 10, 41, 3, 19, 52, 36, 13, 46, 10, 35, 3, 61, 41, 16, 1, 50, 26, 42, 18, 46, 2, 25, 54, 20, 39, 23, 47, 31, 41, 12, 38, 17, 8, 19, 31, 48, 12, 61, 9, 54, 29, 35, 15, 38, 6, 43, 34, 14, 7, 47 }, + { 39, 2, 33, 26, 53, 8, 18, 50, 41, 12, 53, 1, 63, 24, 19, 39, 2, 24, 47, 10, 60, 38, 19, 63, 48, 4, 15, 45, 32, 14, 60, 36, 29, 53, 23, 63, 34, 12, 61, 1, 43, 11, 53, 30, 1, 26, 60, 45, 23, 39, 3, 29, 12, 50, 4, 16, 51, 3, 45, 36, 50, 1, 16, 54, 35, 14, 57, 30, 58, 9, 46, 14, 41, 10, 32, 38, 4, 30, 21, 51, 32, 63, 25, 1, 60, 27, 53, 18, 51, 22, 28, 55, 34, 12, 40, 3, 60, 29, 57, 41, 6, 44, 11, 53, 8, 61, 24, 57, 1, 28, 44, 59, 36, 3, 34, 25, 41, 31, 16, 44, 22, 47, 28, 58, 1, 49, 54, 29 }, + { 58, 25, 50, 13, 38, 30, 60, 24, 6, 57, 27, 42, 9, 45, 6, 61, 30, 50, 4, 34, 29, 3, 46, 13, 22, 42, 58, 28, 9, 39, 23, 44, 7, 15, 44, 2, 40, 15, 47, 41, 23, 37, 7, 59, 38, 11, 34, 6, 62, 14, 52, 35, 55, 19, 32, 61, 33, 24, 57, 6, 22, 59, 29, 7, 49, 25, 40, 3, 17, 39, 27, 52, 0, 55, 16, 57, 24, 61, 36, 6, 29, 12, 48, 39, 20, 44, 6, 40, 33, 5, 48, 10, 57, 36, 22, 51, 33, 9, 24, 12, 62, 29, 50, 35, 14, 43, 5, 33, 47, 52, 13, 23, 10, 51, 56, 16, 46, 1, 49, 4, 61, 9, 52, 18, 31, 21, 36, 17 }, + { 19, 42, 9, 48, 2, 44, 11, 37, 48, 20, 33, 16, 55, 35, 49, 15, 37, 20, 59, 16, 53, 22, 56, 31, 50, 11, 34, 54, 16, 51, 4, 49, 33, 53, 21, 28, 56, 24, 31, 9, 52, 16, 48, 24, 44, 13, 51, 20, 31, 49, 18, 6, 34, 2, 44, 14, 47, 8, 15, 43, 13, 41, 33, 52, 20, 61, 7, 51, 34, 62, 4, 20, 36, 33, 43, 8, 46, 13, 53, 17, 45, 42, 9, 31, 52, 11, 30, 56, 13, 59, 17, 44, 27, 6, 62, 11, 43, 17, 49, 38, 26, 2, 16, 27, 58, 21, 54, 18, 26, 5, 35, 61, 43, 27, 7, 39, 14, 58, 37, 55, 20, 33, 13, 40, 62, 10, 55, 5 }, + { 51, 14, 61, 29, 59, 20, 55, 31, 0, 49, 11, 60, 3, 26, 22, 56, 0, 40, 12, 43, 41, 8, 36, 0, 17, 57, 24, 2, 46, 26, 61, 18, 0, 38, 12, 59, 6, 49, 3, 57, 19, 63, 5, 33, 18, 54, 28, 56, 0, 43, 26, 46, 63, 27, 56, 22, 27, 54, 38, 28, 63, 24, 10, 45, 0, 31, 42, 21, 12, 25, 44, 49, 59, 6, 26, 50, 3, 34, 27, 59, 0, 35, 62, 16, 4, 58, 47, 0, 43, 24, 37, 2, 54, 20, 46, 31, 0, 56, 34, 5, 55, 45, 60, 37, 0, 40, 10, 38, 63, 46, 15, 20, 0, 53, 21, 62, 30, 11, 24, 27, 40, 0, 57, 26, 3, 45, 27, 35 }, +}; + +#else +#define DM_WIDTH 8 +#define DM_WIDTH_SHIFT 3 +#define DM_HEIGHT 8 +static const unsigned char DM[8][8] = +{ + { 0, 32, 8, 40, 2, 34, 10, 42 }, + { 48, 16, 56, 24, 50, 18, 58, 26 }, + { 12, 44, 4, 36, 14, 46, 6, 38 }, + { 60, 28, 52, 20, 62, 30, 54, 22 }, + { 3, 35, 11, 43, 1, 33, 9, 41 }, + { 51, 19, 59, 27, 49, 17, 57, 25 }, + { 15, 47, 7, 39, 13, 45, 5, 37 }, + { 63, 31, 55, 23, 61, 29, 53, 21 } +}; +#endif + +static guint32 *DM_565 = NULL; + +static void +xlib_rgb_preprocess_dm_565 (void) +{ + int i; + guint32 dith; + + if (DM_565 == NULL) + { + DM_565 = malloc(sizeof(guint32) * DM_WIDTH * DM_HEIGHT); + for (i = 0; i < DM_WIDTH * DM_HEIGHT; i++) + { + dith = DM[0][i] >> 3; + DM_565[i] = (dith << 20) | dith | (((7 - dith) >> 1) << 10); +#ifdef VERBOSE + printf ("%i %x %x\n", i, dith, DM_565[i]); +#endif + } + } +} + +static void +xlib_rgb_convert_8_d666 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int dith; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 7; + r = ((r * 5) + dith) >> 8; + g = ((g * 5) + (262 - dith)) >> 8; + b = ((b * 5) + dith) >> 8; + obptr[0] = colorcube_d[(r << 6) | (g << 3) | b]; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_8_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int dith; + int rs, gs, bs; + + bptr = buf; + bpl = image->bytes_per_line; + rs = image_info->nred_shades - 1; + gs = image_info->ngreen_shades - 1; + bs = image_info->nblue_shades - 1; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 7; + r = ((r * rs) + dith) >> 8; + g = ((g * gs) + (262 - dith)) >> 8; + b = ((b * bs) + dith) >> 8; + obptr[0] = colorcube_d[(r << 6) | (g << 3) | b]; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_8_indexed (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + unsigned char c; + unsigned char *lut; + + lut = cmap->lut; + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + c = *bp2++; + obptr[0] = lut[c]; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_gray8 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + obptr[0] = (g + ((b + r) >> 1)) >> 1; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_gray8_gray (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int y; + int bpl; + unsigned char *obuf; + unsigned char *bptr; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + memcpy (obuf, bptr, (unsigned int)width); + bptr += rowstride; + obuf += bpl; + } +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define HAIRY_CONVERT_565 +#endif + +#ifdef HAIRY_CONVERT_565 +/* Render a 24-bit RGB image in buf into the GdkImage, without dithering. + This assumes native byte ordering - what should really be done is to + check whether static_image->byte_order is consistent with the _ENDIAN + config flag, and if not, use a different function. + + This one is even faster than the one below - its inner loop loads 3 + words (i.e. 4 24-bit pixels), does a lot of shifting and masking, + then writes 2 words. */ +static void +xlib_rgb_convert_565 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + unsigned char r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + if (((unsigned long)obuf | (unsigned long) bp2) & 3) + { + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + ((guint16 *)obptr)[0] = ((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (b >> 3); + obptr += 2; + } + } + else + { + for (x = 0; x < width - 3; x += 4) + { + guint32 r1b0g0r0; + guint32 g2r2b1g1; + guint32 b3g3r3b2; + + r1b0g0r0 = ((guint32 *)bp2)[0]; + g2r2b1g1 = ((guint32 *)bp2)[1]; + b3g3r3b2 = ((guint32 *)bp2)[2]; + ((guint32 *)obptr)[0] = + ((r1b0g0r0 & 0xf8) << 8) | + ((r1b0g0r0 & 0xfc00) >> 5) | + ((r1b0g0r0 & 0xf80000) >> 19) | + (r1b0g0r0 & 0xf8000000) | + ((g2r2b1g1 & 0xfc) << 19) | + ((g2r2b1g1 & 0xf800) << 5); + ((guint32 *)obptr)[1] = + ((g2r2b1g1 & 0xf80000) >> 8) | + ((g2r2b1g1 & 0xfc000000) >> 21) | + ((b3g3r3b2 & 0xf8) >> 3) | + ((b3g3r3b2 & 0xf800) << 16) | + ((b3g3r3b2 & 0xfc0000) << 3) | + ((b3g3r3b2 & 0xf8000000) >> 11); + bp2 += 12; + obptr += 8; + } + for (; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + ((guint16 *)obptr)[0] = ((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (b >> 3); + obptr += 2; + } + } + bptr += rowstride; + obuf += bpl; + } +} +#else +/* Render a 24-bit RGB image in buf into the GdkImage, without dithering. + This assumes native byte ordering - what should really be done is to + check whether static_image->byte_order is consistent with the _ENDIAN + config flag, and if not, use a different function. + + This routine is faster than the one included with Gtk 1.0 for a number + of reasons: + + 1. Shifting instead of lookup tables (less memory traffic). + + 2. Much less register pressure, especially because shifts are + in the code. + + 3. A memcpy is avoided (i.e. the transfer function). + + 4. On big-endian architectures, byte swapping is avoided. + + That said, it wouldn't be hard to make it even faster - just make an + inner loop that reads 3 words (i.e. 4 24-bit pixels), does a lot of + shifting and masking, then writes 2 words. +*/ +static void +xlib_rgb_convert_565 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + unsigned char r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + ((unsigned short *)obuf)[x] = ((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (b >> 3); + } + bptr += rowstride; + obuf += bpl; + } +} +#endif + +#ifdef HAIRY_CONVERT_565 +static void +xlib_rgb_convert_565_gray (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + unsigned char g; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + if (((unsigned long)obuf | (unsigned long) bp2) & 3) + { + for (x = 0; x < width; x++) + { + g = *bp2++; + ((guint16 *)obptr)[0] = ((g & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (g >> 3); + obptr += 2; + } + } + else + { + for (x = 0; x < width - 3; x += 4) + { + guint32 g3g2g1g0; + + g3g2g1g0 = ((guint32 *)bp2)[0]; + ((guint32 *)obptr)[0] = + ((g3g2g1g0 & 0xf8) << 8) | + ((g3g2g1g0 & 0xfc) << 3) | + ((g3g2g1g0 & 0xf8) >> 3) | + (g3g2g1g0 & 0xf800) << 16 | + ((g3g2g1g0 & 0xfc00) << 11) | + ((g3g2g1g0 & 0xf800) << 5); + ((guint32 *)obptr)[1] = + ((g3g2g1g0 & 0xf80000) >> 8) | + ((g3g2g1g0 & 0xfc0000) >> 13) | + ((g3g2g1g0 & 0xf80000) >> 19) | + (g3g2g1g0 & 0xf8000000) | + ((g3g2g1g0 & 0xfc000000) >> 5) | + ((g3g2g1g0 & 0xf8000000) >> 11); + bp2 += 4; + obptr += 8; + } + for (; x < width; x++) + { + g = *bp2++; + ((guint16 *)obptr)[0] = ((g & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (g >> 3); + obptr += 2; + } + } + bptr += rowstride; + obuf += bpl; + } +} +#else +static void +xlib_rgb_convert_565_gray (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + unsigned char g; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + g = *bp2++; + ((guint16 *)obuf)[x] = ((g & 0xf8) << 8) | + ((g & 0xfc) << 3) | + (g >> 3); + } + bptr += rowstride; + obuf += bpl; + } +} +#endif + +static void +xlib_rgb_convert_565_br (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + unsigned char r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + /* final word is: + g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5 + */ + ((unsigned short *)obuf)[x] = (r & 0xf8) | + ((g & 0xe0) >> 5) | + ((g & 0x1c) << 11) | + ((b & 0xf8) << 5); + } + bptr += rowstride; + obuf += bpl; + } +} + +/* Thanks to Ray Lehtiniemi for a patch that resulted in a ~25% speedup + in this mode. */ +#ifdef HAIRY_CONVERT_565 +static void +xlib_rgb_convert_565_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + /* Now this is what I'd call some highly tuned code! */ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + + width += x_align; + height += y_align; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = y_align; y < height; y++) + { + guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT); + bp2 = bptr; + obptr = obuf; + if (((unsigned long)obuf | (unsigned long) bp2) & 3) + { + for (x = x_align; x < width; x++) + { + gint32 rgb = *bp2++ << 20; + rgb += *bp2++ << 10; + rgb += *bp2++; + rgb += dmp[x & (DM_WIDTH - 1)]; + rgb += 0x10040100 + - ((rgb & 0x1e0001e0) >> 5) + - ((rgb & 0x00070000) >> 6); + + ((unsigned short *)obptr)[0] = + ((rgb & 0x0f800000) >> 12) | + ((rgb & 0x0003f000) >> 7) | + ((rgb & 0x000000f8) >> 3); + obptr += 2; + } + } + else + { + for (x = x_align; x < width - 3; x += 4) + { + guint32 r1b0g0r0; + guint32 g2r2b1g1; + guint32 b3g3r3b2; + guint32 rgb02, rgb13; + + r1b0g0r0 = ((guint32 *)bp2)[0]; + g2r2b1g1 = ((guint32 *)bp2)[1]; + b3g3r3b2 = ((guint32 *)bp2)[2]; + rgb02 = + ((r1b0g0r0 & 0xff) << 20) + + ((r1b0g0r0 & 0xff00) << 2) + + ((r1b0g0r0 & 0xff0000) >> 16) + + dmp[x & (DM_WIDTH - 1)]; + rgb02 += 0x10040100 + - ((rgb02 & 0x1e0001e0) >> 5) + - ((rgb02 & 0x00070000) >> 6); + rgb13 = + ((r1b0g0r0 & 0xff000000) >> 4) + + ((g2r2b1g1 & 0xff) << 10) + + ((g2r2b1g1 & 0xff00) >> 8) + + dmp[(x + 1) & (DM_WIDTH - 1)]; + rgb13 += 0x10040100 + - ((rgb13 & 0x1e0001e0) >> 5) + - ((rgb13 & 0x00070000) >> 6); + ((guint32 *)obptr)[0] = + ((rgb02 & 0x0f800000) >> 12) | + ((rgb02 & 0x0003f000) >> 7) | + ((rgb02 & 0x000000f8) >> 3) | + ((rgb13 & 0x0f800000) << 4) | + ((rgb13 & 0x0003f000) << 9) | + ((rgb13 & 0x000000f8) << 13); + rgb02 = + ((g2r2b1g1 & 0xff0000) << 4) + + ((g2r2b1g1 & 0xff000000) >> 14) + + (b3g3r3b2 & 0xff) + + dmp[(x + 2) & (DM_WIDTH - 1)]; + rgb02 += 0x10040100 + - ((rgb02 & 0x1e0001e0) >> 5) + - ((rgb02 & 0x00070000) >> 6); + rgb13 = + ((b3g3r3b2 & 0xff00) << 12) + + ((b3g3r3b2 & 0xff0000) >> 6) + + ((b3g3r3b2 & 0xff000000) >> 24) + + dmp[(x + 3) & (DM_WIDTH - 1)]; + rgb13 += 0x10040100 + - ((rgb13 & 0x1e0001e0) >> 5) + - ((rgb13 & 0x00070000) >> 6); + ((guint32 *)obptr)[1] = + ((rgb02 & 0x0f800000) >> 12) | + ((rgb02 & 0x0003f000) >> 7) | + ((rgb02 & 0x000000f8) >> 3) | + ((rgb13 & 0x0f800000) << 4) | + ((rgb13 & 0x0003f000) << 9) | + ((rgb13 & 0x000000f8) << 13); + bp2 += 12; + obptr += 8; + } + for (; x < width; x++) + { + gint32 rgb = *bp2++ << 20; + rgb += *bp2++ << 10; + rgb += *bp2++; + rgb += dmp[x & (DM_WIDTH - 1)]; + rgb += 0x10040100 + - ((rgb & 0x1e0001e0) >> 5) + - ((rgb & 0x00070000) >> 6); + + ((unsigned short *)obptr)[0] = + ((rgb & 0x0f800000) >> 12) | + ((rgb & 0x0003f000) >> 7) | + ((rgb & 0x000000f8) >> 3); + obptr += 2; + } + } + bptr += rowstride; + obuf += bpl; + } +} +#else +static void +xlib_rgb_convert_565_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr; + + width += x_align; + height += y_align; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + (ax - x_align) * 2; + + for (y = y_align; y < height; y++) + { + guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT); + unsigned char *bp2 = bptr; + + for (x = x_align; x < width; x++) + { + gint32 rgb = *bp2++ << 20; + rgb += *bp2++ << 10; + rgb += *bp2++; + rgb += dmp[x & (DM_WIDTH - 1)]; + rgb += 0x10040100 + - ((rgb & 0x1e0001e0) >> 5) + - ((rgb & 0x00070000) >> 6); + + ((unsigned short *)obuf)[x] = + ((rgb & 0x0f800000) >> 12) | + ((rgb & 0x0003f000) >> 7) | + ((rgb & 0x000000f8) >> 3); + } + + bptr += rowstride; + obuf += bpl; + } +} +#endif + +static void +xlib_rgb_convert_555 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + unsigned char r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + ((unsigned short *)obuf)[x] = ((r & 0xf8) << 7) | + ((g & 0xf8) << 2) | + (b >> 3); + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_555_br (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + unsigned char r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 2; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + /* final word is: + g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6 + */ + ((unsigned short *)obuf)[x] = ((r & 0xf8) >> 1) | + ((g & 0xc0) >> 6) | + ((g & 0x18) << 10) | + ((b & 0xf8) << 5); + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_888_msb (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int y; + unsigned char *obuf; + int bpl; + unsigned char *bptr; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 3; + for (y = 0; y < height; y++) + { + memcpy (obuf, bptr, (unsigned int)(width + width + width)); + bptr += rowstride; + obuf += bpl; + } +} + +/* todo: optimize this */ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define HAIRY_CONVERT_888 +#endif + +#ifdef HAIRY_CONVERT_888 +static void +xlib_rgb_convert_888_lsb (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 3; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + if (((unsigned long)obuf | (unsigned long) bp2) & 3) + { + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + *obptr++ = b; + *obptr++ = g; + *obptr++ = r; + bp2 += 3; + } + } + else + { + for (x = 0; x < width - 3; x += 4) + { + guint32 r1b0g0r0; + guint32 g2r2b1g1; + guint32 b3g3r3b2; + + r1b0g0r0 = ((guint32 *)bp2)[0]; + g2r2b1g1 = ((guint32 *)bp2)[1]; + b3g3r3b2 = ((guint32 *)bp2)[2]; + ((guint32 *)obptr)[0] = + (r1b0g0r0 & 0xff00) | + ((r1b0g0r0 & 0xff0000) >> 16) | + (((g2r2b1g1 & 0xff00) | (r1b0g0r0 & 0xff)) << 16); + ((guint32 *)obptr)[1] = + (g2r2b1g1 & 0xff0000ff) | + ((r1b0g0r0 & 0xff000000) >> 16) | + ((b3g3r3b2 & 0xff) << 16); + ((guint32 *)obptr)[2] = + (((g2r2b1g1 & 0xff0000) | (b3g3r3b2 & 0xff000000)) >> 16) | + ((b3g3r3b2 & 0xff00) << 16) | + ((b3g3r3b2 & 0xff0000)); + bp2 += 12; + obptr += 12; + } + for (; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + *obptr++ = b; + *obptr++ = g; + *obptr++ = r; + bp2 += 3; + } + } + bptr += rowstride; + obuf += bpl; + } +} +#else +static void +xlib_rgb_convert_888_lsb (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 3; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + obuf[x * 3] = b; + obuf[x * 3 + 1] = g; + obuf[x * 3 + 2] = r; + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} +#endif + +/* convert 24-bit packed to 32-bit unpacked */ +/* todo: optimize this */ +static void +xlib_rgb_convert_0888 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 4; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + ((guint32 *)obuf)[x] = (r << 16) | (g << 8) | b; + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_0888_br (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 4; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + ((guint32 *)obuf)[x] = (b << 24) | (g << 16) | (r << 8); + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_8880_br (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * 4; + for (y = 0; y < height; y++) + { + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + ((guint32 *)obuf)[x] = (b << 16) | (g << 8) | r; + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +/* Generic truecolor/directcolor conversion function. Slow, but these + are oddball modes. */ +static void +xlib_rgb_convert_truecolor_lsb (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + int r_right, r_left; + int g_right, g_left; + int b_right, b_left; + int bpp; + guint32 pixel; + int i; + + r_right = 8 - image_info->red_prec; + r_left = image_info->red_shift; + g_right = 8 - image_info->green_prec; + g_left = image_info->green_shift; + b_right = 8 - image_info->blue_prec; + b_left = image_info->blue_shift; + bpp = image_info->bpp; + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * bpp; + for (y = 0; y < height; y++) + { + obptr = obuf; + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + pixel = ((r >> r_right) << r_left) | + ((g >> g_right) << g_left) | + ((b >> b_right) << b_left); + for (i = 0; i < bpp; i++) + { + *obptr++ = pixel & 0xff; + pixel >>= 8; + } + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_truecolor_lsb_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + int r_right, r_left, r_prec; + int g_right, g_left, g_prec; + int b_right, b_left, b_prec; + int bpp; + guint32 pixel; + int i; + int dith; + int r1, g1, b1; + const unsigned char *dmp; + + r_right = 8 - image_info->red_prec; + r_left = image_info->red_shift; + r_prec = image_info->red_prec; + g_right = 8 - image_info->green_prec; + g_left = image_info->green_shift; + g_prec = image_info->green_prec; + b_right = 8 - image_info->blue_prec; + b_left = image_info->blue_shift; + b_prec = image_info->blue_prec; + bpp = image_info->bpp; + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * bpp; + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + obptr = obuf; + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + dith = dmp[(x_align + x) & (DM_WIDTH - 1)] << 2; + r1 = r + (dith >> r_prec); + g1 = g + ((252 - dith) >> g_prec); + b1 = b + (dith >> b_prec); + pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) | + (((g1 - (g1 >> g_prec)) >> g_right) << g_left) | + (((b1 - (b1 >> b_prec)) >> b_right) << b_left); + for (i = 0; i < bpp; i++) + { + *obptr++ = pixel & 0xff; + pixel >>= 8; + } + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_truecolor_msb (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + int r_right, r_left; + int g_right, g_left; + int b_right, b_left; + int bpp; + guint32 pixel; + int shift, shift_init; + + r_right = 8 - image_info->red_prec; + r_left = image_info->red_shift; + g_right = 8 - image_info->green_prec; + g_left = image_info->green_shift; + b_right = 8 - image_info->blue_prec; + b_left = image_info->blue_shift; + bpp = image_info->bpp; + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * bpp; + shift_init = (bpp - 1) << 3; + for (y = 0; y < height; y++) + { + obptr = obuf; + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + pixel = ((r >> r_right) << r_left) | + ((g >> g_right) << g_left) | + ((b >> b_right) << b_left); + for (shift = shift_init; shift >= 0; shift -= 8) + { + *obptr++ = (pixel >> shift) & 0xff; + } + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_truecolor_msb_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *obuf, *obptr; + int bpl; + unsigned char *bptr, *bp2; + int r, g, b; + int r_right, r_left, r_prec; + int g_right, g_left, g_prec; + int b_right, b_left, b_prec; + int bpp; + guint32 pixel; + int shift, shift_init; + int dith; + int r1, g1, b1; + const unsigned char *dmp; + + r_right = 8 - image_info->red_prec; + r_left = image_info->red_shift; + r_prec = image_info->red_prec; + g_right = 8 - image_info->green_prec; + g_left = image_info->green_shift; + g_prec = image_info->green_prec; + b_right = 8 - image_info->blue_prec; + b_left = image_info->blue_shift; + b_prec = image_info->blue_prec; + bpp = image_info->bpp; + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax * bpp; + shift_init = (bpp - 1) << 3; + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + obptr = obuf; + bp2 = bptr; + for (x = 0; x < width; x++) + { + r = bp2[0]; + g = bp2[1]; + b = bp2[2]; + dith = dmp[(x_align + x) & (DM_WIDTH - 1)] << 2; + r1 = r + (dith >> r_prec); + g1 = g + ((252 - dith) >> g_prec); + b1 = b + (dith >> b_prec); + pixel = (((r1 - (r1 >> r_prec)) >> r_right) << r_left) | + (((g1 - (g1 >> g_prec)) >> g_right) << g_left) | + (((b1 - (b1 >> b_prec)) >> b_right) << b_left); + for (shift = shift_init; shift >= 0; shift -= 8) + { + *obptr++ = (pixel >> shift) & 0xff; + } + bp2 += 3; + } + bptr += rowstride; + obuf += bpl; + } +} + +/* This actually works for depths from 3 to 7 */ +static void +xlib_rgb_convert_4 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int dith; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x += 1) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3; + obptr[0] = colorcube_d[(((r + dith) & 0x100) >> 2) | + (((g + 258 - dith) & 0x100) >> 5) | + (((b + dith) & 0x100) >> 8)]; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +/* This actually works for depths from 3 to 7 */ +static void +xlib_rgb_convert_gray4 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + int shift; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + shift = 9 - image_info->x_visual_info->depth; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + obptr[0] = (g + ((b + r) >> 1)) >> shift; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_gray4_pack (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + int shift; + unsigned char pix0, pix1; + /* todo: this is hardcoded to big-endian. Make endian-agile. */ + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + (ax >> 1); + shift = 9 - image_info->x_visual_info->depth; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x += 2) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + pix0 = (g + ((b + r) >> 1)) >> shift; + r = *bp2++; + g = *bp2++; + b = *bp2++; + pix1 = (g + ((b + r) >> 1)) >> shift; + obptr[0] = (pix0 << 4) | pix1; + obptr++; + } + if (width & 1) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + pix0 = (g + ((b + r) >> 1)) >> shift; + obptr[0] = (pix0 << 4); + } + bptr += rowstride; + obuf += bpl; + } +} + +/* This actually works for depths from 3 to 7 */ +static void +xlib_rgb_convert_gray4_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int prec, right; + int gray; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + ax; + prec = image_info->x_visual_info->depth; + right = 8 - prec; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + gray = (g + ((b + r) >> 1)) >> 1; + gray += (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) >> prec; + obptr[0] = (gray - (gray >> prec)) >> right; + obptr++; + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_gray4_d_pack (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int prec, right; + int gray; + unsigned char pix0, pix1; + /* todo: this is hardcoded to big-endian. Make endian-agile. */ + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + (ax >> 1); + prec = image_info->x_visual_info->depth; + right = 8 - prec; + for (y = 0; y < height; y++) + { + bp2 = bptr; + obptr = obuf; + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + for (x = 0; x < width; x += 2) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + gray = (g + ((b + r) >> 1)) >> 1; + gray += (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) >> prec; + pix0 = (gray - (gray >> prec)) >> right; + r = *bp2++; + g = *bp2++; + b = *bp2++; + gray = (g + ((b + r) >> 1)) >> 1; + gray += (dmp[(x_align + x + 1) & (DM_WIDTH - 1)] << 2) >> prec; + pix1 = (gray - (gray >> prec)) >> right; + obptr[0] = (pix0 << 4) | pix1; + obptr++; + } + if (width & 1) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + gray = (g + ((b + r) >> 1)) >> 1; + gray += (dmp[(x_align + x + 1) & (DM_WIDTH - 1)] << 2) >> prec; + pix0 = (gray - (gray >> prec)) >> right; + obptr[0] = (pix0 << 4); + } + bptr += rowstride; + obuf += bpl; + } +} + +static void +xlib_rgb_convert_1 (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + int x, y; + int bpl; + unsigned char *obuf, *obptr; + unsigned char *bptr, *bp2; + int r, g, b; + const unsigned char *dmp; + int dith; + unsigned char byte; + + bptr = buf; + bpl = image->bytes_per_line; + obuf = ((unsigned char *)image->data) + ay * bpl + (ax >> 3); + byte = 0; /* unnecessary, but it keeps gcc from complaining */ + for (y = 0; y < height; y++) + { + dmp = DM[(y_align + y) & (DM_HEIGHT - 1)]; + bp2 = bptr; + obptr = obuf; + for (x = 0; x < width; x++) + { + r = *bp2++; + g = *bp2++; + b = *bp2++; + dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 4) | 4; + byte += byte + (r + g + g + b + dith > 1020); + if ((x & 7) == 7) + { + obptr[0] = byte; + obptr++; + } + } + if (x & 7) + obptr[0] = byte << (8 - (x & 7)); + bptr += rowstride; + obuf += bpl; + } +} + +/* Returns a pointer to the stage buffer. */ +static unsigned char * +xlib_rgb_ensure_stage (void) +{ + if (image_info->stage_buf == NULL) + image_info->stage_buf = malloc (IMAGE_HEIGHT * STAGE_ROWSTRIDE); + return image_info->stage_buf; +} + +/* This is slow. Speed me up, please. */ +static void +xlib_rgb_32_to_stage (unsigned char *buf, int rowstride, int width, int height) +{ + int x, y; + unsigned char *pi_start, *po_start; + unsigned char *pi, *po; + + pi_start = buf; + po_start = xlib_rgb_ensure_stage (); + for (y = 0; y < height; y++) + { + pi = pi_start; + po = po_start; + for (x = 0; x < width; x++) + { + *po++ = *pi++; + *po++ = *pi++; + *po++ = *pi++; + pi++; + } + pi_start += rowstride; + po_start += STAGE_ROWSTRIDE; + } +} + +/* Generic 32bit RGB conversion function - convert to 24bit packed, then + go from there. */ +static void +xlib_rgb_convert_32_generic (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + xlib_rgb_32_to_stage (buf, rowstride, width, height); + + (*image_info->conv) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +/* Generic 32bit RGB conversion function - convert to 24bit packed, then + go from there. */ +static void +xlib_rgb_convert_32_generic_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + xlib_rgb_32_to_stage (buf, rowstride, width, height); + + (*image_info->conv_d) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +/* This is slow. Speed me up, please. */ +static void +xlib_rgb_gray_to_stage (unsigned char *buf, int rowstride, int width, int height) +{ + int x, y; + unsigned char *pi_start, *po_start; + unsigned char *pi, *po; + unsigned char gray; + + pi_start = buf; + po_start = xlib_rgb_ensure_stage (); + for (y = 0; y < height; y++) + { + pi = pi_start; + po = po_start; + for (x = 0; x < width; x++) + { + gray = *pi++; + *po++ = gray; + *po++ = gray; + *po++ = gray; + } + pi_start += rowstride; + po_start += STAGE_ROWSTRIDE; + } +} + +/* Generic gray conversion function - convert to 24bit packed, then go + from there. */ +static void +xlib_rgb_convert_gray_generic (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + xlib_rgb_gray_to_stage (buf, rowstride, width, height); + + (*image_info->conv) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +static void +xlib_rgb_convert_gray_generic_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + xlib_rgb_gray_to_stage (buf, rowstride, width, height); + + (*image_info->conv_d) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +/* Render grayscale using indexed method. */ +static void +xlib_rgb_convert_gray_cmap (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + (*image_info->conv_indexed) (image, ax, ay, width, height, + buf, rowstride, + x_align, y_align, image_info->gray_cmap); +} + +#if 0 +static void +xlib_rgb_convert_gray_cmap_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + (*image_info->conv_indexed_d) (image, ax, ay, width, height, + buf, rowstride, + x_align, y_align, image_info->gray_cmap); +} +#endif + +/* This is slow. Speed me up, please. */ +static void +xlib_rgb_indexed_to_stage (unsigned char *buf, int rowstride, int width, int height, + XlibRgbCmap *cmap) +{ + int x, y; + unsigned char *pi_start, *po_start; + unsigned char *pi, *po; + int rgb; + + pi_start = buf; + po_start = xlib_rgb_ensure_stage (); + for (y = 0; y < height; y++) + { + pi = pi_start; + po = po_start; + for (x = 0; x < width; x++) + { + rgb = cmap->colors[*pi++]; + *po++ = rgb >> 16; + *po++ = (rgb >> 8) & 0xff; + *po++ = rgb & 0xff; + } + pi_start += rowstride; + po_start += STAGE_ROWSTRIDE; + } +} + +/* Generic gray conversion function - convert to 24bit packed, then go + from there. */ +static void +xlib_rgb_convert_indexed_generic (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, XlibRgbCmap *cmap) +{ + xlib_rgb_indexed_to_stage (buf, rowstride, width, height, cmap); + + (*image_info->conv) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +static void +xlib_rgb_convert_indexed_generic_d (XImage *image, + int ax, int ay, int width, int height, + unsigned char *buf, int rowstride, + int x_align, int y_align, + XlibRgbCmap *cmap) +{ + xlib_rgb_indexed_to_stage (buf, rowstride, width, height, cmap); + + (*image_info->conv_d) (image, ax, ay, width, height, + image_info->stage_buf, STAGE_ROWSTRIDE, + x_align, y_align, cmap); +} + +/* Select a conversion function based on the visual and a + representative image. */ +static void +xlib_rgb_select_conv (XImage *image, ByteOrder byte_order) +{ + int depth, byterev; + int vtype; /* visual type */ + int bpp; /* bits per pixel - from the visual */ + guint32 red_mask, green_mask, blue_mask; + XlibRgbConvFunc conv, conv_d; + XlibRgbConvFunc conv_32, conv_32_d; + XlibRgbConvFunc conv_gray, conv_gray_d; + XlibRgbConvFunc conv_indexed, conv_indexed_d; + Bool mask_rgb, mask_bgr; + + depth = image_info->x_visual_info->depth; + bpp = image->bits_per_pixel; + if (xlib_rgb_verbose) + printf ("Chose visual 0x%x, image bpp=%d, %s first\n", + (int)image_info->x_visual_info->visual->visualid, + bpp, byte_order == LSB_FIRST ? "lsb" : "msb"); + +#if G_BYTE_ORDER == G_BIG_ENDIAN + byterev = (byte_order == LSB_FIRST); +#else + byterev = (byte_order == MSB_FIRST); +#endif + + vtype = image_info->x_visual_info->class; + if (vtype == DirectColor) + vtype = TrueColor; + + red_mask = image_info->x_visual_info->red_mask; + green_mask = image_info->x_visual_info->green_mask; + blue_mask = image_info->x_visual_info->blue_mask; + + mask_rgb = red_mask == 0xff0000 && green_mask == 0xff00 && blue_mask == 0xff; + mask_bgr = red_mask == 0xff && green_mask == 0xff00 && blue_mask == 0xff0000; + + conv = NULL; + conv_d = NULL; + + conv_32 = xlib_rgb_convert_32_generic; + conv_32_d = xlib_rgb_convert_32_generic_d; + + conv_gray = xlib_rgb_convert_gray_generic; + conv_gray_d = xlib_rgb_convert_gray_generic_d; + + conv_indexed = xlib_rgb_convert_indexed_generic; + conv_indexed_d = xlib_rgb_convert_indexed_generic_d; + + image_info->dith_default = FALSE; + + if (image_info->bitmap) + conv = xlib_rgb_convert_1; + else if (bpp == 16 && depth == 16 && !byterev && + red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f) + { + conv = xlib_rgb_convert_565; + conv_d = xlib_rgb_convert_565_d; + conv_gray = xlib_rgb_convert_565_gray; + xlib_rgb_preprocess_dm_565 (); + } + else if (bpp == 16 && depth == 16 && + vtype == TrueColor&& byterev && + red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f) + conv = xlib_rgb_convert_565_br; + + else if (bpp == 16 && depth == 15 && + vtype == TrueColor && !byterev && + red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f) + conv = xlib_rgb_convert_555; + + else if (bpp == 16 && depth == 15 && + vtype == TrueColor && byterev && + red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f) + conv = xlib_rgb_convert_555_br; + + /* I'm not 100% sure about the 24bpp tests - but testing will show*/ + else if (bpp == 24 && depth == 24 && vtype == TrueColor && + ((mask_rgb && byte_order == LSB_FIRST) || + (mask_bgr && byte_order == MSB_FIRST))) + conv = xlib_rgb_convert_888_lsb; + else if (bpp == 24 && depth == 24 && vtype == TrueColor && + ((mask_rgb && byte_order == MSB_FIRST) || + (mask_bgr && byte_order == LSB_FIRST))) + conv = xlib_rgb_convert_888_msb; +#if G_BYTE_ORDER == G_BIG_ENDIAN + else if (bpp == 32 && depth == 24 && vtype == TrueColor && + (mask_rgb && byte_order == LSB_FIRST)) + conv = xlib_rgb_convert_0888_br; + else if (bpp == 32 && depth == 24 && vtype == TrueColor && + (mask_rgb && byte_order == MSB_FIRST)) + conv = xlib_rgb_convert_0888; + else if (bpp == 32 && depth == 24 && vtype == TrueColor && + (mask_bgr && byte_order == MSB_FIRST)) + conv = xlib_rgb_convert_8880_br; +#else + else if (bpp == 32 && depth == 24 && vtype == TrueColor && + (mask_rgb && byte_order == MSB_FIRST)) + conv = xlib_rgb_convert_0888_br; + else if (bpp == 32 && (depth == 32 || depth == 24) && vtype == TrueColor && + (mask_rgb && byte_order == LSB_FIRST)) + conv = xlib_rgb_convert_0888; + else if (bpp == 32 && depth == 24 && vtype == TrueColor && + (mask_bgr && byte_order == LSB_FIRST)) + conv = xlib_rgb_convert_8880_br; +#endif + + else if (vtype == TrueColor && byte_order == LSB_FIRST) + { + conv = xlib_rgb_convert_truecolor_lsb; + conv_d = xlib_rgb_convert_truecolor_lsb_d; + } + else if (vtype == TrueColor && byte_order == MSB_FIRST) + { + conv = xlib_rgb_convert_truecolor_msb; + conv_d = xlib_rgb_convert_truecolor_msb_d; + } + else if (bpp == 8 && depth == 8 && (vtype == PseudoColor +#ifdef ENABLE_GRAYSCALE + || vtype == GrayScale +#endif + )) + { + image_info->dith_default = TRUE; + conv = xlib_rgb_convert_8; + if (vtype != GrayScale) + { + if (image_info->nred_shades == 6 && + image_info->ngreen_shades == 6 && + image_info->nblue_shades == 6) + conv_d = xlib_rgb_convert_8_d666; + else + conv_d = xlib_rgb_convert_8_d; + } + conv_indexed = xlib_rgb_convert_8_indexed; + conv_gray = xlib_rgb_convert_gray_cmap; + } + else if (bpp == 8 && depth == 8 && (vtype == StaticGray +#ifdef not_ENABLE_GRAYSCALE + || vtype == GrayScale +#endif + )) + { + conv = xlib_rgb_convert_gray8; + conv_gray = xlib_rgb_convert_gray8_gray; + } + else if (bpp == 8 && depth < 8 && depth >= 2 && + (vtype == StaticGray + || vtype == GrayScale)) + { + conv = xlib_rgb_convert_gray4; + conv_d = xlib_rgb_convert_gray4_d; + } + else if (bpp == 8 && depth < 8 && depth >= 3) + { + conv = xlib_rgb_convert_4; + } + else if (bpp == 4 && depth <= 4 && depth >= 2 && + (vtype == StaticGray + || vtype == GrayScale)) + { + conv = xlib_rgb_convert_gray4_pack; + conv_d = xlib_rgb_convert_gray4_d_pack; + } + + if (conv_d == NULL) + conv_d = conv; + + image_info->conv = conv; + image_info->conv_d = conv_d; + + image_info->conv_32 = conv_32; + image_info->conv_32_d = conv_32_d; + + image_info->conv_gray = conv_gray; + image_info->conv_gray_d = conv_gray_d; + + image_info->conv_indexed = conv_indexed; + image_info->conv_indexed_d = conv_indexed_d; +} + +static int horiz_idx; +static int horiz_y = IMAGE_HEIGHT; +static int vert_idx; +static int vert_x = IMAGE_WIDTH; +static int tile_idx; +static int tile_x = IMAGE_WIDTH; +static int tile_y1 = IMAGE_HEIGHT; +static int tile_y2 = IMAGE_HEIGHT; + +#ifdef VERBOSE +static int sincelast; +#endif + +/* Defining NO_FLUSH can cause inconsistent screen updates, but is useful + for performance evaluation. */ + +#undef NO_FLUSH + +static int +xlib_rgb_alloc_scratch_image (void) +{ + if (static_image_idx == N_IMAGES) + { +#ifndef NO_FLUSH + XFlush(image_info->display); +#endif +#ifdef VERBOSE + printf ("flush, %d puts since last flush\n", sincelast); + sincelast = 0; +#endif + static_image_idx = 0; + horiz_y = IMAGE_HEIGHT; + vert_x = IMAGE_WIDTH; + tile_x = IMAGE_WIDTH; + tile_y1 = tile_y2 = IMAGE_HEIGHT; + } + return static_image_idx++; +} + +static XImage * +xlib_rgb_alloc_scratch (int width, int height, int *ax, int *ay) +{ + XImage *image; + int idx; + + if (width >= (IMAGE_WIDTH >> 1)) + { + if (height >= (IMAGE_HEIGHT >> 1)) + { + idx = xlib_rgb_alloc_scratch_image (); + *ax = 0; + *ay = 0; + } + else + { + if (height + horiz_y > IMAGE_HEIGHT) + { + horiz_idx = xlib_rgb_alloc_scratch_image (); + horiz_y = 0; + } + idx = horiz_idx; + *ax = 0; + *ay = horiz_y; + horiz_y += height; + } + } + else + { + if (height >= (IMAGE_HEIGHT >> 1)) + { + if (width + vert_x > IMAGE_WIDTH) + { + vert_idx = xlib_rgb_alloc_scratch_image (); + vert_x = 0; + } + idx = vert_idx; + *ax = vert_x; + *ay = 0; + /* using 3 and -4 would be slightly more efficient on 32-bit machines + with > 1bpp displays */ + vert_x += (width + 7) & -8; + } + else + { + if (width + tile_x > IMAGE_WIDTH) + { + tile_y1 = tile_y2; + tile_x = 0; + } + if (height + tile_y1 > IMAGE_HEIGHT) + { + tile_idx = xlib_rgb_alloc_scratch_image (); + tile_x = 0; + tile_y1 = 0; + tile_y2 = 0; + } + if (height + tile_y1 > tile_y2) + tile_y2 = height + tile_y1; + idx = tile_idx; + *ax = tile_x; + *ay = tile_y1; + tile_x += (width + 7) & -8; + } + } + image = static_image[idx]; +#ifdef VERBOSE + printf ("index %d, x %d, y %d (%d x %d)\n", idx, *ax, *ay, width, height); + sincelast++; +#endif + return image; +} + +static void +xlib_draw_rgb_image_core (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + unsigned char *buf, + int pixstride, + int rowstride, + XlibRgbConvFunc conv, + XlibRgbCmap *cmap, + int xdith, + int ydith) +{ + int ay, ax; + int xs0, ys0; + XImage *image; + int width1, height1; + unsigned char *buf_ptr; + + if (image_info->bitmap) + { + if (image_info->own_gc == 0) + { + XColor color; + + image_info->own_gc = XCreateGC(image_info->display, + drawable, + 0, NULL); + color.pixel = WhitePixel(image_info->display, + image_info->screen_num); + XSetForeground(image_info->display, image_info->own_gc, color.pixel); + color.pixel = BlackPixel(image_info->display, + image_info->screen_num); + XSetBackground(image_info->display, image_info->own_gc, color.pixel); + } + gc = image_info->own_gc; + } + for (ay = 0; ay < height; ay += IMAGE_HEIGHT) + { + height1 = MIN (height - ay, IMAGE_HEIGHT); + for (ax = 0; ax < width; ax += IMAGE_WIDTH) + { + width1 = MIN (width - ax, IMAGE_WIDTH); + buf_ptr = buf + ay * rowstride + ax * pixstride; + + image = xlib_rgb_alloc_scratch (width1, height1, &xs0, &ys0); + + conv (image, xs0, ys0, width1, height1, buf_ptr, rowstride, + x + ax + xdith, y + ay + ydith, cmap); + +#ifndef DONT_ACTUALLY_DRAW + XPutImage(image_info->display, drawable, gc, image, + xs0, ys0, x + ax, y + ay, (unsigned int)width1, (unsigned int)height1); +#endif + } + } +} + + +/** + * xlib_draw_rgb_image: + * @drawable: Destination drawable. + * @gc: A graphic context. + * @x: Leftmost coordinate of the destination rectangle. + * @y: Upper coordinate of the destination rectangle. + * @width: Width of the destination rectangle, in pixels. + * @height: Height of the destination rectangle, in pixels. + * @dith: Dithering method to use. + * @rgb_buf: Pointer to the pixel in the RGB buffer that corresponds to the + * upper-left corner of the rectangular region to render. + * @rowstride: Offset between pixel rows in the RGB buffer, in bytes. + * + * Renders an RGB buffer to a drawable. Pixels are specified as RGB triplets + * with 8 bits per channel. An image will thus look like an RGBRGBRGBRGB + * sequence of 8-bit values. This function does not let you specify dither + * offsets; applications that need to render partial regions of a buffer to + * build the final image should use xlib_draw_rgb_image_dithalign() instead. + **/ +void +xlib_draw_rgb_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *rgb_buf, + int rowstride) +{ + if (dith == XLIB_RGB_DITHER_NONE || (dith == XLIB_RGB_DITHER_NORMAL && + !image_info->dith_default)) + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + rgb_buf, 3, rowstride, image_info->conv, NULL, + 0, 0); + else + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + rgb_buf, 3, rowstride, image_info->conv_d, NULL, + 0, 0); +} + +/** + * xlib_draw_rgb_image_dithalign: + * @drawable: Destination drawable. + * @gc: A graphic context. + * @x: Leftmost coordinate of the destination rectangle. + * @y: Upper coordinate of the destination rectangle. + * @width: Width of the destination rectangle, in pixels. + * @height: Height of the destination rectangle, in pixels. + * @dith: Dithering method to use. + * @rgb_buf: Pointer to the pixel in the RGB buffer that corresponds to the + * upper-left corner of the rectangular region to render. + * @rowstride: Offset between pixel rows in the RGB buffer, in bytes. + * @xdith: X offset for the dither mask. + * @ydith: Y offset for the dither mask. + * + * Renders an RGB buffer to a drawable. Pixels are specified as RGB triplets + * with 8 bits per channel. An image will thus look like an RGBRGBRGBRGB + * sequence of 8-bit values. This function lets you specify a pair of dither + * offsets. It should be used when you need to render regions of an RGB buffer + * separately to form the final image; the dither offsets let you align the + * dither mask appropriately. + **/ +void +xlib_draw_rgb_image_dithalign (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *rgb_buf, + int rowstride, + int xdith, + int ydith) +{ + if (dith == XLIB_RGB_DITHER_NONE || (dith == XLIB_RGB_DITHER_NORMAL && + !image_info->dith_default)) + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + rgb_buf, 3, rowstride, image_info->conv, NULL, + xdith, ydith); + else + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + rgb_buf, 3, rowstride, image_info->conv_d, NULL, + xdith, ydith); +} + +/** + * xlib_draw_rgb_32_image: + * @drawable: Destination drawable. + * @gc: A graphic context. + * @x: Leftmost coordinate of the destination rectangle. + * @y: Upper coordinate of the destination rectangle. + * @width: Width of the destination rectangle, in pixels. + * @height: Height of the destination rectangle, in pixels. + * @dith: Dithering method to use. + * @buf: Pointer to the pixel in the RGB buffer that corresponds to the + * upper-left corner of the rectangular region to render. + * @rowstride: Offset between pixel rows in the RGB buffer, in bytes. + * + * This function is analogous to xlib_draw_rgb_image(), but it lets you use + * 32-bit RGB buffers with pixels specified as 0xRRGGBB00. The + * least-significant 8 bits are actually discarded. This function can lead to + * faster results than xlib_draw_rgb_image() since the pixels are aligned on + * 32-bit boundaries. + **/ +void +xlib_draw_rgb_32_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride) +{ + if (dith == XLIB_RGB_DITHER_NONE || (dith == XLIB_RGB_DITHER_NORMAL && + !image_info->dith_default)) + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 4, rowstride, + image_info->conv_32, NULL, 0, 0); + else + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 4, rowstride, + image_info->conv_32_d, NULL, 0, 0); +} + +static void +xlib_rgb_make_gray_cmap (XlibRgbInfo *info) +{ + guint32 rgb[256]; + int i; + + for (i = 0; i < 256; i++) + rgb[i] = (i << 16) | (i << 8) | i; + info->gray_cmap = xlib_rgb_cmap_new (rgb, 256); +} + +/** + * xlib_draw_gray_image: + * @drawable: Destination drawable. + * @gc: A graphic context. + * @x: Leftmost coordinate of the destination rectangle. + * @y: Upper coordinate of the destination rectangle. + * @width: Width of the destination rectangle, in pixels. + * @height: Height of thd destination rectangle, in pixels. + * @dith: Dithering method to use. + * @buf: Pointer to the pixel in the grayscale buffer that corresponds to the + * upper-left corner of the rectangular region to render. + * @rowstride: Offset between pixel rows in the grayscale buffer, in pixels. + * + * Renders a grayscale buffer to a drawable. Pixels are specified as 8-bit + * intensity values. An image will thus look as a GGGGGG sequence of 8-bit + * values. + **/ +void +xlib_draw_gray_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride) +{ + if (image_info->bpp == 1 && + image_info->gray_cmap == NULL && + (image_info->x_visual_info->class == PseudoColor || + image_info->x_visual_info->class == GrayScale)) + xlib_rgb_make_gray_cmap (image_info); + + if (dith == XLIB_RGB_DITHER_NONE || (dith == XLIB_RGB_DITHER_NORMAL && + !image_info->dith_default)) + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 1, rowstride, + image_info->conv_gray, NULL, 0, 0); + else + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 1, rowstride, + image_info->conv_gray_d, NULL, 0, 0); +} + +/** + * xlib_rgb_cmap_new: + * @colors: FIXME + * @n_colors: FIXME + * + * FIXME + * + * Return value: FIXME + **/ +XlibRgbCmap * +xlib_rgb_cmap_new (guint32 *colors, int n_colors) +{ + XlibRgbCmap *cmap; + int i, j; + guint32 rgb; + + if (n_colors < 0) + return NULL; + if (n_colors > 256) + return NULL; + cmap = malloc(sizeof(XlibRgbCmap)); + memcpy (cmap->colors, colors, n_colors * sizeof(guint32)); + if (image_info->bpp == 1 && + (image_info->x_visual_info->class == PseudoColor || + image_info->x_visual_info->class == GrayScale)) + for (i = 0; i < n_colors; i++) + { + rgb = colors[i]; + j = ((rgb & 0xf00000) >> 12) | + ((rgb & 0xf000) >> 8) | + ((rgb & 0xf0) >> 4); +#ifdef VERBOSE + printf ("%d %x %x %d\n", i, j, colorcube[j]); +#endif + cmap->lut[i] = colorcube[j]; + } + return cmap; +} + +/** + * xlib_rgb_cmap_free: + * @cmap: An XlibRGB colormap. + * + * Frees an XlibRGB colormap. + **/ +void +xlib_rgb_cmap_free (XlibRgbCmap *cmap) +{ + free (cmap); +} + +/** + * xlib_draw_indexed_image: + * @drawable: FIXME + * @gc: FIXME + * @x: FIXME + * @y: FIXME + * @width: FIXME + * @height: FIXME + * @dith: FIXME + * @buf: FIXME + * @rowstride: FIXME + * @cmap: FIXME + * + * FIXME + **/ +void +xlib_draw_indexed_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride, + XlibRgbCmap *cmap) +{ + if (dith == XLIB_RGB_DITHER_NONE || (dith == XLIB_RGB_DITHER_NORMAL && + !image_info->dith_default)) + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 1, rowstride, + image_info->conv_indexed, cmap, 0, 0); + else + xlib_draw_rgb_image_core (drawable, gc, x, y, width, height, + buf, 1, rowstride, + image_info->conv_indexed_d, cmap, 0, 0); +} + +/** + * xlib_rgb_ditherable: + * + * Queries whether XlibRGB supports dithering for its chosen visual. + * + * Return value: TRUE if dithering can be performed for the visual that XlibRGB + * is using, FALSE otherwise. + **/ +Bool +xlib_rgb_ditherable (void) +{ + return (image_info->conv != image_info->conv_d); +} + +/** + * xlib_rgb_get_cmap: + * + * Queries the X colormap that XlibRGB is using. + * + * Return value: An X colormap. + **/ +Colormap +xlib_rgb_get_cmap (void) +{ + /* xlib_rgb_init (); */ + if (image_info) + return image_info->cmap; + else + return 0; +} + +/** + * xlib_rgb_get_visual: + * + * Queries the visual that XlibRGB is using. + * + * Return value: An X visual. + **/ +Visual * +xlib_rgb_get_visual (void) +{ + /* xlib_rgb_init (); */ + if (image_info) + return image_info->x_visual_info->visual; + else + return 0; +} + +/** + * xlib_rgb_get_visual_info: + * + * Queries the visual info structure for the visual that XlibRGB is using. + * + * Return value: An XVisualInfo structure. + **/ +XVisualInfo * +xlib_rgb_get_visual_info (void) +{ + /* xlib_rgb_init (); */ + if (image_info) + return image_info->x_visual_info; + else + return 0; +} + +/** + * xlib_rgb_get_depth: + * + * Queries the depth of the visual that XlibRGB is using. + * + * Return value: Bit depth. + **/ +int +xlib_rgb_get_depth (void) +{ + XVisualInfo * v = xlib_rgb_get_visual_info(); + + if (v) + { + return v->depth; + } + + return 0; +} + +/** + * xlib_rgb_get_display: + * + * Queries the X display that XlibRGB is using. + * + * Return value: An X display. + **/ +Display * +xlib_rgb_get_display (void) +{ + if (image_info) + return image_info->display; + + return NULL; +} + +/** + * xlib_rgb_get_screen: + * + * Queries the screen that XlibRGB is using. + * + * Return value: An X screen. + **/ +Screen * +xlib_rgb_get_screen (void) +{ + if (image_info) + return image_info->screen; + + return NULL; +} diff --git a/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.h b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.h new file mode 100644 index 000000000..7d0b92bbd --- /dev/null +++ b/contrib/gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.h @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "MPL"); you may not use this file except in + * compliance with the MPL. You may obtain a copy of the MPL at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the MPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL + * for the specific language governing rights and limitations under the + * MPL. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Library General Public License (the "LGPL"), in + * which case the provisions of the LGPL are applicable instead of + * those above. If you wish to allow use of your version of this file + * only under the terms of the LGPL and not to allow others to use + * your version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the LGPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the LGPL. + */ + +/* + * This code is derived from GdkRgb. + * For more information on GdkRgb, see http://www.levien.com/gdkrgb/ + * Raph Levien <raph@acm.org> + */ + +/* Ported by Christopher Blizzard to Xlib. With permission from the + * original authors of this file, the contents of this file are also + * redistributable under the terms of the Mozilla Public license. For + * information about the Mozilla Public License, please see the + * license information at http://www.mozilla.org/MPL/ + */ + +/* This code is copyright the following authors: + * Raph Levien <raph@acm.org> + * Manish Singh <manish@gtk.org> + * Tim Janik <timj@gtk.org> + * Peter Mattis <petm@xcf.berkeley.edu> + * Spencer Kimball <spencer@xcf.berkeley.edu> + * Josh MacDonald <jmacd@xcf.berkeley.edu> + * Christopher Blizzard <blizzard@redhat.com> + * Owen Taylor <otaylor@redhat.com> + * Shawn T. Amundson <amundson@gtk.org> +*/ + + +#ifndef __XLIB_RGB_H__ +#define __XLIB_RGB_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> +#include <X11/Intrinsic.h> + +#include <glib.h> + +typedef struct _XlibRgbCmap XlibRgbCmap; + +struct _XlibRgbCmap { + unsigned int colors[256]; + unsigned char lut[256]; /* for 8-bit modes */ +}; + +void +xlib_rgb_init (Display *display, Screen *screen); +void +xlib_rgb_init_with_depth (Display *display, Screen *screen, int prefDepth); + +unsigned long +xlib_rgb_xpixel_from_rgb (guint32 rgb); + +void +xlib_rgb_gc_set_foreground (GC gc, guint32 rgb); + +void +xlib_rgb_gc_set_background (GC gc, guint32 rgb); + +typedef enum +{ + XLIB_RGB_DITHER_NONE, + XLIB_RGB_DITHER_NORMAL, + XLIB_RGB_DITHER_MAX +} XlibRgbDither; + +void +xlib_draw_rgb_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *rgb_buf, + int rowstride); + +void +xlib_draw_rgb_image_dithalign (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *rgb_buf, + int rowstride, + int xdith, + int ydith); + +void +xlib_draw_rgb_32_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride); + +void +xlib_draw_gray_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride); + +XlibRgbCmap * +xlib_rgb_cmap_new (guint32 *colors, int n_colors); + +void +xlib_rgb_cmap_free (XlibRgbCmap *cmap); + +void +xlib_draw_indexed_image (Drawable drawable, + GC gc, + int x, + int y, + int width, + int height, + XlibRgbDither dith, + unsigned char *buf, + int rowstride, + XlibRgbCmap *cmap); + +/* Below are some functions which are primarily useful for debugging + and experimentation. */ +Bool +xlib_rgb_ditherable (void); + +void +xlib_rgb_set_verbose (Bool verbose); + +/* experimental colormap stuff */ +void +xlib_rgb_set_install (Bool install); + +void +xlib_rgb_set_min_colors (int min_colors); + +Colormap +xlib_rgb_get_cmap (void); + +Visual * +xlib_rgb_get_visual (void); + +XVisualInfo * +xlib_rgb_get_visual_info (void); + +int +xlib_rgb_get_depth (void); + +Display * +xlib_rgb_get_display (void); + +Screen * +xlib_rgb_get_screen (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __XLIB_RGB_H__ */ diff --git a/demos/testpixbuf.c b/demos/testpixbuf.c index c6d5a45c5..f118205e2 100644 --- a/demos/testpixbuf.c +++ b/demos/testpixbuf.c @@ -370,7 +370,8 @@ new_testrgb_window (GdkPixbuf *pixbuf, gchar *title) GtkWidget *button; GtkWidget *drawing_area; gint w, h; - + + g_return_val_if_fail (pixbuf != NULL, NULL); w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); @@ -427,18 +428,34 @@ static gint update_timeout(gpointer data) { ProgressFileStatus *status = data; - gboolean done; - - done = TRUE; + gboolean done, error; + + done = FALSE; + error = FALSE; if (!feof(status->imagefile)) { gint nbytes; nbytes = fread(status->buf, 1, status->readlen, status->imagefile); - done = !gdk_pixbuf_loader_write (GDK_PIXBUF_LOADER (status->loader), status->buf, nbytes); - - } + + error = !gdk_pixbuf_loader_write (GDK_PIXBUF_LOADER (status->loader), status->buf, nbytes); + if (error) { + G_BREAKPOINT(); + } + + } else { /* Really done */ + + GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (status->loader); + new_testrgb_window (pixbuf, "After progressive load"); + done = TRUE; + + } + + if (error) { + g_warning ("Serious error writing to loader"); + done = TRUE; + } if (done) { gtk_widget_queue_draw(*status->rgbwin); diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 7021e4b4f..695d66552 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,14 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * gdk-pixbuf/*.sgml, gdk-pixbuf/tmpl/*.sgml: copy in from 1.0 + + * gdk-pixbuf/gdk-pixbuf-sections.txt: add Xlib sections from 1.0 + tree + + * gdk-pixbuf/Makefile.am: add stuff from 1.0 tree + + * gdk-pixbuf/compiling.sgml: copy from 1.0 tree + 2000-09-26 Havoc Pennington <hp@redhat.com> * gtk/tmpl/gtkrc.sgml: Document stock icon stuff diff --git a/docs/reference/gdk-pixbuf/Makefile.am b/docs/reference/gdk-pixbuf/Makefile.am index f5cd156c1..b39999466 100644 --- a/docs/reference/gdk-pixbuf/Makefile.am +++ b/docs/reference/gdk-pixbuf/Makefile.am @@ -8,12 +8,13 @@ DOC_MAIN_SGML_FILE=gdk-pixbuf.sgml # The directory containing the source code (if it contains documentation). DOC_SOURCE_DIR=$(GDK_PIXBUF_DIR)/gdk-pixbuf +SECOND_DOC_SOURCE_DIR=$(top_srcdir)/contrib/gdk-pixbuf-xlib # Extra options to supply to gtkdoc-fixref FIXXREF_OPTIONS= # Header files to ignore when scanning -IGNORE_HFILES=pixops.h pixops-internal.h +IGNORE_HFILES=pixops.h pixops-internal.h gdk-pixbuf-xlib-private.h # Extra files to add when scanning EXTRA_HFILES= \ @@ -34,12 +35,17 @@ tmpl_sources = \ tmpl/module_interface.sgml \ tmpl/refcounting.sgml \ tmpl/scaling.sgml \ - tmpl/util.sgml + tmpl/util.sgml \ + tmpl/gdk-pixbuf-xlib-from-drawables.sgml \ + tmpl/gdk-pixbuf-xlib-init.sgml \ + tmpl/gdk-pixbuf-xlib-rendering.sgml \ + tmpl/gdk-pixbuf-xlib-rgb.sgml # Extra SGML files that are included by DOC_MAIN_SGML_FILE content_files = \ compiling.sgml \ - gdk-pixbuf.sgml + gdk-pixbuf.sgml \ + porting-from-imlib.sgml #################################### # Everything below here is generic # @@ -71,14 +77,14 @@ endif scan: -(cd $(srcdir) \ - && gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(EXTRA_HFILES)) + && gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --source-dir=$(SECOND_DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(EXTRA_HFILES)) templates: cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) sgml: cd $(srcdir) \ - && gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) + && gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --source-dir=$(SECOND_DOC_SOURCE_DIR) html: test -d $(srcdir)/html || mkdir $(srcdir)/html diff --git a/docs/reference/gdk-pixbuf/compiling.sgml b/docs/reference/gdk-pixbuf/compiling.sgml index dc335ef6d..6224909f8 100644 --- a/docs/reference/gdk-pixbuf/compiling.sgml +++ b/docs/reference/gdk-pixbuf/compiling.sgml @@ -1,25 +1,22 @@ <appendix id="compiling"> - <title>Compiling the <application>gdk-pixbuf</application> - library</title> + <title>Compiling the &gdk-pixbuf; library</title> <para> This appendix describes the special options you can use while - compiling the <application>gdk-pixbuf</application> library. + compiling the &gdk-pixbuf; library. </para> <sect1 id="building"> <title>Building the Library</title> <para> - The <application>gdk-pixbuf</application> library uses the - standard GNU build system, using - <application>autoconf</application> for package configuration - and resolving portability issues, + The &gdk-pixbuf; library uses the standard GNU build system, + using <application>autoconf</application> for package + configuration and resolving portability issues, <application>automake</application> for building makefiles that comply with the GNU Coding Standards, and <application>libtool</application> for building shared libraries on multiple platforms. The normal sequence for - compiling and installing the - <application>gdk-pixbuf</application> library is thus: + compiling and installing the &gdk-pixbuf; library is thus: <literallayout> <userinput>./configure</userinput> @@ -43,9 +40,8 @@ <para> In addition to the normal options, the - <command>configure</command> script in the - <application>gdk-pixbuf</application> library supports these - additional arguments: + <command>configure</command> script in the &gdk-pixbuf; + library supports these additional arguments: <cmdsynopsis> <command>configure</command> @@ -67,15 +63,13 @@ <systemitem>--enable-modules</systemitem></title> <para> - Normally <application>gdk-pixbuf</application> will try to - build the image file format loaders as little shared - libraries that are loaded on demand. The - <systemitem>--disable-modules</systemitem> argument - indicates that they should all be built statically into the - <application>gdk-pixbuf</application> library instead. This - is useful for people who need to produce statically-linked - binaries. If neither - <systemitem>--disable-modules</systemitem> nor + Normally &gdk-pixbuf; will try to build the image file + format loaders as little shared libraries that are loaded on + demand. The <systemitem>--disable-modules</systemitem> + argument indicates that they should all be built statically + into the &gdk-pixbuf; library instead. This is useful for + people who need to produce statically-linked binaries. If + neither <systemitem>--disable-modules</systemitem> nor <systemitem>--enable-modules</systemitem> is specified, then the <command>configure</command> script will try to auto-detect whether shared modules work on your system. @@ -91,11 +85,11 @@ to auto-detect whether the <application>gtk-doc</application> package is installed. If it is, then it will use it to extract and build the - documentation for the <application>gdk-pixbuf</application> - library. These options can be used to explicitly control - whether gtk-doc should be used or not. If it is not used, - the distributed, pre-generated HTML files will be installed - instead of building them on your machine. + documentation for the &gdk-pixbuf; library. These options + can be used to explicitly control whether gtk-doc should be + used or not. If it is not used, the distributed, + pre-generated HTML files will be installed instead of + building them on your machine. </para> </formalpara> </sect1> diff --git a/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt b/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt index 51192a064..39fc15ddc 100644 --- a/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt +++ b/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt @@ -140,4 +140,50 @@ GdkPixbufModule gdk_pixbuf_get_module gdk_pixbuf_get_named_module gdk_pixbuf_load_module -</SECTION>
\ No newline at end of file +</SECTION> + +<SECTION> +<FILE>gdk-pixbuf-xlib-init</FILE> +gdk_pixbuf_xlib_init +gdk_pixbuf_xlib_init_with_depth +</SECTION> + +<SECTION> +<FILE>gdk-pixbuf-xlib-rendering</FILE> +gdk_pixbuf_xlib_render_threshold_alpha +gdk_pixbuf_xlib_render_to_drawable +gdk_pixbuf_xlib_render_to_drawable_alpha +gdk_pixbuf_xlib_render_pixmap_and_mask +</SECTION> + +<SECTION> +<FILE>gdk-pixbuf-xlib-from-drawables</FILE> +gdk_pixbuf_xlib_get_from_drawable +</SECTION> + +<SECTION> +<FILE>gdk-pixbuf-xlib-rgb</FILE> +XlibRgbCmap +XlibRgbDither +xlib_rgb_init +xlib_rgb_init_with_depth +xlib_rgb_gc_set_foreground +xlib_rgb_gc_set_background +xlib_draw_rgb_image +xlib_draw_rgb_image_dithalign +xlib_draw_rgb_32_image +xlib_draw_gray_image +xlib_rgb_cmap_new +xlib_rgb_cmap_free +xlib_draw_indexed_image +xlib_rgb_ditherable +xlib_rgb_set_verbose +xlib_rgb_set_install +xlib_rgb_set_min_colors +xlib_rgb_get_cmap +xlib_rgb_get_visual +xlib_rgb_get_visual_info +xlib_rgb_get_depth +xlib_rgb_get_display +xlib_rgb_get_screen +</SECTION> diff --git a/docs/reference/gdk-pixbuf/gdk-pixbuf.sgml b/docs/reference/gdk-pixbuf/gdk-pixbuf.sgml index 16252c70a..60907f135 100644 --- a/docs/reference/gdk-pixbuf/gdk-pixbuf.sgml +++ b/docs/reference/gdk-pixbuf/gdk-pixbuf.sgml @@ -1,23 +1,28 @@ -<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ -<!entity gdk-pixbuf-Initialization-and-Versions SYSTEM "sgml/initialization_versions.sgml"> +<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN"[ + <!entity gdk-pixbuf-gdk-pixbuf SYSTEM "sgml/gdk-pixbuf.sgml"> <!entity gdk-pixbuf-refcounting SYSTEM "sgml/refcounting.sgml"> <!entity gdk-pixbuf-file-loading SYSTEM "sgml/file-loading.sgml"> <!entity gdk-pixbuf-creating SYSTEM "sgml/creating.sgml"> -<!entity gdk-pixbuf-rendering SYSTEM "sgml/rendering.sgml"> <!entity gdk-pixbuf-scaling SYSTEM "sgml/scaling.sgml"> -<!entity gdk-pixbuf-from-drawables SYSTEM "sgml/from-drawables.sgml"> <!entity gdk-pixbuf-util SYSTEM "sgml/util.sgml"> <!entity gdk-pixbuf-animation SYSTEM "sgml/animation.sgml"> -<!entity gdk-pixbuf-Module-Interface SYSTEM "sgml/module_interface.sgml"> <!entity GdkPixbufLoader SYSTEM "sgml/gdk-pixbuf-loader.sgml"> -<!entity GnomeCanvasPixbuf SYSTEM "sgml/gnome-canvas-pixbuf.sgml"> +<!entity gdk-pixbuf-gdk-pixbuf-xlib-init SYSTEM "sgml/gdk-pixbuf-xlib-init.sgml"> +<!entity gdk-pixbuf-gdk-pixbuf-xlib-rendering SYSTEM "sgml/gdk-pixbuf-xlib-rendering.sgml"> +<!entity gdk-pixbuf-gdk-pixbuf-xlib-from-drawables SYSTEM "sgml/gdk-pixbuf-xlib-from-drawables.sgml"> +<!entity gdk-pixbuf-gdk-pixbuf-xlib-rgb SYSTEM "sgml/gdk-pixbuf-xlib-rgb.sgml"> + +<!entity Porting-From-Imlib SYSTEM "porting-from-imlib.sgml"> <!entity Compiling SYSTEM "compiling.sgml"> + +<!entity gdk-pixbuf "<application>gdk-pixbuf</application>"> +<!entity Imlib "<application>Imlib</application>"> ]> <book id="index"> <bookinfo> - <title>The <application>gdk-pixbuf</application> Library</title> + <title>The &gdk-pixbuf; Library</title> <authorgroup> <author> @@ -32,24 +37,53 @@ </authorgroup> <copyright> - <year>1999</year> + <year>2000</year> <holder>The Free Software Foundation</holder> </copyright> + + <legalnotice> + <para> + Permission is granted to copy, distribute and/or modify this + document under the terms of the <citetitle>GNU Free + Documentation License</citetitle>, Version 1.1 or any later + version published by the Free Software Foundation with no + Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. You may obtain a copy of the <citetitle>GNU Free + Documentation License</citetitle> from the Free Software + Foundation by visiting <ulink type="http" + url="http://www.fsf.org">their Web site</ulink> or by writing + to: + + <address> + The Free Software Foundation, Inc., + <street>59 Temple Place</street> - Suite 330, + <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>, + <country>USA</country> + </address> + </para> + + <para> + Many of the names used by companies to distinguish their + products and services are claimed as trademarks. Where those + names appear in any GNOME documentation, and those trademarks + are made aware to the members of the GNOME Documentation + Project, the names have been printed in caps or initial caps. + </para> + </legalnotice> </bookinfo> - <reference id="api"> + <reference> <title>API Reference</title> <partintro> <para> This part presents the class and function reference for the - <application>gdk-pixbuf</application> library. Classes are - described together with their methods; individual functions - are grouped by functional group. + &gdk-pixbuf; library. Classes are described together with + their methods; individual functions are grouped by functional + group. </para> </partintro> - &gdk-pixbuf-Initialization-and-Versions; &gdk-pixbuf-gdk-pixbuf; &gdk-pixbuf-refcounting; &gdk-pixbuf-file-loading; @@ -57,15 +91,51 @@ &gdk-pixbuf-scaling; &gdk-pixbuf-util; &gdk-pixbuf-animation; + &GdkPixbufLoader; - &GnomeCanvasPixbuf; - </reference> - <reference id="internals"> - <title>Internals</title> - &gdk-pixbuf-Module-Interface; + &gdk-pixbuf-gdk-pixbuf-xlib-init; + &gdk-pixbuf-gdk-pixbuf-xlib-rendering; + &gdk-pixbuf-gdk-pixbuf-xlib-from-drawables; + &gdk-pixbuf-gdk-pixbuf-xlib-rgb; </reference> + &Porting-From-Imlib; &Compiling; + <!-- License --> + + <appendix id="license"> + <title>License</title> + + <para> + This library is free software; you can redistribute it and/or + modify it under the terms of the <citetitle>GNU Library General + Public License</citetitle> as published by the Free Software + Foundation; either version 2 of the License, or (at your option) + any later version. + </para> + + <para> + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + <citetitle>GNU Library General Public License</citetitle> for + more details. + </para> + + <para> + You may obtain a copy of the <citetitle>GNU Library General + Public License</citetitle> from the Free Software Foundation by + visiting <ulink type="http" url="http://www.fsf.org">their Web + site</ulink> or by writing to: + + <address> + Free Software Foundation, Inc. + <street>59 Temple Place</street> - Suite 330 + <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode> + <country>USA</country> + </address> + </para> + </appendix> </book> diff --git a/docs/reference/gdk-pixbuf/porting-from-imlib.sgml b/docs/reference/gdk-pixbuf/porting-from-imlib.sgml new file mode 100644 index 000000000..b736200cf --- /dev/null +++ b/docs/reference/gdk-pixbuf/porting-from-imlib.sgml @@ -0,0 +1,360 @@ + <appendix> + <title>Porting applications from &Imlib; to &gdk-pixbuf;</title> + + <para> + This appendix contains the basic steps needed to port an + application that uses the &Imlib; library to use &gdk-pixbuf; + instead. + </para> + + <note> + <para> + This appendix refers to version 1 of the &Imlib; library; this + discussion is not relevant to Imlib 2. Also, we discuss the + gdk_imlib API instead of the Xlib-based API. + </para> + </note> + + <!-- Introduction --> + + <sect1> + <title>Introduction</title> + + <para> + Prior to the GNOME 1.2 platform, the &Imlib; library was the + preferred way of loading and rendering images in GNOME + applications. Unfortunately, &Imlib; has important design + limitations that make it hard to write efficient and highly + modular applications. + </para> + + <para> + The &gdk-pixbuf; library was designed as a solution to + &Imlib;'s shortcomings. It provides a simple, orthogonal API + and convenience functions for the most common operations. In + addition, it supports full transparency information for + images, or alpha channel. More importantly, it has + well-defined semantics for memory management through the use + of reference counting; &Imlib; has an intractably complex + memory management mechanism and cache that will make your head + spin. + </para> + </sect1> + + <!-- Differences between Imlib and gdk-pixbuf --> + + <sect1> + <title>Differences between &Imlib; and &gdk-pixbuf;</title> + + <para> + Generally, applications that use &Imlib; do not have to be + changed extensively to use &gdk-pixbuf;; its simple and + flexible API makes things easy. This section describes the + differences between &Imlib; and &gdk-pixbuf;; you should take + these into account when modifying your applications to use + &gdk-pixbuf;. + </para> + + <!-- Initialization --> + + <sect2> + <title>Initialization</title> + + <para> + The &gdk-pixbuf; library does not need to be initialized. + However, if you intend to use the rendering functions or + anything else from the <application>GdkRGB</application> + library, you should call <function>gdk_rgb_init()</function> + after calling <function>gtk_init()</function> or + <function>gnome_init()</function> in your program. + </para> + + <note> + <para> + In GNOME applications you normally don't need to + initialize &Imlib;, as <function>gnome_init()</function> + calls <function>gdk_imlib_init()</function> automatically. + </para> + </note> + </sect2> + + <!-- Memory management --> + + <sect2> + <title>Memory management</title> + + <para> + The &gdk-pixbuf; library provides a simple, well-defined + memory management mechanism for images in the form of + reference counting. This makes it very convenient to use + for large-scale applications that need to share images + between different parts of the program. In stark contrast, + &Imlib; has a terribly complex mechanism of an image and + pixmap cache which makes it very hard for applications to + share image structures between different parts of the + program. Unfortunately this mechanism makes things very + prone to memory leaks and tricky bugs. + </para> + + <para> + The basic principle in &gdk-pixbuf; is that when you obtain + a new <link linkend="GdkPixbuf">GdkPixbuf</link> structure, + it is created with an initial reference count of 1. When + another part of the program wants to keep a reference to the + pixbuf, it should call <link + linkend="gdk-pixbuf-ref">gdk_pixbuf_ref()</link>; this will + increase the reference count by 1. When some part of the + program does not need to keep a reference to a pixbuf + anymore and wants to release the pixbuf, it should call + <link linkend="gdk-pixbuf-unref">gdk_pixbuf_unref()</link>; + this will decrease the reference count by 1. When the + reference count drops to zero, the pixbuf gets destroyed or + <emphasis>finalized</emphasis> and its memory is freed. + </para> + + <para> + For applications that need to implement a cache of loaded + images, &gdk-pixbuf; provides a way to hook to the last + unreference operation of a pixbuf; instead of finalizing the + pixbuf, the user-installed hook can decide to keep it around + in a cache instead. + </para> + + <para> + Finally, &gdk-pixbuf; does not provide a cache of rendered + pixmaps. This is unnecessary for most applications, since + the scaling and rendering functions are quite fast and + applications may need to use subtly different values each + time they call these functions, for example, to take into + account dithering and zooming offsets. + </para> + + <para> + Most applications will simply need to call + <function>gdk_pixbuf_ref()</function> when they want to keep + an extra reference to a pixbuf, and then + <function>gdk_pixbuf_unref()</function> when they are done + with it. + </para> + </sect2> + + <!-- The Rendering Process --> + + <sect2> + <title>The Rendering Process</title> + + <para> + The &gdk-pixbuf; library has the policy of always rendering + pixbufs to Gdk drawables you provide; it will not create + them for you. This is in general more flexible than + &Imlib;'s policy of always creating a pixmap and making you + use that instead. + </para> + + <para> + The disadvantage of always having a pixmap created for you + is that it wastes memory in the X server if you intend to + copy that rendered data onto another drawable, for example, + the final destination window or a temporary pixmap for + drawing. This is the most common case, unfortunately, so + the &Imlib; policy introduces unnecessary copying. + </para> + + <para> + Also, &Imlib; can only render pixmaps that are the whole + size of the source image; you cannot render just a subset + region of the image. This is inconvenient for applications + that need to render small portions at a time, such as + applications that do scrolling. Since the whole image must + be rendered at a time, this can lead to performance and + memory usage problems. + </para> + + <para> + The &gdk-pixbuf; library lets you render any rectangular + region from an image onto any drawable that you provide. + This lets the application have fine control the way images + are rendered. + </para> + </sect2> + </sect1> + + <!-- Converting Applications to gdk-pixbuf --> + + <sect1> + <title>Converting Applications to &gdk-pixbuf;</title> + + <para> + This sections describes the actual changes you need to make in + an &Imlib; program to make it use &gdk-pixbuf; instead. + </para> + + <!-- Image loading and creation --> + + <sect2> + <title>Image loading and creation</title> + + <para> + The &gdk-pixbuf; library can load image files synchronously + (i.e. with a single function call), create images from RGB + data in memory, and as a convenience, it can also create + images from inline XPM data. + </para> + + <para> + To load an image file in a single function call, simply use + <function>gdk_pixbuf_new_from_file()</function>. Note that + this will make the program block until the whole file has + been read. This function effectively replaces + <function>gdk_imlib_load_image()</function>. + </para> + + <para> + If you have RGB data in memory, you can use + <function>gdk_pixbuf_new_from_data()</function> to create a + pixbuf out of it; this is a replacement for + <function>gdk_imlib_create_image_from_data()</function>. + &gdk-pixbuf; does not copy the image data; it is up to you + to define the ownership policy by providing a destroy + notification function that will be called when the image + data needs to be freed. The function you provide can then + free the data or do something else, as appropriate. + </para> + + <para> + As a convenience, you can use the + <function>gdk_pixbuf_new_from_xpm_data()</function> function + to create a pixbuf out of inline XPM data that was compiled + into your C program. This is a replacement for + <function>gdk_imlib_create_image_from_xpm_data()</function>. + </para> + + <para> + After you have created a pixbuf, you can manipulate it in + any way you please and then finally call + <function>gdk_pixbuf_unref()</function> when you are done + with it. This can be thought of as a replacement for + <function>gdk_imlib_destroy_image()</function> but with much + cleaner semantics. + </para> + </sect2> + + <!-- Rendering Images --> + + <sect2> + <title>Rendering Images</title> + + <para> + Applications that use &Imlib; must first call + <function>gdk_imlib_render()</function> to render the whole + image data onto a pixmap that &Imlib; creates. Then they + must copy that pixmap's data into the final destination for + the image. + </para> + + <para> + In contrast, &gdk-pixbuf; provides convenience functions to + render arbitrary rectangular regions of an image onto a + drawable that your application provides. You can use + <function>gdk_pixbuf_render_to_drawable()</function> or + <function>gdk_pixbuf_render_to_drawable_alpha()</function> + to do this; having your application provide the destination + drawable and specify an arbitrary region means your + application has complete control over the way images are + rendered. + </para> + + <para> + As a convenience, &gdk-pixbuf; also provides the + <function>gdk_pixbuf_render_pixmap_and_mask()</function> + function; this will create new pixmap and mask drawables for + a whole pixbuf and render the image data onto them. Only + trivially simple applications should find a use for this + function, since usually you want finer control of how things + are rendered. + </para> + </sect2> + + <!-- Scaling Images --> + + <sect2> + <title>Scaling Images</title> + + <para> + &Imlib; lets you render scaled image data at the time you + call <function>gdk_imlib_render()</function>. Again, this + unfortunately scales and renders the whole image onto a new + pixmap. + </para> + + <para> + &gdk-pixbuf; provides a number of functions that do scaling + of arbitrary regions of a source pixbuf onto a destination + one. These functions can also perform compositing + operations against the data in the destination pixbuf or + against a solid color or a colored checkerboard. + <footnote> + <para> + You can use a colored checkerboard as the background for + compositing when you want to provide a visual indication + that the image has partially opaque areas. This is + normally used in image editing and viewing programs. + </para> + + <para> + Compositing against a single solid color is actually a + special case of a checkerboard; it simply uses checks of + the same color. + </para> + </footnote> + </para> + + <para> + Very simple applications may find it sufficient to use + <function>gdk_pixbuf_scale_simple()</function> or + <function>gdk_pixbuf_composite_color_simple()</function>. + These functions scale the whole source image at a time and + create a new pixbuf with the result. + </para> + + <para> + More sophisticated applications will need to use + <function>gdk_pixbuf_scale()</function>, + <function>gdk_pixbuf_composite()</function>, or + <function>gdk_pixbuf_composite_color()</function> instead. + These functions let you scale and composite an arbitrary + region of the source pixbuf onto a destination pixbuf that + you provide. + </para> + </sect2> + + <!-- Getting Image Data from a Drawable --> + + <sect2> + <title>Getting Image Data from a Drawable</title> + + <para> + &Imlib; lets you create an image by fetching a drawable's + contents from the X server and converting those into RGB + data. This is done with the + <function>gdk_imlib_create_image_from_drawable()</function> + function. + </para> + + <para> + &gdk-pixbuf; provides the + <function>gdk_pixbuf_get_from_drawable()</function> function + instead. It lets you specify a destination pixbuf instead + of always creating a new one for you. + </para> + </sect2> + </sect1> + </appendix> + +<!-- +Local variables: +mode: sgml +sgml-parent-document: ("gdk-pixbuf.sgml" "book" "book" "") +End: +--> + diff --git a/docs/reference/gdk-pixbuf/tmpl/animation.sgml b/docs/reference/gdk-pixbuf/tmpl/animation.sgml index 128863b5b..6a64ac85d 100644 --- a/docs/reference/gdk-pixbuf/tmpl/animation.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/animation.sgml @@ -6,12 +6,11 @@ Animations as multi-frame structures. <!-- ##### SECTION Long_Description ##### --> <para> - The <application>gdk-pixbuf</application> library provides a - simple mechanism to load and represent animations, primarily - animated GIF files. Animations are represented as lists of - #GdkPixbufFrame structures. Each frame structure contains a - #GdkPixbuf structure and information about the frame's overlay - mode and duration. + The &gdk-pixbuf; library provides a simple mechanism to load and + represent animations, primarily animated GIF files. Animations + are represented as lists of #GdkPixbufFrame structures. Each + frame structure contains a #GdkPixbuf structure and information + about the frame's overlay mode and duration. </para> <!-- ##### SECTION See_Also ##### --> diff --git a/docs/reference/gdk-pixbuf/tmpl/file-loading.sgml b/docs/reference/gdk-pixbuf/tmpl/file-loading.sgml index 0a35bd4f4..3f00def6c 100644 --- a/docs/reference/gdk-pixbuf/tmpl/file-loading.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/file-loading.sgml @@ -6,12 +6,11 @@ Loading a pixbuf from a file. <!-- ##### SECTION Long_Description ##### --> <para> - The <application>gdk-pixbuf</application> library provides a - simple mechanism for loading an image from a file in synchronous - fashion. This means that the library takes control of the - application while the file is being loaded; from the user's point - of view, the application will block until the image is done - loading. + The &gdk-pixbuf; library provides a simple mechanism for loading + an image from a file in synchronous fashion. This means that the + library takes control of the application while the file is being + loaded; from the user's point of view, the application will block + until the image is done loading. </para> <para> diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-unused.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-unused.sgml index a8f01a9aa..094a3a188 100644 --- a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-unused.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-unused.sgml @@ -31,6 +31,10 @@ Drawables to Pixbufs </para> +<!-- ##### SECTION ./tmpl/xlib-from-drawables.sgml:Title ##### --> +X Drawables to Pixbufs + + <!-- ##### FUNCTION gdk_pixbuf_render_pixmap_and_mask ##### --> <para> @@ -46,6 +50,21 @@ sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") End: --> +<!-- ##### ARG GnomeCanvasPixbuf:width ##### --> + <para> + Indicates the width the pixbuf will be scaled to. This argument + will only be used if the <link + linkend="GnomeCanvasPixbuf--width-set">width_set</link> argument + is %TRUE. If the <link + linkend="GnomeCanvasPixbuf--width-in-pixels">width_in_pixels</link> + argument is %FALSE, the width will be taken to be in canvas units, + and thus will be scaled along with the canvas item's affine + transformation. If width_in_pixels is %TRUE, the width will be + taken to be in pixels, and will visually remain a constant size + even if the item's affine transformation changes. + </para> + + <!-- ##### FUNCTION gdk_pixbuf_render_to_drawable ##### --> <para> @@ -85,6 +104,43 @@ sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") End: --> +<!-- ##### ARG GnomeCanvasPixbuf:x ##### --> + <para> + Indicates the horizontal translation offset of the pixbuf item's + image. This offset may not actually appear horizontal, since it + will be affected by the item's affine transformation. The default + is 0.0. + </para> + + +<!-- ##### ARG GnomeCanvasPixbuf:y ##### --> + <para> + Indicates the vertical translation offset of the pixbuf item's + image. Works in the same way as the <link + linkend="GnomeCanvasPixbuf--x">x</link> argument. The default is + 0.0. + </para> + + +<!-- ##### SECTION ./tmpl/xlib-init.sgml:Short_Description ##### --> +Initializing the &gdk-pixbuf; Xlib library. + + +<!-- ##### SECTION ./tmpl/xlib-from-drawables.sgml:Long_Description ##### --> + <para> + The functions in this section allow you to take the image data + from an X drawable and dump it into a #GdkPixbuf. This can be + used for screenshots and other special effects. Note that these + operations can be expensive, since the image data has to be + transferred from the X server to the client program and converted. + </para> + + <para> + These functions are analogous to those for the Gdk version of + &gdk-pixbuf;. + </para> + + <!-- ##### FUNCTION gdk_pixbuf_new_from_art_pixbuf ##### --> <para> @@ -93,16 +149,94 @@ End: @art_pixbuf: @Returns: +<!-- ##### SECTION ./tmpl/xlib-init.sgml:See_Also ##### --> + <para> + XlibRGB + </para> + + +<!-- ##### ARG GnomeCanvasPixbuf:y_in_pixels ##### --> + <para> + Works in the same way as the <link + linkend="GnomeCanvasPixbuf--x-in-pixels">x_in_pixels</link> + argument, but controls whether the <link + linkend="GnomeCanvasPixbuf--y">y</link> translation offset is + scaled or not. The default is %FALSE. + </para> + +<!-- +Local variables: +mode: sgml +sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") +End: +--> + + +<!-- ##### SECTION ./tmpl/gnome-canvas-pixbuf.sgml:See_Also ##### --> + <para> + #GnomeCanvas, #GdkPixbuf + </para> + + +<!-- ##### ARG GnomeCanvasPixbuf:pixbuf ##### --> + <para> + Contains a pointer to a #GdkPixbuf structure that will be used by + the pixbuf canvas item as an image source. When a pixbuf is set + its reference count is incremented; if the pixbuf item kept a + pointer to another #GdkPixbuf structure, the reference count of + this structure will be decremented. Also, the GdkPixbuf's + reference count will automatically be decremented when the + #GnomeCanvasPixbuf item is destroyed. When a pixbuf is queried, a + reference count will not be added to the return value; you must do + this yourself if you intend to keep the pixbuf structure around. + </para> + + <!-- ##### ARG GnomeCanvasPixbuf:y_pixels ##### --> <para> </para> +<!-- ##### SECTION ./tmpl/xlib-rgb.sgml:See_Also ##### --> + <para> + GdkRGB + </para> + + +<!-- ##### SECTION ./tmpl/xlib-rendering.sgml:Long_Description ##### --> + <para> + The &gdk-pixbuf; Xlib library provides several convenience + functions to render pixbufs to X drawables. It uses XlibRGB to + render the image data. + </para> + + <para> + These functions are analogous to those for the Gdk version of + &gdk-pixbuf;. + </para> + + <!-- ##### SECTION ./tmpl/gdk-pixbuf-io.sgml:Short_Description ##### --> +<!-- ##### SECTION ./tmpl/gnome-canvas-pixbuf.sgml:Short_Description ##### --> +Canvas item to display #GdkPixbuf images. + + +<!-- ##### ARG GnomeCanvasPixbuf:x_in_pixels ##### --> + <para> + If this argument is %TRUE, the pixbuf's translation with respect + to its logical origin in item-relative coordinates will be in + pixels, that is, the visible offset will not change even if the + item's affine transformation changes. If it is %FALSE, the + pixbuf's translation will be taken to be in canvas units, and thus + will change along with the item's affine transformation. The + default is %FALSE. + </para> + + <!-- ##### SECTION ./tmpl/from-drawables.sgml:Long_Description ##### --> <para> The functions in this section allow you to take the image data @@ -113,12 +247,36 @@ End: </para> +<!-- ##### SECTION ./tmpl/xlib-rgb.sgml:Long_Description ##### --> + <para> + The XlibRGB set of functions is a port of the GdkRGB library to + use plain Xlib and X drawables. You can use these functions to + render RGB buffers into drawables very quickly with high-quality + dithering. + </para> + + +<!-- ##### SECTION ./tmpl/xlib-rgb.sgml:Short_Description ##### --> +Functions for rendering RGB buffers to X drawables. + + +<!-- ##### MACRO GNOME_CANVAS_PIXBUF ##### --> + <para> + Casts a #GtkOjbect to a #GnomeCanvasPixbuf. + </para> + +@obj: A GTK+ object. + <!-- ##### SECTION ./tmpl/gdk-pixbuf-io.sgml:See_Also ##### --> <para> </para> +<!-- ##### SECTION ./tmpl/xlib-rendering.sgml:Short_Description ##### --> +Rendering a pixbuf to an X drawable. + + <!-- ##### FUNCTION gdk_pixbuf_finalize ##### --> <para> @@ -153,6 +311,31 @@ Rendering a pixbuf to a GDK drawable. </para> +<!-- ##### ARG GnomeCanvasPixbuf:width_in_pixels ##### --> + <para> + If this argument is %TRUE, then the width of the pixbuf will be + considered to be in pixels, that is, it will not be visually + scaled even if the item's affine transformation changes. If this + is %FALSE, then the width of the pixbuf will be considered to be + in canvas units, and so will be scaled normally by affine + transformations. The default is %FALSE. + </para> + + +<!-- ##### SECTION ./tmpl/xlib-init.sgml:Long_Description ##### --> + <para> + In addition to the normal Gdk-specific functions, the &gdk-pixbuf; + package provides a small library that lets Xlib-only applications + use #GdkPixbuf structures and render them to X drawables. The + functions in this section are used to initialize the &gdk-pixbuf; + Xlib library. This library must be initialized near the beginning + or the program or before calling any of the other &gdk-pixbuf; + Xlib functions; it cannot be initialized automatically since + Xlib-only applications do not call gdk_rgb_init() like GNOME + applications do. + </para> + + <!-- ##### FUNCTION gdk_pixbuf_get_format ##### --> <para> @@ -161,6 +344,30 @@ Rendering a pixbuf to a GDK drawable. @pixbuf: @Returns: +<!-- ##### ARG GnomeCanvasPixbuf:height_in_pixels ##### --> + <para> + Works in the same way as the <link + linkend="GnomeCanvasPixbuf--width-in-pixels">width_in_pixels</link> + argument. The default is %FALSE. + </para> + + +<!-- ##### SECTION ./tmpl/xlib-rendering.sgml:See_Also ##### --> +<para> + +</para> + + +<!-- ##### ARG GnomeCanvasPixbuf:width_set ##### --> + <para> + Determines whether the <link + linkend="GnomeCanvasPixbuf--width">width</link> argument is taken + into account when scaling the pixbuf item. If this argument is + %FALSE, then the width value of the pixbuf will be used instead. + This argument is %FALSE by default. + </para> + + <!-- ##### FUNCTION gdk_pixbuf_render_to_drawable_alpha ##### --> <para> @@ -180,22 +387,54 @@ Rendering a pixbuf to a GDK drawable. @x_dither: @y_dither: +<!-- ##### SECTION ./tmpl/xlib-init.sgml:Title ##### --> +&gdk-pixbuf; Xlib initialization + + +<!-- ##### SECTION ./tmpl/xlib-from-drawables.sgml:Short_Description ##### --> +Getting parts of an X drawable's image data into a pixbuf. + + +<!-- ##### SECTION ./tmpl/xlib-rgb.sgml:Title ##### --> +XlibRGB + + <!-- ##### ARG GnomeCanvasPixbuf:x_pixels ##### --> <para> </para> +<!-- ##### ARG GnomeCanvasPixbuf:height ##### --> + <para> + Indicates the height the pixbuf will be scaled to. This argument + will only be used if the <link + linkend="GnomeCanvasPixbuf--height-set">height_set</link> argument + is %TRUE. Works in the same way as the <link + linkend="GnomeCanvasPixbuf--width">width</link> argument. + </para> + + <!-- ##### SECTION ./tmpl/from-drawables.sgml:See_Also ##### --> <para> gdk_image_get(). </para> +<!-- ##### SECTION ./tmpl/xlib-from-drawables.sgml:See_Also ##### --> +<para> + +</para> + + <!-- ##### SECTION ./tmpl/rendering.sgml:Title ##### --> Rendering +<!-- ##### SECTION ./tmpl/gnome-canvas-pixbuf.sgml:Title ##### --> +GnomeCanvasPixbuf + + <!-- ##### MACRO GDK_PIXBUF_LOADER ##### --> <para> Casts a #GtkObject to a #GdkPixbufLoader. @@ -216,19 +455,18 @@ Rendering <!-- ##### SECTION ./tmpl/rendering.sgml:Long_Description ##### --> <para> - The <application>gdk-pixbuf</application> library provides several - convenience functions to render pixbufs to GDK drawables. It uses - the GdkRGB to render the image data. + The &gdk-pixbuf; library provides several convenience functions to + render pixbufs to GDK drawables. It uses the GdkRGB to render the + image data. </para> <para> At this point there is not a standard alpha channel extension for the X Window System, so it is not possible to use full opacity information when painting images to arbitrary drawables. The - <application>gdk-pixbuf</application> convenience functions will - threshold the opacity information to create a bi-level clipping - mask (black and white), and use that to draw the image onto a - drawable. + &gdk-pixbuf; convenience functions will threshold the opacity + information to create a bi-level clipping mask (black and white), + and use that to draw the image onto a drawable. </para> <important> @@ -290,6 +528,190 @@ In the future it will do full alpha compositing. </para> +<!-- ##### SECTION ./tmpl/gnome-canvas-pixbuf.sgml:Long_Description ##### --> + <para> + This canvas item displays #GdkPixbuf images. It handles full + affine transformations in both GDK and antialiased modes, and also + supports the <ulink url="http://www.w3.org">W3C</ulink>'s <ulink + url="http://www.w3.org/Graphics/SVG/">SVG</ulink>-like scaling and + translation semantics for absolute pixel values. + </para> + + <para> + #GdkPixbuf structures may be shared among different pixbuf canvas + items; the pixbuf item uses #GdkPixbuf's reference counting + functions for this. + </para> + + <refsect2> + <title>Custom Scaling and Translation</title> + + <para> + In addition to the normal affine transformations supported by + canvas items, the #GnomeCanvasPixbuf item supports independent + object arguments for scaling and translation. This is useful + for explicitly setting a size to which the pixbuf's image will + be scaled, and for specifying translation offsets that take + place in the item's local coordinate system. + </para> + + <para> + By default, the pixbuf canvas item will attain the size in units + of the #GdkPixbuf it contains. If a #GnomeCanvasPixbuf is + configured to use a #GdkPixbuf that has a size of 300 by 200 + pixels, then the pixbuf item will automatically obtain a size of + 300 by 200 units in the item's local coordinate system. If the + item is transformed with a scaling transformation of (0.5, 2.0), + then the final image size will be of 150 by 400 pixels. + </para> + + <para> + To set custom width and height values, you must set the <link + linkend="GnomeCanvasPixbuf--width-set">width_set</link> or <link + linkend="GnomeCanvasPixbuf--height-set">height_set</link> + arguments to %TRUE, and then set the <link + linkend="GnomeCanvasPixbuf--width">width</link> or <link + linkend="GnomeCanvasPixbuf--height">height</link> arguments to + the desired values. The former two arguments control whether + the latter two are used when computing the final image's size; + they are both %FALSE by default so that the pixbuf item will + attain a size in units equal to the size in pixels of the + #GdkPixbuf that the item contains. + </para> + + <para> + The custom translation offsets are controlled by the <link + linkend="GnomeCanvasPixbuf--x">x</link> and <link + linkend="GnomeCanvasPixbuf--y">y</link> arguments. The logical + upper-left vertex of the image will be translated by the + specified distance, aligned with the item's local coordinate + system. + </para> + </refsect2> + + <refsect2> + <title>Absolute Pixel Scaling and Translation</title> + + <para> + The <ulink url="http://www.w3.org/Graphics/SVG/">Scalable Vector + Graphics</ulink> specification (SVG) of the <ulink + url="http://www.w3.org">World Wide Web Consortium</ulink> also + allows images to be translated and scaled by absolute pixel + values that are independent of an item's normal affine + transformation. + </para> + + <para> + Normally, the pixbuf item's translation and scaling arguments + are interpreted in units, so they will be modified by the item's + affine transformation. The <link + linkend="GnomeCanvasPixbuf--width-in-pixels">width_in_pixels</link>, + <link + linkend="GnomeCanvasPixbuf--height-in-pixels">height_in_pixels</link>, + <link + linkend="GnomeCanvasPixbuf--x-in-pixels">x_in_pixels</link>, and + <link + linkend="GnomeCanvasPixbuf--y-in-pixels">y_in_pixels</link> + object arguments can be used to modify this behavior. If one of + these arguments is %TRUE, then the corresponding scaling or + translation value will not be affected lengthwise by the pixbuf + item's affine transformation. + </para> + + <para> + For example, consider a pixbuf item whose size is (300, 200). + If the item is modified with a scaling transformation of (0.5, + 2.0) but the <link + linkend="GnomeCanvasPixbuf--width-in-pixels">width_in_pixels</link> + is set to %TRUE, then the item will appear to be (300, 400) + pixels in size. This means that in this case the item's affine + transformation only applies to the height value, while the width + value is kept in absolute pixels. + </para> + + <para> + Likewise, consider a pixbuf item whose (<link + linkend="GnomeCanvasPixbuf--x">x</link>, <link + linkend="GnomeCanvasPixbuf--y">y</link>) arguments are set to + (30, 40). If the item is then modified by the same scaling + transformation of (0.5, 2.0) but the <link + linkend="GnomeCanvasPixbuf--y-in-pixels">y_in_pixels</link> + argument is set to %TRUE, then the image's upper-left corner + will appear to be at position (15, 40). In this case, the + affine transformation is applied only to the x offset, while the + y offset is kept in absolute pixels. + </para> + + <para> + In short, these arguments control whether a particular dimension + of a pixbuf item is scaled or not in the normal way by the + item's affine transformation. + </para> + </refsect2> + + <refsect2> + <title>Resource Management</title> + + <para> + When you set the #GdkPixbuf structure that a #GnomeCanvasPixbuf + item will use by setting the <link + linkend="GnomeCanvasPixbuf--pixbuf">pixbuf</link> argument, a + reference count will be added to that #GdkPixbuf structure. + When the pixbuf item no longer needs the #GdkPixbuf structure, + such as when the item is destroyed or when a new pixbuf + structure is passed to it, then the old #GdkPixbuf structure + will be automatically unreferenced. + </para> + + <para> + This means that if an application just needs to load a pixbuf + image and set it into a pixbuf canvas item, it can do the + following to ‘forget’ about the pixbuf structure: + + <programlisting> + GdkPixbuf *pixbuf; + GnomeCanvasItem *item; + + pixbuf = gdk_pixbuf_new_from_file ("foo.png"); + g_assert (pixbuf != NULL); + + item = gnome_canvas_item_new (gnome_canvas_root (my_canvas), + gnome_canvas_pixbuf_get_type (), + "pixbuf", pixbuf, + NULL); + gdk_pixbuf_unref (pixbuf); + </programlisting> + </para> + + <para> + After this happens, the reference count of the pixbuf structure + will be 1: the gdk_pixbuf_new_from_file() function creates it + with a reference count of 1, then setting the <link + linkend="GnomeCanvasPixbuf--pixbuf">pixbuf</link> argument of + the #GnomeCanvasPixbuf item increases it to 2, and then it is + decremented to 1 by the call to gdk_pixbuf_unref(). When the + canvas item is destroyed, it will automatically unreference the + pixbuf structure again, causing its reference count to drop to + zero and thus be freed. + </para> + </refsect2> + + +<!-- ##### SECTION ./tmpl/xlib-rendering.sgml:Title ##### --> +Xlib Rendering + + +<!-- ##### ARG GnomeCanvasPixbuf:height_set ##### --> + <para> + Determines whether the <link + linkend="GnomeCanvasPixbuf--height">height</link> argument is + taken into account when scaling the pixbuf item. Works in the + same way as the <link + linkend="GnomeCanvasPixbuf--width-set">width_set</link> argument. + The default is %FALSE. + </para> + + <!-- ##### SECTION ./tmpl/gdk-pixbuf-io.sgml:Title ##### --> gdk-pixbuf-io diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-from-drawables.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-from-drawables.sgml new file mode 100644 index 000000000..fd59f2db6 --- /dev/null +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-from-drawables.sgml @@ -0,0 +1,48 @@ +<!-- ##### SECTION Title ##### --> +X Drawables to Pixbufs + +<!-- ##### SECTION Short_Description ##### --> +Getting parts of an X drawable's image data into a pixbuf. + +<!-- ##### SECTION Long_Description ##### --> + <para> + The functions in this section allow you to take the image data + from an X drawable and dump it into a #GdkPixbuf. This can be + used for screenshots and other special effects. Note that these + operations can be expensive, since the image data has to be + transferred from the X server to the client program and converted. + </para> + + <para> + These functions are analogous to those for the Gdk version of + &gdk-pixbuf;. + </para> + +<!-- ##### SECTION See_Also ##### --> +<para> + +</para> + +<!-- ##### FUNCTION gdk_pixbuf_xlib_get_from_drawable ##### --> +<para> + +</para> + +@dest: +@src: +@cmap: +@visual: +@src_x: +@src_y: +@dest_x: +@dest_y: +@width: +@height: +@Returns: <!-- +Local variables: +mode: sgml +sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") +End: +--> + + diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-init.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-init.sgml new file mode 100644 index 000000000..e841a19b0 --- /dev/null +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-init.sgml @@ -0,0 +1,48 @@ +<!-- ##### SECTION Title ##### --> +&gdk-pixbuf; Xlib initialization + +<!-- ##### SECTION Short_Description ##### --> +Initializing the &gdk-pixbuf; Xlib library. + +<!-- ##### SECTION Long_Description ##### --> + <para> + In addition to the normal Gdk-specific functions, the &gdk-pixbuf; + package provides a small library that lets Xlib-only applications + use #GdkPixbuf structures and render them to X drawables. The + functions in this section are used to initialize the &gdk-pixbuf; + Xlib library. This library must be initialized near the beginning + or the program or before calling any of the other &gdk-pixbuf; + Xlib functions; it cannot be initialized automatically since + Xlib-only applications do not call gdk_rgb_init() like GNOME + applications do. + </para> + +<!-- ##### SECTION See_Also ##### --> + <para> + XlibRGB + </para> + +<!-- ##### FUNCTION gdk_pixbuf_xlib_init ##### --> +<para> + +</para> + +@display: +@screen_num: + + +<!-- ##### FUNCTION gdk_pixbuf_xlib_init_with_depth ##### --> +<para> + +</para> + +@display: +@screen_num: +@prefDepth: <!-- +Local variables: +mode: sgml +sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") +End: +--> + + diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rendering.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rendering.sgml new file mode 100644 index 000000000..46c6ac084 --- /dev/null +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rendering.sgml @@ -0,0 +1,94 @@ +<!-- ##### SECTION Title ##### --> +Xlib Rendering + +<!-- ##### SECTION Short_Description ##### --> +Rendering a pixbuf to an X drawable. + +<!-- ##### SECTION Long_Description ##### --> + <para> + The &gdk-pixbuf; Xlib library provides several convenience + functions to render pixbufs to X drawables. It uses XlibRGB to + render the image data. + </para> + + <para> + These functions are analogous to those for the Gdk version of + &gdk-pixbuf;. + </para> + +<!-- ##### SECTION See_Also ##### --> +<para> + +</para> + +<!-- ##### FUNCTION gdk_pixbuf_xlib_render_threshold_alpha ##### --> +<para> + +</para> + +@pixbuf: +@bitmap: +@src_x: +@src_y: +@dest_x: +@dest_y: +@width: +@height: +@alpha_threshold: + + +<!-- ##### FUNCTION gdk_pixbuf_xlib_render_to_drawable ##### --> +<para> + +</para> + +@pixbuf: +@drawable: +@gc: +@src_x: +@src_y: +@dest_x: +@dest_y: +@width: +@height: +@dither: +@x_dither: +@y_dither: + + +<!-- ##### FUNCTION gdk_pixbuf_xlib_render_to_drawable_alpha ##### --> +<para> + +</para> + +@pixbuf: +@drawable: +@src_x: +@src_y: +@dest_x: +@dest_y: +@width: +@height: +@alpha_mode: +@alpha_threshold: +@dither: +@x_dither: +@y_dither: + + +<!-- ##### FUNCTION gdk_pixbuf_xlib_render_pixmap_and_mask ##### --> +<para> + +</para> + +@pixbuf: +@pixmap_return: +@mask_return: +@alpha_threshold: <!-- +Local variables: +mode: sgml +sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") +End: +--> + + diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rgb.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rgb.sgml new file mode 100644 index 000000000..7ddc62143 --- /dev/null +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-xlib-rgb.sgml @@ -0,0 +1,268 @@ +<!-- ##### SECTION Title ##### --> +XlibRGB + +<!-- ##### SECTION Short_Description ##### --> +Functions for rendering RGB buffers to X drawables. + +<!-- ##### SECTION Long_Description ##### --> + <para> + The XlibRGB set of functions is a port of the GdkRGB library to + use plain Xlib and X drawables. You can use these functions to + render RGB buffers into drawables very quickly with high-quality + dithering. + </para> + +<!-- ##### SECTION See_Also ##### --> + <para> + GdkRGB + </para> + +<!-- ##### STRUCT XlibRgbCmap ##### --> + <para> + FIXME: Describe this. + </para> + +@colors: FIXME. +@lut: FIXME. + +<!-- ##### ENUM XlibRgbDither ##### --> + <para> + These values are used to specify which dithering method should be + used. <symbol>XLIB_RGB_DITHER_NONE</symbol> will use no dithering + and simply map the colors in an RGB buffer to the closest colors + that the display can provide. + <symbol>XLIB_RGB_DITHER_NORMAL</symbol> will provide dithering + only on pseudocolor displays. + <symbol>XLIB_RGB_DITHER_MAX</symbol> will provide dithering on + pseudocolor and 16-bit truecolor or “high color” + displays. + </para> + +@XLIB_RGB_DITHER_NONE: Specifies no dithering. +@XLIB_RGB_DITHER_NORMAL: Specifies dithering only on pseudocolor +displays. +@XLIB_RGB_DITHER_MAX: Specifies dithering on high color displays. + +<!-- ##### FUNCTION xlib_rgb_init ##### --> +<para> + +</para> + +@display: +@screen: + + +<!-- ##### FUNCTION xlib_rgb_init_with_depth ##### --> +<para> + +</para> + +@display: +@screen: +@prefDepth: + + +<!-- ##### FUNCTION xlib_rgb_gc_set_foreground ##### --> +<para> + +</para> + +@gc: +@rgb: + + +<!-- ##### FUNCTION xlib_rgb_gc_set_background ##### --> +<para> + +</para> + +@gc: +@rgb: + + +<!-- ##### FUNCTION xlib_draw_rgb_image ##### --> +<para> + +</para> + +@drawable: +@gc: +@x: +@y: +@width: +@height: +@dith: +@rgb_buf: +@rowstride: + + +<!-- ##### FUNCTION xlib_draw_rgb_image_dithalign ##### --> +<para> + +</para> + +@drawable: +@gc: +@x: +@y: +@width: +@height: +@dith: +@rgb_buf: +@rowstride: +@xdith: +@ydith: + + +<!-- ##### FUNCTION xlib_draw_rgb_32_image ##### --> +<para> + +</para> + +@drawable: +@gc: +@x: +@y: +@width: +@height: +@dith: +@buf: +@rowstride: + + +<!-- ##### FUNCTION xlib_draw_gray_image ##### --> +<para> + +</para> + +@drawable: +@gc: +@x: +@y: +@width: +@height: +@dith: +@buf: +@rowstride: + + +<!-- ##### FUNCTION xlib_rgb_cmap_new ##### --> +<para> + +</para> + +@colors: +@n_colors: +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_cmap_free ##### --> +<para> + +</para> + +@cmap: + + +<!-- ##### FUNCTION xlib_draw_indexed_image ##### --> +<para> + +</para> + +@drawable: +@gc: +@x: +@y: +@width: +@height: +@dith: +@buf: +@rowstride: +@cmap: + + +<!-- ##### FUNCTION xlib_rgb_ditherable ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_set_verbose ##### --> +<para> + +</para> + +@verbose: + + +<!-- ##### FUNCTION xlib_rgb_set_install ##### --> +<para> + +</para> + +@install: + + +<!-- ##### FUNCTION xlib_rgb_set_min_colors ##### --> +<para> + +</para> + +@min_colors: + + +<!-- ##### FUNCTION xlib_rgb_get_cmap ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_get_visual ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_get_visual_info ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_get_depth ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_get_display ##### --> +<para> + +</para> + +@Returns: + + +<!-- ##### FUNCTION xlib_rgb_get_screen ##### --> +<para> + +</para> + +@Returns: <!-- +Local variables: +mode: sgml +sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") +End: +--> + + diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf.sgml index 9decee178..08b549d0f 100644 --- a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf.sgml @@ -18,19 +18,17 @@ Information that describes an image. <!-- ##### ENUM GdkColorspace ##### --> <para> This enumeration defines the color spaces that are supported by - the <application>gdk-pixbuf</application> library. Currently only - RGB is supported. + the &gdk-pixbuf; library. Currently only RGB is supported. </para> @GDK_COLORSPACE_RGB: Indicates a red/green/blue additive color space. <!-- ##### STRUCT GdkPixbuf ##### --> <para> - This is the main structure in the - <application>gdk-pixbuf</application> library. It is used to - represent images. It contains information about the image's pixel - data, its color space, bits per sample, width and height, and the - rowstride or number of bytes between rows. + This is the main structure in the &gdk-pixbuf; library. It is + used to represent images. It contains information about the + image's pixel data, its color space, bits per sample, width and + height, and the rowstride or number of bytes between rows. </para> @parent_instance: diff --git a/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml b/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml index b1719b797..c0a33f2ee 100644 --- a/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml @@ -68,6 +68,7 @@ Module Interface @stop_load: @load_increment: @load_animation: +@save: <!-- ##### FUNCTION gdk_pixbuf_get_module ##### --> <para> diff --git a/docs/reference/gdk-pixbuf/tmpl/scaling.sgml b/docs/reference/gdk-pixbuf/tmpl/scaling.sgml index 0e4cf95a5..a8d41a117 100644 --- a/docs/reference/gdk-pixbuf/tmpl/scaling.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/scaling.sgml @@ -6,12 +6,11 @@ Scaling pixbufs and scaling and compositing pixbufs <!-- ##### SECTION Long_Description ##### --> <para> - The <application>gdk-pixbuf</application> contains functions to - scale pixbufs, to scale pixbufs and composite against an existing - image, and to scale pixbufs and composite against a solid color or - checkerboard. Compositing a checkerboard is a common way to show - an image with an alpha channel in image-viewing and editing - software. + The &gdk-pixbuf; contains functions to scale pixbufs, to scale + pixbufs and composite against an existing image, and to scale + pixbufs and composite against a solid color or checkerboard. + Compositing a checkerboard is a common way to show an image with + an alpha channel in image-viewing and editing software. </para> <para> diff --git a/docs/reference/gdk/gdk-decl.txt b/docs/reference/gdk/gdk-decl.txt index 0d40604f5..297dddb11 100644 --- a/docs/reference/gdk/gdk-decl.txt +++ b/docs/reference/gdk/gdk-decl.txt @@ -2611,6 +2611,31 @@ void <RETURNS>void </RETURNS> PangoContext *context,GdkColormap *colormap </FUNCTION> +<FUNCTION> +<NAME>gdk_pixbuf_render_threshold_alpha</NAME> +<RETURNS>void </RETURNS> +GdkPixbuf *pixbuf,GdkBitmap *bitmap,int src_x,int src_y,int dest_x,int dest_y,int width,int height,int alpha_threshold +</FUNCTION> +<FUNCTION> +<NAME>gdk_pixbuf_render_to_drawable</NAME> +<RETURNS>void </RETURNS> +GdkPixbuf *pixbuf,GdkDrawable *drawable,GdkGC *gc,int src_x,int src_y,int dest_x,int dest_y,int width,int height,GdkRgbDither dither,int x_dither,int y_dither +</FUNCTION> +<FUNCTION> +<NAME>gdk_pixbuf_render_to_drawable_alpha</NAME> +<RETURNS>void </RETURNS> +GdkPixbuf *pixbuf,GdkDrawable *drawable,int src_x,int src_y,int dest_x,int dest_y,int width,int height,GdkPixbufAlphaMode alpha_mode,int alpha_threshold,GdkRgbDither dither,int x_dither,int y_dither +</FUNCTION> +<FUNCTION> +<NAME>gdk_pixbuf_render_pixmap_and_mask</NAME> +<RETURNS>void </RETURNS> +GdkPixbuf *pixbuf,GdkPixmap **pixmap_return,GdkBitmap **mask_return,int alpha_threshold +</FUNCTION> +<FUNCTION> +<NAME>gdk_pixbuf_get_from_drawable</NAME> +<RETURNS>GdkPixbuf *</RETURNS> +GdkPixbuf *dest,GdkDrawable *src,GdkColormap *cmap,int src_x,int src_y,int dest_x,int dest_y,int width,int height +</FUNCTION> <STRUCT> <NAME>GdkPixmapObject</NAME> </STRUCT> @@ -3359,12 +3384,13 @@ typedef enum <NAME>GdkWindowHints</NAME> typedef enum { - GDK_HINT_POS = 1 << 0, - GDK_HINT_MIN_SIZE = 1 << 1, - GDK_HINT_MAX_SIZE = 1 << 2, - GDK_HINT_BASE_SIZE = 1 << 3, - GDK_HINT_ASPECT = 1 << 4, - GDK_HINT_RESIZE_INC = 1 << 5 + GDK_HINT_POS = 1 << 0, + GDK_HINT_MIN_SIZE = 1 << 1, + GDK_HINT_MAX_SIZE = 1 << 2, + GDK_HINT_BASE_SIZE = 1 << 3, + GDK_HINT_ASPECT = 1 << 4, + GDK_HINT_RESIZE_INC = 1 << 5, + GDK_HINT_WIN_GRAVITY = 1 << 6 } GdkWindowHints; </ENUM> <ENUM> @@ -3392,6 +3418,22 @@ typedef enum GDK_FUNC_CLOSE = 1 << 5 } GdkWMFunction; </ENUM> +<ENUM> +<NAME>GdkGravity</NAME> +typedef enum +{ + GDK_GRAVITY_NORTH_WEST = 1, + GDK_GRAVITY_NORTH, + GDK_GRAVITY_NORTH_EAST, + GDK_GRAVITY_WEST, + GDK_GRAVITY_CENTER, + GDK_GRAVITY_EAST, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_SOUTH, + GDK_GRAVITY_SOUTH_EAST, + GDK_GRAVITY_STATIC +} GdkGravity; +</ENUM> <STRUCT> <NAME>GdkWindowAttr</NAME> struct GdkWindowAttr @@ -3424,7 +3466,7 @@ struct GdkGeometry { gint height_inc; gdouble min_aspect; gdouble max_aspect; - /* GdkGravity gravity; */ + GdkGravity win_gravity; }; </STRUCT> <STRUCT> @@ -3795,6 +3837,11 @@ GdkWindow *window,GdkWMFunction functions void </FUNCTION> <FUNCTION> +<NAME>gdk_window_iconify</NAME> +<RETURNS>void </RETURNS> +GdkWindow *window +</FUNCTION> +<FUNCTION> <NAME>gdk_window_register_dnd</NAME> <RETURNS>void </RETURNS> GdkWindow *window @@ -3846,36 +3893,3 @@ GdkWindow *window,gboolean update_children <NAME>GDK_HAVE_WCTYPE_H</NAME> #define GDK_HAVE_WCTYPE_H 1 </MACRO> -<ENUM> -<NAME>GdkPixbufAlphaMode</NAME> -typedef enum -{ - GDK_PIXBUF_ALPHA_BILEVEL, - GDK_PIXBUF_ALPHA_FULL -} GdkPixbufAlphaMode; -</ENUM> -<FUNCTION> -<NAME>gdk_pixbuf_render_threshold_alpha</NAME> -<RETURNS>void </RETURNS> -GdkPixbuf *pixbuf,GdkBitmap *bitmap,int src_x,int src_y,int dest_x,int dest_y,int width,int height,int alpha_threshold -</FUNCTION> -<FUNCTION> -<NAME>gdk_pixbuf_render_to_drawable</NAME> -<RETURNS>void </RETURNS> -GdkPixbuf *pixbuf,GdkDrawable *drawable,GdkGC *gc,int src_x,int src_y,int dest_x,int dest_y,int width,int height,GdkRgbDither dither,int x_dither,int y_dither -</FUNCTION> -<FUNCTION> -<NAME>gdk_pixbuf_render_to_drawable_alpha</NAME> -<RETURNS>void </RETURNS> -GdkPixbuf *pixbuf,GdkDrawable *drawable,int src_x,int src_y,int dest_x,int dest_y,int width,int height,GdkPixbufAlphaMode alpha_mode,int alpha_threshold,GdkRgbDither dither,int x_dither,int y_dither -</FUNCTION> -<FUNCTION> -<NAME>gdk_pixbuf_render_pixmap_and_mask</NAME> -<RETURNS>void </RETURNS> -GdkPixbuf *pixbuf,GdkPixmap **pixmap_return,GdkBitmap **mask_return,int alpha_threshold -</FUNCTION> -<FUNCTION> -<NAME>gdk_pixbuf_get_from_drawable</NAME> -<RETURNS>GdkPixbuf *</RETURNS> -GdkPixbuf *dest,GdkDrawable *src,GdkColormap *cmap,int src_x,int src_y,int dest_x,int dest_y,int width,int height -</FUNCTION> diff --git a/docs/reference/gdk/gdk-docs.sgml b/docs/reference/gdk/gdk-docs.sgml index 8da5b4377..51d744473 100644 --- a/docs/reference/gdk/gdk-docs.sgml +++ b/docs/reference/gdk/gdk-docs.sgml @@ -25,9 +25,9 @@ <!entity gdk-Cursors SYSTEM "sgml/cursors.sgml"> <!entity gdk-Input SYSTEM "sgml/input.sgml"> <!entity gdk-Drag-and-Drop SYSTEM "sgml/dnd.sgml"> -<!entity gdk-X-Window-System-Interaction SYSTEM -"sgml/x_interaction.sgml"> +<!entity gdk-X-Window-System-Interaction SYSTEM "sgml/x_interaction.sgml"> ]> + <book id="index"> <bookinfo> <title>GDK Reference Manual</title> diff --git a/docs/reference/gdk/tmpl/gdk-unused.sgml b/docs/reference/gdk/tmpl/gdk-unused.sgml index 7b727e7c2..f45539021 100644 --- a/docs/reference/gdk/tmpl/gdk-unused.sgml +++ b/docs/reference/gdk/tmpl/gdk-unused.sgml @@ -110,6 +110,14 @@ configuration information. </para> +<!-- ##### ENUM GdkPixbufAlphaMode ##### --> +<para> + +</para> + +@GDK_PIXBUF_ALPHA_BILEVEL: +@GDK_PIXBUF_ALPHA_FULL: + <!-- ##### FUNCTION gdk_regions_subtract ##### --> <para> Subtracts one region from another. diff --git a/docs/reference/gdk/tmpl/pixbufs.sgml b/docs/reference/gdk/tmpl/pixbufs.sgml index b11da1c1d..a0a8e3e91 100644 --- a/docs/reference/gdk/tmpl/pixbufs.sgml +++ b/docs/reference/gdk/tmpl/pixbufs.sgml @@ -14,14 +14,6 @@ Pixbufs </para> -<!-- ##### ENUM GdkPixbufAlphaMode ##### --> -<para> - -</para> - -@GDK_PIXBUF_ALPHA_BILEVEL: -@GDK_PIXBUF_ALPHA_FULL: - <!-- ##### FUNCTION gdk_pixbuf_render_threshold_alpha ##### --> <para> diff --git a/docs/reference/gdk/tmpl/windows.sgml b/docs/reference/gdk/tmpl/windows.sgml index 1aa9d0d86..8a2a6032e 100644 --- a/docs/reference/gdk/tmpl/windows.sgml +++ b/docs/reference/gdk/tmpl/windows.sgml @@ -86,6 +86,7 @@ Windows @GDK_HINT_BASE_SIZE: @GDK_HINT_ASPECT: @GDK_HINT_RESIZE_INC: +@GDK_HINT_WIN_GRAVITY: <!-- ##### STRUCT GdkGeometry ##### --> <para> @@ -102,6 +103,7 @@ Windows @height_inc: @min_aspect: @max_aspect: +@win_gravity: <!-- ##### FUNCTION gdk_window_new ##### --> <para> diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 33cc601f3..321f5ad58 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,79 @@ +2000-10-06 Havoc Pennington <hp@redhat.com> + + * gdk-pixbuf.h: add GdkPixbufAlphaMode + +2000-10-06 Havoc Pennington <hp@redhat.com> + + This entry is a summary of the merged-in changes from 1.0. + Relevant original ChangeLog entries are spliced in after + this entry; the files they refer to are from the 1.0 + gdk-pixbuf sources. + + * pixops/pixops.c (pixops_composite_nearest): sync a small fix + from 1.0 + + * io-xpm.c (xpm_seek_string): add fscanf error check from 1.0 + Add progressive loader from 1.0 + + * io-tiff.c (gdk_pixbuf__tiff_image_begin_load): mem leak fixes + from 1.0 tree + + * io-pnm.c: new version from 1.0 tree + + * io-jpeg.c (gdk_pixbuf__jpeg_image_load): sync from 1.0, use + malloc not g_malloc + + * io-gif.c (lzw_read_byte): sync from 1.0, change a g_error to + g_warning + (gif_get_next_step): return 0 here, sync from 1.0 + + * gdk-pixbuf-util.c: sync email address change for Cody + Russell + +2000-09-11 Jeffrey Stedfast <fejj@helixcode.com> + + * gdk-pixbuf/io-pnm.c: Pretty much totally rewrote again because + last nights code was still "broken". Should now properly handle + all error conditions gracefully. + +2000-09-10 Jeffrey Stedfast <fejj@helixcode.com> + + * gdk-pixbuf/io-pnm.c: Rewrote. + +2000-09-09 Federico Mena Quintero <federico@helixcode.com> + + * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): Compute + the correct dest offset. + +2000-08-25 Federico Mena Quintero <federico@helixcode.com> + + * gdk-pixbuf/io-xpm.c: #include <unistd.h> + +2000-08-05 Larry Ewing <lewing@helixcode.com> + + * gdk-pixbuf/io-tiff.c: stop leaking context->tempname. + + * gdk-pixbuf/io-xpm.c: same as above. + +2000-07-26 Michael Meeks <michael@helixcode.com> + + * gdk-pixbuf/io-jpeg.c (gdk_pixbuf__jpeg_image_load): make + g_malloc a malloc. + +2000-07-21 Larry Ewing <lewing@helixcode.com> + + * gdk-pixbuf/io-xpm.c: add a fake progressive loader so that + xpm at least supports the progressive interface like the one in + io-tiff.c. This should be reimplemented as an actual progressive + loader. + +2000-07-19 Jonathan Blandford <jrb@redhat.com> + + * demo/pixbuf-demo.c (update_timeout): changed scaling level to + make it look better. + * gdk-pixbuf/testpixbuf.c (update_timeout): Patch from michael + meeks to handle errors better. + 2000-10-07 Tor Lillqvist <tml@iki.fi> * gdk_pixbuf.def diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c index c6ae8e2f2..5f4320f22 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.c +++ b/gdk-pixbuf/gdk-pixbuf-loader.c @@ -492,14 +492,17 @@ gdk_pixbuf_loader_new_with_type (const char *image_type) * gdk_pixbuf_loader_get_pixbuf: * @loader: A pixbuf loader. * - * Queries the GdkPixbuf that a pixbuf loader is currently creating. In general - * it only makes sense to call this function afer the "area_prepared" signal has - * been emitted by the loader; this means that enough data has been read to know - * the size of the image that will be allocated. If the loader has not received - * enough data via gdk_pixbuf_loader_write(), then this function returns NULL. - * The returned pixbuf will be the same in all future calls to the loader, so - * simply calling gdk_pixbuf_ref() should be sufficient to continue using it. - * + * Queries the GdkPixbuf that a pixbuf loader is currently creating. + * In general it only makes sense to call this function afer the + * "area_prepared" signal has been emitted by the loader; this means + * that enough data has been read to know the size of the image that + * will be allocated. If the loader has not received enough data via + * gdk_pixbuf_loader_write(), then this function returns NULL. The + * returned pixbuf will be the same in all future calls to the loader, + * so simply calling gdk_pixbuf_ref() should be sufficient to continue + * using it. Additionally, if the loader is an animation, it will + * return the first frame of the animation. + * * Return value: The GdkPixbuf that the loader is creating, or NULL if not * enough data has been read to determine how to create the image buffer. **/ @@ -512,6 +515,19 @@ gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader) g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL); priv = loader->private; + + if (priv->animation) + { + GList *list; + + list = gdk_pixbuf_animation_get_frames (priv->animation); + if (list != NULL) + { + GdkPixbufFrame *frame = list->data; + + return gdk_pixbuf_frame_get_pixbuf (frame); + } + } return priv->pixbuf; } diff --git a/gdk-pixbuf/gdk-pixbuf-util.c b/gdk-pixbuf/gdk-pixbuf-util.c index db8ca758e..36fc29750 100644 --- a/gdk-pixbuf/gdk-pixbuf-util.c +++ b/gdk-pixbuf/gdk-pixbuf-util.c @@ -3,7 +3,7 @@ * Copyright (C) 1999 The Free Software Foundation * * Authors: Federico Mena-Quintero <federico@gimp.org> - * Cody Russell <bratsche@dfw.net> + * Cody Russell <bratsche@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index 82f0551ba..a61dc9366 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -36,6 +36,13 @@ extern "C" { +/* Alpha compositing mode */ +typedef enum +{ + GDK_PIXBUF_ALPHA_BILEVEL, + GDK_PIXBUF_ALPHA_FULL +} GdkPixbufAlphaMode; + /* Color spaces; right now only RGB is supported. * Note that these values are encoded in inline pixbufs * as ints, so don't reorder them diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index 57e2af3a3..681e915da 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -537,7 +537,7 @@ lzw_read_byte (GifContext *context) unsigned char buf[260]; /*g_error (" DID WE EVER EVER GET HERE\n");*/ - g_error ("Unhandled Case. If you have an image that causes this, let me <jrb@redhat.com> know.\n"); + g_warning ("Unhandled Case. If you have an image that causes this, let me <jrb@redhat.com> know.\n"); if (ZeroDataBlock) { return -2; @@ -982,7 +982,7 @@ gif_get_next_step (GifContext *context) /* hmm. Not 100% sure what to do about this. Should * i try to return a blank image instead? */ context->state = GIF_DONE; - return -2; + return 0; } if (c == '!') { diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index 89ca8d201..623077738 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -196,7 +196,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f) w = cinfo.output_width; h = cinfo.output_height; - pixels = g_malloc (h * w * 3); + pixels = malloc (h * w * 3); if (!pixels) { jpeg_destroy_decompress (&cinfo); return NULL; diff --git a/gdk-pixbuf/io-pnm.c b/gdk-pixbuf/io-pnm.c index aa1b19391..c91658cfd 100644 --- a/gdk-pixbuf/io-pnm.c +++ b/gdk-pixbuf/io-pnm.c @@ -1,20 +1,22 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* GdkPixbuf library - PNM image loader * * Copyright (C) 1999 Red Hat, Inc. * - * Authors: Michael Fulbright <drmike@redhat.com> + * Authors: Jeffrey Stedfast <fejj@helixcode.com> + * Michael Fulbright <drmike@redhat.com> * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public + * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Library General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public + * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. @@ -29,16 +31,15 @@ #include "gdk-pixbuf-private.h" #include "gdk-pixbuf-io.h" - #define PNM_BUF_SIZE 4096 -#define PNM_SUSPEND 0 -#define PNM_OK 1 #define PNM_FATAL_ERR -1 +#define PNM_SUSPEND 0 +#define PNM_OK 1 typedef enum { - PNM_FORMAT_PGM, + PNM_FORMAT_PGM = 1, PNM_FORMAT_PGM_RAW, PNM_FORMAT_PPM, PNM_FORMAT_PPM_RAW, @@ -47,51 +48,54 @@ typedef enum { } PnmFormat; typedef struct { - guchar buffer[PNM_BUF_SIZE]; - guchar *next_byte; - guint bytes_left; + guchar buffer[PNM_BUF_SIZE]; + guchar *byte; + guint nbytes; } PnmIOBuffer; typedef struct { - ModuleUpdatedNotifyFunc updated_func; + ModuleUpdatedNotifyFunc updated_func; ModulePreparedNotifyFunc prepared_func; - gpointer user_data; + gpointer user_data; + + GdkPixbuf *pixbuf; + guchar *pixels; /* incoming pixel data buffer */ + guchar *dptr; /* current position in pixbuf */ + + PnmIOBuffer inbuf; + + guint width; + guint height; + guint maxval; + guint rowstride; + PnmFormat type; + + guint output_row; /* last row to be completed */ + guint output_col; + gboolean did_prescan; /* are we in image data yet? */ + gboolean got_header; /* have we loaded pnm header? */ + + guint scan_state; - GdkPixbuf *pixbuf; - guchar *pixels; /* incoming pixel data buffer */ - guchar *dptr; /* current position in pixbuf */ - - PnmIOBuffer inbuf; - - guint width; - guint height; - guint maxval; - guint rowstride; - PnmFormat type; - - guint output_row; /* last row to be completed */ - guint output_col; - gboolean did_prescan; /* are we in image data yet? */ - gboolean got_header; /* have we loaded jpeg header? */ } PnmLoaderContext; -GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f); -gpointer gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc func, - ModuleUpdatedNotifyFunc func2, - ModuleFrameDoneNotifyFunc frame_done_func, - ModuleAnimationDoneNotifyFunc anim_done_func, - gpointer user_data); -void gdk_pixbuf__pnm_image_stop_load (gpointer context); -gboolean gdk_pixbuf__pnm_image_load_increment(gpointer context, guchar *buf, guint size); +GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f); +gpointer gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc func, + ModuleUpdatedNotifyFunc func2, + ModuleFrameDoneNotifyFunc frame_done_func, + ModuleAnimationDoneNotifyFunc anim_done_func, + gpointer user_data); +void gdk_pixbuf__pnm_image_stop_load (gpointer context); +gboolean gdk_pixbuf__pnm_image_load_increment (gpointer context, guchar *buf, guint size); -static void explode_bitmap_into_buf (PnmLoaderContext *context); -static void explode_gray_into_buf (PnmLoaderContext *context); +static void explode_bitmap_into_buf (PnmLoaderContext *context); +static void explode_gray_into_buf (PnmLoaderContext *context); /* Destroy notification function for the pixbuf */ static void free_buffer (guchar *pixels, gpointer data) { - free (pixels); + g_free (pixels); } @@ -108,33 +112,32 @@ explode_bitmap_into_buf (PnmLoaderContext *context) gint bit; guchar *dptr; gint wid, x, y; - + g_return_if_fail (context != NULL); g_return_if_fail (context->dptr != NULL); - + /* I'm no clever bit-hacker so I'm sure this can be optimized */ dptr = context->dptr; y = context->output_row; wid = context->width; - - from = dptr + (wid - 1)/8; + + from = dptr + ((wid - 1) / 8); to = dptr + (wid - 1) * 3; /* bit = 7 - (((y+1)*wid-1) % 8); */ - bit = 7 - ((wid-1) % 8); - + bit = 7 - ((wid-1) % 8); + /* get first byte and align properly */ data = from[0]; for (j = 0; j < bit; j++, data >>= 1); - + for (x = wid-1; x >= 0; x--) { - /* g_print ("%c", (data & 1) ? '*' : ' '); */ - - to[0] = to[1] = to[2] = (data & 1) ? 0x00 : 0xff; - + + to[0] = to[1] = to[2] = (data & 0x01) ? 0x00 : 0xff; + to -= 3; bit++; - + if (bit > 7) { from--; data = from[0]; @@ -143,7 +146,7 @@ explode_bitmap_into_buf (PnmLoaderContext *context) data >>= 1; } } - + /* g_print ("\n"); */ } @@ -154,10 +157,10 @@ explode_gray_into_buf (PnmLoaderContext *context) gint j; guchar *from, *to; guint w; - + g_return_if_fail (context != NULL); g_return_if_fail (context->dptr != NULL); - + /* Expand grey->colour. Expand from the end of the * memory down, so we can use the same buffer. */ @@ -173,221 +176,203 @@ explode_gray_into_buf (PnmLoaderContext *context) } } -/* skip over whitespace in file from current pos. */ -/* also skips comments */ -/* returns pointer to first non-whitespace char hit or, or NULL if */ -/* we ran out of data w/o hitting a whitespace */ -/* internal pointer in inbuf isnt moved ahead in this case */ -static guchar * -skip_ahead_whitespace (PnmIOBuffer *inbuf) -{ - gboolean in_comment; - guchar *ptr; - guint num_left; - - g_return_val_if_fail (inbuf != NULL, NULL); - g_return_val_if_fail (inbuf->next_byte != NULL, NULL); - - in_comment = FALSE; - num_left = inbuf->bytes_left; - ptr = inbuf->next_byte; - while (num_left > 0) { - if (in_comment) { - if (*ptr == '\n') - in_comment = FALSE; - } else if (*ptr == '#') { - in_comment = TRUE; - } else if (!isspace (*ptr)) { - inbuf->bytes_left -= (ptr-inbuf->next_byte); - inbuf->next_byte = ptr; - return ptr; - } - ptr ++; - num_left--; - } - return NULL; -} - -/* reads into buffer until we hit whitespace in file from current pos, */ -/* return NULL if ran out of data */ -/* advances inbuf if successful */ -static guchar * -read_til_whitespace (PnmIOBuffer *inbuf, guchar *buf, guint size) +/* skip over whitespace and comments in input buffer */ +static gint +pnm_skip_whitespace (PnmIOBuffer *inbuf) { - guchar *p; - guchar *ptr; - guint num_left; - - g_return_val_if_fail (inbuf != NULL, NULL); - g_return_val_if_fail (inbuf->next_byte != NULL, NULL); - - p = buf; - num_left = inbuf->bytes_left; - ptr = inbuf->next_byte; - while (num_left > 0 && (p-buf)+1 < size) { - if (isspace (*ptr)) { - *p = '\0'; - inbuf->bytes_left = num_left; - inbuf->next_byte = ptr; - return ptr; - } else { - *p = *ptr; - p++; - ptr++; - num_left--; + register guchar *inptr; + guchar *inend; + + g_return_val_if_fail (inbuf != NULL, PNM_FATAL_ERR); + g_return_val_if_fail (inbuf->byte != NULL, PNM_FATAL_ERR); + + inend = inbuf->byte + inbuf->nbytes; + inptr = inbuf->byte; + + for ( ; inptr < inend; inptr++) { + if (*inptr == '#') { + /* in comment - skip to the end of this line */ + for ( ; *inptr != '\n' && inptr < inend; inptr++); + } else if (!isspace (*inptr)) { + inbuf->byte = inptr; + inbuf->nbytes = (guint) (inend - inptr); + return PNM_OK; } } - return NULL; + + inbuf->byte = inptr; + inbuf->nbytes = (guint) (inend - inptr); + + return PNM_SUSPEND; } -/* read next number from buffer */ -/* -1 if failed, 0 if successful */ +/* read next number from buffer */ static gint -read_next_number (PnmIOBuffer *inbuf, guint *value) +pnm_read_next_value (PnmIOBuffer *inbuf, guint *value) { - guchar *tmpptr; - guchar *old_next_byte; - gchar *errptr; - guint old_bytes_left; - guchar buf[128]; - - g_return_val_if_fail (inbuf != NULL, -1); - g_return_val_if_fail (inbuf->next_byte != NULL, -1); - g_return_val_if_fail (value != NULL, -1); - - old_next_byte = inbuf->next_byte; - old_bytes_left = inbuf->bytes_left; - - if ((tmpptr = skip_ahead_whitespace (inbuf)) == NULL) - return -1; - - if ((tmpptr = read_til_whitespace (inbuf, buf, 128)) == NULL) { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return -1; - } + register guchar *inptr, *word, *p; + guchar *inend, buf[128]; + gchar *endptr; + gint retval; - *value = strtol (buf, &errptr, 10); - - if (*errptr != '\0') { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return -1; - } - - return 0; + g_return_val_if_fail (inbuf != NULL, PNM_FATAL_ERR); + g_return_val_if_fail (inbuf->byte != NULL, PNM_FATAL_ERR); + g_return_val_if_fail (value != NULL, PNM_FATAL_ERR); + + /* skip white space */ + if ((retval = pnm_skip_whitespace (inbuf)) != PNM_OK) + return retval; + + inend = inbuf->byte + inbuf->nbytes; + inptr = inbuf->byte; + + /* copy this pnm 'word' into a temp buffer */ + for (p = inptr, word = buf; (p < inend) && !isspace (*p) && (p - inptr < 128); p++, word++) + *word = *p; + *word = '\0'; + + /* hmmm, there must be more data to this 'word' */ + if (!isspace (*p)) + return PNM_SUSPEND; + + /* get the value */ + *value = strtol (buf, &endptr, 10); + if (*endptr != '\0') + return PNM_FATAL_ERR; + + inbuf->byte = p; + inbuf->nbytes = (guint) (inend - p); + + return PNM_OK; } /* returns PNM_OK, PNM_SUSPEND, or PNM_FATAL_ERR */ static gint pnm_read_header (PnmLoaderContext *context) { - guchar *old_next_byte; - guint old_bytes_left; PnmIOBuffer *inbuf; - guint w, h; - gint rc; - PnmFormat type; - - g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - - inbuf = &context->inbuf; - old_bytes_left = inbuf->bytes_left; - old_next_byte = inbuf->next_byte; + gint retval; - /* file must start with a 'P' followed by a numeral */ - /* so loop till we get enough data to determine type*/ - if (inbuf->bytes_left < 2) - return PNM_SUSPEND; + g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - if (*inbuf->next_byte != 'P') - return PNM_FATAL_ERR; + inbuf = &context->inbuf; - switch (*(inbuf->next_byte+1)) { - case '1': - type = PNM_FORMAT_PBM; - break; - case '2': - type = PNM_FORMAT_PGM; - break; - case '3': - type = PNM_FORMAT_PPM; - break; - case '4': - type = PNM_FORMAT_PBM_RAW; - break; - case '5': - type = PNM_FORMAT_PGM_RAW; - break; - case '6': - type = PNM_FORMAT_PPM_RAW; - break; - default: - return PNM_FATAL_ERR; + if (!context->type) { + /* file must start with a 'P' followed by a numeral */ + /* so loop till we get enough data to determine type */ + if (inbuf->nbytes < 2) + return PNM_SUSPEND; + + if (*inbuf->byte != 'P') + return PNM_FATAL_ERR; + + inbuf->byte++; + inbuf->nbytes--; + + switch (*inbuf->byte) { + case '1': + context->type = PNM_FORMAT_PBM; + break; + case '2': + context->type = PNM_FORMAT_PGM; + break; + case '3': + context->type = PNM_FORMAT_PPM; + break; + case '4': + context->type = PNM_FORMAT_PBM_RAW; + break; + case '5': + context->type = PNM_FORMAT_PGM_RAW; + break; + case '6': + context->type = PNM_FORMAT_PPM_RAW; + break; + default: + return PNM_FATAL_ERR; + } + + if (!inbuf->nbytes) + return PNM_SUSPEND; + + inbuf->byte++; + inbuf->nbytes--; } - context->type = type; - - inbuf->next_byte += 2; - inbuf->bytes_left -= 2; - - /* now read remainder of header */ - if ((rc = read_next_number (inbuf, &w))) { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return PNM_SUSPEND; + if (!context->width) { + /* read the pixmap width */ + guint width = 0; + + retval = pnm_read_next_value (inbuf, &width); + + if (retval != PNM_OK) + return retval; + + if (!width) + return PNM_FATAL_ERR; + + context->width = width; } - if ((rc = read_next_number (inbuf, &h))) { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return PNM_SUSPEND; + if (!context->height) { + /* read the pixmap height */ + guint height = 0; + + retval = pnm_read_next_value (inbuf, &height); + + if (retval != PNM_OK) + return retval; + + if (!height) + return PNM_FATAL_ERR; + + context->height = height; } - context->width = w; - context->height = h; - - switch (type) { + switch (context->type) { case PNM_FORMAT_PPM: case PNM_FORMAT_PPM_RAW: case PNM_FORMAT_PGM: case PNM_FORMAT_PGM_RAW: - if ((rc = read_next_number (inbuf, &context->maxval)) < 0) { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return PNM_SUSPEND; + if (!context->maxval) { + retval = pnm_read_next_value (inbuf, &context->maxval); + + if (retval != PNM_OK) + return retval; + + if (context->maxval == 0) + return PNM_FATAL_ERR; } break; default: break; } - + return PNM_OK; } - static gint pnm_read_raw_scanline (PnmLoaderContext *context) { - guint numpix; - guint numbytes, offset; PnmIOBuffer *inbuf; - + guint numbytes, offset; + guint numpix = 0; + guchar *dest; + guint i; + g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - -/*G_BREAKPOINT(); */ - + inbuf = &context->inbuf; - + switch (context->type) { case PNM_FORMAT_PBM_RAW: - numpix = inbuf->bytes_left * 8; + numpix = inbuf->nbytes * 8; break; case PNM_FORMAT_PGM_RAW: - numpix = inbuf->bytes_left; + numpix = inbuf->nbytes; break; case PNM_FORMAT_PPM_RAW: - numpix = inbuf->bytes_left/3; + numpix = inbuf->nbytes / 3; break; default: g_warning ("io-pnm.c: Illegal raw pnm type!\n"); @@ -395,79 +380,100 @@ pnm_read_raw_scanline (PnmLoaderContext *context) } numpix = MIN (numpix, context->width - context->output_col); - - if (numpix == 0) + + if (!numpix) return PNM_SUSPEND; - context->dptr = context->pixels + - context->output_row * context->rowstride; + context->dptr = context->pixels + context->output_row * context->rowstride; switch (context->type) { case PNM_FORMAT_PBM_RAW: - numbytes = numpix/8 + ((numpix % 8) ? 1 : 0); - offset = context->output_col/8; + numbytes = (numpix / 8) + ((numpix % 8) ? 1 : 0); + offset = context->output_col / 8; break; case PNM_FORMAT_PGM_RAW: numbytes = numpix; offset = context->output_col; break; case PNM_FORMAT_PPM_RAW: - numbytes = numpix*3; - offset = context->output_col*3; + numbytes = numpix * 3; + offset = context->output_col * 3; break; default: g_warning ("io-pnm.c: Illegal raw pnm type!\n"); return PNM_FATAL_ERR; } - memcpy (context->dptr + offset, inbuf->next_byte, numbytes); - - inbuf->next_byte += numbytes; - inbuf->bytes_left -= numbytes; - + switch (context->type) { + case PNM_FORMAT_PBM_RAW: + dest = context->dptr + offset; + memcpy (dest, inbuf->byte, numbytes); + break; + case PNM_FORMAT_PGM_RAW: + case PNM_FORMAT_PPM_RAW: + dest = context->dptr + offset; + + if (context->maxval == 255) { + /* special-case optimization */ + memcpy (dest, inbuf->byte, numbytes); + } else { + for (i = 0; i < numbytes; i++) { + guchar *byte = inbuf->byte + i; + + /* scale the color to an 8-bit color depth */ + if (*byte > context->maxval) + *dest++ = 255; + else + *dest++ = (guchar) (255 * *byte / context->maxval); + } + } + break; + default: + g_warning ("Invalid raw pnm format!"); + } + + inbuf->byte += numbytes; + inbuf->nbytes -= numbytes; + context->output_col += numpix; if (context->output_col == context->width) { - if ( context->type == PNM_FORMAT_PBM_RAW ) - explode_bitmap_into_buf(context); - else if ( context->type == PNM_FORMAT_PGM_RAW ) + if (context->type == PNM_FORMAT_PBM_RAW) + explode_bitmap_into_buf (context); + else if (context->type == PNM_FORMAT_PGM_RAW) explode_gray_into_buf (context); context->output_col = 0; context->output_row++; - } else { return PNM_SUSPEND; } - + return PNM_OK; } - static gint pnm_read_ascii_scanline (PnmLoaderContext *context) { - guint offset; - gint rc; - guint value, numval, i; + PnmIOBuffer *inbuf; + guint offset; + guint value, numval, i; guchar data; guchar mask; - guchar *old_next_byte, *dptr; - guint old_bytes_left; - PnmIOBuffer *inbuf; - + guchar *dptr; + gint retval; + g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - + data = mask = 0; - + inbuf = &context->inbuf; - - context->dptr = context->pixels + - context->output_row * context->rowstride; - + + context->dptr = context->pixels + context->output_row * context->rowstride; + switch (context->type) { case PNM_FORMAT_PBM: numval = MIN (8, context->width - context->output_col); - offset = context->output_col/8; + offset = context->output_col / 8; break; case PNM_FORMAT_PGM: numval = 1; @@ -475,32 +481,31 @@ pnm_read_ascii_scanline (PnmLoaderContext *context) break; case PNM_FORMAT_PPM: numval = 3; - offset = context->output_col*3; + offset = context->output_col * 3; break; default: g_warning ("Can't happen\n"); return PNM_FATAL_ERR; } - - dptr = context->dptr + offset; - + + dptr = context->dptr + offset + context->scan_state; + while (TRUE) { if (context->type == PNM_FORMAT_PBM) { mask = 0x80; data = 0; numval = MIN (8, context->width - context->output_col); } - - old_next_byte = inbuf->next_byte; - old_bytes_left = inbuf->bytes_left; - - for (i=0; i<numval; i++) { - if ((rc = read_next_number (inbuf, &value))) { - inbuf->next_byte = old_next_byte; - inbuf->bytes_left = old_bytes_left; - return PNM_SUSPEND; + + for (i = context->scan_state; i < numval; i++) { + retval = pnm_read_next_value (inbuf, &value); + if (retval != PNM_OK) { + /* save state and return */ + context->scan_state = i; + return retval; } + switch (context->type) { case PNM_FORMAT_PBM: if (value) @@ -509,72 +514,73 @@ pnm_read_ascii_scanline (PnmLoaderContext *context) break; case PNM_FORMAT_PGM: - *dptr++ = (guchar)(255.0*((double)value/(double)context->maxval)); - break; case PNM_FORMAT_PPM: - *dptr++ = (guchar)(255.0*((double)value/(double)context->maxval)); + /* scale the color to an 8-bit color depth */ + if (value > context->maxval) + *dptr++ = 255; + else + *dptr++ = (guchar)(255 * value / context->maxval); break; default: - g_warning ("io-pnm.c: Illegal raw pnm type!\n"); + g_warning ("io-pnm.c: Illegal ascii pnm type!\n"); break; } } + context->scan_state = 0; + if (context->type == PNM_FORMAT_PBM) { *dptr++ = data; context->output_col += numval; } else { context->output_col++; } - + if (context->output_col == context->width) { - if ( context->type == PNM_FORMAT_PBM ) - explode_bitmap_into_buf(context); - else if ( context->type == PNM_FORMAT_PGM ) + if (context->type == PNM_FORMAT_PBM) + explode_bitmap_into_buf (context); + else if (context->type == PNM_FORMAT_PGM) explode_gray_into_buf (context); - + context->output_col = 0; context->output_row++; break; } - } - + return PNM_OK; } -/* returns 1 if a scanline was converted, 0 means we ran out of data */ +/* returns 1 if a scanline was converted, 0 means we ran out of data */ static gint pnm_read_scanline (PnmLoaderContext *context) { - gint rc; - + gint retval; + g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - + /* read in image data */ /* for raw formats this is trivial */ switch (context->type) { case PNM_FORMAT_PBM_RAW: case PNM_FORMAT_PGM_RAW: case PNM_FORMAT_PPM_RAW: - rc = pnm_read_raw_scanline (context); - if (rc == PNM_SUSPEND) - return rc; + retval = pnm_read_raw_scanline (context); + if (retval != PNM_OK) + return retval; break; - case PNM_FORMAT_PBM: case PNM_FORMAT_PGM: case PNM_FORMAT_PPM: - rc = pnm_read_ascii_scanline (context); - if (rc == PNM_SUSPEND) - return rc; + retval = pnm_read_ascii_scanline (context); + if (retval != PNM_OK) + return retval; break; - default: g_warning ("Cannot load these image types (yet)\n"); return PNM_FATAL_ERR; } - + return PNM_OK; } @@ -582,99 +588,104 @@ pnm_read_scanline (PnmLoaderContext *context) GdkPixbuf * gdk_pixbuf__pnm_image_load (FILE *f) { - gint nbytes; - gint rc; - PnmLoaderContext context; PnmIOBuffer *inbuf; - + gint nbytes; + gint retval; + /* pretend to be doing progressive loading */ context.updated_func = NULL; context.prepared_func = NULL; context.user_data = NULL; - context.inbuf.bytes_left = 0; - context.inbuf.next_byte = NULL; + context.type = 0; + context.inbuf.nbytes = 0; + context.inbuf.byte = NULL; + context.width = 0; + context.height = 0; + context.maxval = 0; context.pixels = NULL; context.pixbuf = NULL; - context.got_header = context.did_prescan = FALSE; - + context.got_header = FALSE; + context.did_prescan = FALSE; + context.scan_state = 0; + inbuf = &context.inbuf; - - while (TRUE) { - guint num_to_read; - + + while (!feof (f)) { + guint num_to_read; + /* keep buffer as full as possible */ - num_to_read = PNM_BUF_SIZE - inbuf->bytes_left; - - if (inbuf->next_byte != NULL && inbuf->bytes_left > 0) - memmove (inbuf->buffer, inbuf->next_byte, - inbuf->bytes_left); - - nbytes = fread (inbuf->buffer+inbuf->bytes_left, - 1, num_to_read, f); - inbuf->bytes_left += nbytes; - inbuf->next_byte = inbuf->buffer; - - /* ran out of data and we haven't exited main loop */ - if (inbuf->bytes_left == 0) { + num_to_read = PNM_BUF_SIZE - inbuf->nbytes; + + if (inbuf->byte != NULL && inbuf->nbytes > 0) + memmove (inbuf->buffer, inbuf->byte, inbuf->nbytes); + + nbytes = fread (inbuf->buffer + inbuf->nbytes, 1, num_to_read, f); + + /* error checking */ + if (nbytes == 0 && ferror (f)) { + /* we ran out of data? */ if (context.pixbuf) gdk_pixbuf_unref (context.pixbuf); - g_warning ("io-pnm.c: Ran out of data...\n"); + g_warning ("io-pnm.c: Ran out of data.\n"); return NULL; } - + + inbuf->nbytes += nbytes; + inbuf->byte = inbuf->buffer; + /* get header if needed */ if (!context.got_header) { - - rc = pnm_read_header (&context); - if (rc == PNM_FATAL_ERR) + retval = pnm_read_header (&context); + if (retval == PNM_FATAL_ERR) return NULL; - else if (rc == PNM_SUSPEND) + else if (retval == PNM_SUSPEND) continue; - + context.got_header = TRUE; } - + /* scan until we hit image data */ if (!context.did_prescan) { - - if (skip_ahead_whitespace (inbuf) == NULL) + retval = pnm_skip_whitespace (inbuf); + if (retval == PNM_FATAL_ERR) + return NULL; + else if (retval == PNM_SUSPEND) continue; - + context.did_prescan = TRUE; context.output_row = 0; context.output_col = 0; - + context.rowstride = context.width * 3; - context.pixels = g_malloc (context.height * - context.width * 3); + context.pixels = g_malloc (context.height * context.width * 3); + if (!context.pixels) { /* Failed to allocate memory */ - g_error ("Couldn't allocate pixel buf"); + g_warning ("Couldn't allocate pixel buf"); } } - + /* if we got here we're reading image data */ while (context.output_row < context.height) { - - rc = pnm_read_scanline (&context); - - if (rc == PNM_SUSPEND) { + retval = pnm_read_scanline (&context); + + if (retval == PNM_SUSPEND) { break; - } else if (rc == PNM_FATAL_ERR) { + } else if (retval == PNM_FATAL_ERR) { if (context.pixbuf) gdk_pixbuf_unref (context.pixbuf); g_warning ("io-pnm.c: error reading rows..\n"); return NULL; } } - + if (context.output_row < context.height) continue; else break; } - + return gdk_pixbuf_new_from_data (context.pixels, GDK_COLORSPACE_RGB, FALSE, 8, context.width, context.height, context.width * 3, free_buffer, NULL); @@ -695,19 +706,23 @@ gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc prepared_func, gpointer user_data) { PnmLoaderContext *context; - + context = g_new0 (PnmLoaderContext, 1); context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; + context->width = 0; + context->height = 0; + context->maxval = 0; context->pixbuf = NULL; context->pixels = NULL; context->got_header = FALSE; context->did_prescan = FALSE; - - context->inbuf.bytes_left = 0; - context->inbuf.next_byte = NULL; - + context->scan_state = 0; + + context->inbuf.nbytes = 0; + context->inbuf.byte = NULL; + return (gpointer) context; } @@ -720,18 +735,15 @@ void gdk_pixbuf__pnm_image_stop_load (gpointer data) { PnmLoaderContext *context = (PnmLoaderContext *) data; - + g_return_if_fail (context != NULL); - + if (context->pixbuf) gdk_pixbuf_unref (context->pixbuf); - + g_free (context); } - - - /* * context - from image_begin_load * buf - new image data @@ -743,103 +755,104 @@ gboolean gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size) { PnmLoaderContext *context = (PnmLoaderContext *)data; - PnmIOBuffer *inbuf; - - guchar *old_next_byte; - guint old_bytes_left; + PnmIOBuffer *inbuf; + guchar *old_byte; + guint old_nbytes; guchar *bufhd; - guint num_left, spinguard; - gint rc; - + guint num_left, spinguard; + gint retval; + g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (buf != NULL, FALSE); - + bufhd = buf; inbuf = &context->inbuf; - old_bytes_left = inbuf->bytes_left; - old_next_byte = inbuf->next_byte; - + old_nbytes = inbuf->nbytes; + old_byte = inbuf->byte; + num_left = size; spinguard = 0; while (TRUE) { guint num_to_copy; - + /* keep buffer as full as possible */ - num_to_copy = MIN (PNM_BUF_SIZE - inbuf->bytes_left, num_left); + num_to_copy = MIN (PNM_BUF_SIZE - inbuf->nbytes, num_left); if (num_to_copy == 0) spinguard++; - + if (spinguard > 1) return TRUE; - - if (inbuf->next_byte != NULL && inbuf->bytes_left > 0) - memmove (inbuf->buffer, inbuf->next_byte, - inbuf->bytes_left); - - memcpy (inbuf->buffer + inbuf->bytes_left, bufhd, num_to_copy); + + if (inbuf->byte != NULL && inbuf->nbytes > 0) + memmove (inbuf->buffer, inbuf->byte, inbuf->nbytes); + + memcpy (inbuf->buffer + inbuf->nbytes, bufhd, num_to_copy); bufhd += num_to_copy; - inbuf->bytes_left += num_to_copy; - inbuf->next_byte = inbuf->buffer; + inbuf->nbytes += num_to_copy; + inbuf->byte = inbuf->buffer; num_left -= num_to_copy; /* ran out of data and we haven't exited main loop */ - if (inbuf->bytes_left == 0) + if (inbuf->nbytes == 0) return TRUE; - + /* get header if needed */ if (!context->got_header) { - rc = pnm_read_header (context); - if (rc == PNM_FATAL_ERR) + retval = pnm_read_header (context); + + if (retval == PNM_FATAL_ERR) return FALSE; - else if (rc == PNM_SUSPEND) + else if (retval == PNM_SUSPEND) continue; - + context->got_header = TRUE; } - + /* scan until we hit image data */ if (!context->did_prescan) { - if (skip_ahead_whitespace (inbuf) == NULL) + retval = pnm_skip_whitespace (inbuf); + + if (retval == PNM_FATAL_ERR) + return FALSE; + else if (retval == PNM_SUSPEND) continue; - + context->did_prescan = TRUE; context->output_row = 0; context->output_col = 0; - - context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - FALSE, - 8, - context->width, - context->height); - + + context->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, + 8, + context->width, + context->height); + if (context->pixbuf == NULL) { /* Failed to allocate memory */ g_error ("Couldn't allocate gdkpixbuf"); } - + context->pixels = context->pixbuf->pixels; context->rowstride = context->pixbuf->rowstride; - + /* Notify the client that we are ready to go */ (* context->prepared_func) (context->pixbuf, context->user_data); - } - + /* if we got here we're reading image data */ while (context->output_row < context->height) { - rc = pnm_read_scanline (context); - - if (rc == PNM_SUSPEND) { + retval = pnm_read_scanline (context); + + if (retval == PNM_SUSPEND) { break; - } else if (rc == PNM_FATAL_ERR) { + } else if (retval == PNM_FATAL_ERR) { if (context->pixbuf) gdk_pixbuf_unref (context->pixbuf); - g_warning ("io-pnm.c: error reading rows..\n"); + g_warning ("io-pnm.c: error reading rows.\n"); return FALSE; - } else if (rc == PNM_OK) { - + } else if (retval == PNM_OK) { /* send updated signal */ (* context->updated_func) (context->pixbuf, 0, @@ -849,12 +862,12 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size) context->user_data); } } - + if (context->output_row < context->height) continue; else break; } - + return TRUE; } diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c index dcc1ea66b..fdf517463 100644 --- a/gdk-pixbuf/io-tiff.c +++ b/gdk-pixbuf/io-tiff.c @@ -171,12 +171,14 @@ gdk_pixbuf__tiff_image_begin_load (ModulePreparedNotifyFunc prepare_func, fd = open (context->tempname, O_RDWR); #endif if (fd < 0) { + g_free (context->tempname); g_free (context); return NULL; } context->file = fdopen (fd, "w"); if (context->file == NULL) { + g_free (context->tempname); g_free (context); return NULL; } diff --git a/gdk-pixbuf/io-xpm.c b/gdk-pixbuf/io-xpm.c index c94658564..17e2a43f4 100644 --- a/gdk-pixbuf/io-xpm.c +++ b/gdk-pixbuf/io-xpm.c @@ -28,6 +28,7 @@ #include <string.h> #include <glib.h> #include "gdk-pixbuf-private.h" +#include "gdk-pixbuf-io.h" @@ -977,7 +978,8 @@ xpm_seek_string (FILE *infile, const gchar *str, gint skip_comments) char instr[1024]; while (!feof (infile)) { - fscanf (infile, "%1023s", instr); + if (fscanf (infile, "%1023s", instr) < 0) + return FALSE; if (skip_comments == TRUE && strcmp (instr, "/*") == 0) { fscanf (infile, "%1023s", instr); while (!feof (infile) && strcmp (instr, "*/") != 0) @@ -1373,3 +1375,97 @@ gdk_pixbuf__xpm_image_load_xpm_data (const gchar **data) return pixbuf; } + +/* Progressive loader */ +typedef struct _XPMContext XPMContext; +struct _XPMContext +{ + ModulePreparedNotifyFunc prepare_func; + ModuleUpdatedNotifyFunc update_func; + gpointer user_data; + + gchar *tempname; + FILE *file; + gboolean all_okay; +}; + +/* + * FIXME xpm loading progressively is not properly implemented. + * Instead we will buffer to a file then load that file when done. + * This is very broken but it should be relayively simple to fix + * in the future. + */ +gpointer +gdk_pixbuf__xpm_image_begin_load (ModulePreparedNotifyFunc prepare_func, + ModuleUpdatedNotifyFunc update_func, + ModuleFrameDoneNotifyFunc frame_done_func, + ModuleAnimationDoneNotifyFunc anim_done_func, + gpointer user_data) +{ + XPMContext *context; + gint fd; + + g_warning ("load start"); + context = g_new (XPMContext, 1); + context->prepare_func = prepare_func; + context->update_func = update_func; + context->user_data = user_data; + context->all_okay = TRUE; + context->tempname = g_strdup ("/tmp/gdkpixbuf-xpm-tmp.XXXXXX"); + fd = mkstemp (context->tempname); + if (fd < 0) { + g_free (context->tempname); + g_free (context); + return NULL; + } + + context->file = fdopen (fd, "w+"); + if (context->file == NULL) { + g_free (context->tempname); + g_free (context); + return NULL; + } + + return context; +} + +void +gdk_pixbuf__xpm_image_stop_load (gpointer data) +{ + XPMContext *context = (XPMContext*) data; + GdkPixbuf *pixbuf; + + g_return_if_fail (data != NULL); + g_warning ("stopped loading"); + + fflush (context->file); + rewind (context->file); + if (context->all_okay) { + pixbuf = gdk_pixbuf__xpm_image_load (context->file); + + (* context->prepare_func) (pixbuf, context->user_data); + (* context->update_func) (pixbuf, 0, 0, pixbuf->width, pixbuf->height, context->user_data); + gdk_pixbuf_unref (pixbuf); + } + + fclose (context->file); + unlink (context->tempname); + g_free (context->tempname); + g_free ((XPMContext *) context); +} + +gboolean +gdk_pixbuf__xpm_image_load_increment (gpointer data, guchar *buf, guint size) +{ + XPMContext *context = (XPMContext *) data; + + g_return_val_if_fail (data != NULL, FALSE); + g_warning ("load increment"); + + if (fwrite (buf, sizeof (guchar), size, context->file) != size) { + context->all_okay = FALSE; + return FALSE; + } + + return TRUE; +} diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c index 6714133a9..ea1960715 100644 --- a/gdk-pixbuf/pixops/pixops.c +++ b/gdk-pixbuf/pixops/pixops.c @@ -160,7 +160,8 @@ pixops_composite_nearest (guchar *dest_buf, for (i = 0; i < (render_y1 - render_y0); i++) { const guchar *src = src_buf + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT) * src_rowstride; - guchar *dest = dest_buf + i * dest_rowstride + render_x0 * dest_channels; + /* FIXME Owen needs to look at this */ + guchar *dest = dest_buf + i * dest_rowstride; x = render_x0 * x_step + x_step / 2; diff --git a/gdk/gdkpixbuf.h b/gdk/gdkpixbuf.h index 8a487c448..db74d6011 100644 --- a/gdk/gdkpixbuf.h +++ b/gdk/gdkpixbuf.h @@ -11,13 +11,6 @@ extern "C" { /* Rendering to a drawable */ -/* Alpha compositing mode */ -typedef enum -{ - GDK_PIXBUF_ALPHA_BILEVEL, - GDK_PIXBUF_ALPHA_FULL -} GdkPixbufAlphaMode; - void gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, GdkBitmap *bitmap, int src_x, diff --git a/gtk/gdk-pixbuf-loader.c b/gtk/gdk-pixbuf-loader.c index c6ae8e2f2..5f4320f22 100644 --- a/gtk/gdk-pixbuf-loader.c +++ b/gtk/gdk-pixbuf-loader.c @@ -492,14 +492,17 @@ gdk_pixbuf_loader_new_with_type (const char *image_type) * gdk_pixbuf_loader_get_pixbuf: * @loader: A pixbuf loader. * - * Queries the GdkPixbuf that a pixbuf loader is currently creating. In general - * it only makes sense to call this function afer the "area_prepared" signal has - * been emitted by the loader; this means that enough data has been read to know - * the size of the image that will be allocated. If the loader has not received - * enough data via gdk_pixbuf_loader_write(), then this function returns NULL. - * The returned pixbuf will be the same in all future calls to the loader, so - * simply calling gdk_pixbuf_ref() should be sufficient to continue using it. - * + * Queries the GdkPixbuf that a pixbuf loader is currently creating. + * In general it only makes sense to call this function afer the + * "area_prepared" signal has been emitted by the loader; this means + * that enough data has been read to know the size of the image that + * will be allocated. If the loader has not received enough data via + * gdk_pixbuf_loader_write(), then this function returns NULL. The + * returned pixbuf will be the same in all future calls to the loader, + * so simply calling gdk_pixbuf_ref() should be sufficient to continue + * using it. Additionally, if the loader is an animation, it will + * return the first frame of the animation. + * * Return value: The GdkPixbuf that the loader is creating, or NULL if not * enough data has been read to determine how to create the image buffer. **/ @@ -512,6 +515,19 @@ gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader) g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL); priv = loader->private; + + if (priv->animation) + { + GList *list; + + list = gdk_pixbuf_animation_get_frames (priv->animation); + if (list != NULL) + { + GdkPixbufFrame *frame = list->data; + + return gdk_pixbuf_frame_get_pixbuf (frame); + } + } return priv->pixbuf; } |