summaryrefslogtreecommitdiffstats
path: root/karbon/render
diff options
context:
space:
mode:
Diffstat (limited to 'karbon/render')
-rw-r--r--karbon/render/Makefile.am34
-rw-r--r--karbon/render/art_render_misc.c403
-rw-r--r--karbon/render/art_render_misc.h109
-rw-r--r--karbon/render/art_render_pattern.c111
-rw-r--r--karbon/render/art_render_pattern.h58
-rw-r--r--karbon/render/art_rgb.c174
-rw-r--r--karbon/render/art_rgb.h44
-rw-r--r--karbon/render/art_rgb_affine_private.c127
-rw-r--r--karbon/render/art_rgb_affine_private.h39
-rw-r--r--karbon/render/art_rgb_svp.c458
-rw-r--r--karbon/render/art_rgb_svp.h55
-rw-r--r--karbon/render/art_rgba_affine.c107
-rw-r--r--karbon/render/art_rgba_affine.h50
-rw-r--r--karbon/render/vkopainter.cc943
-rw-r--r--karbon/render/vkopainter.h124
-rw-r--r--karbon/render/vpainter.h102
-rw-r--r--karbon/render/vpainterfactory.cc74
-rw-r--r--karbon/render/vpainterfactory.h48
-rw-r--r--karbon/render/vqpainter.cc284
-rw-r--r--karbon/render/vqpainter.h95
-rw-r--r--karbon/render/xrgbrender/Makefile.am5
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlib-drawable.c1137
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlib-private.h39
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlib-render.c380
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlib.c63
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlib.h80
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.c3724
-rw-r--r--karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.h194
28 files changed, 9061 insertions, 0 deletions
diff --git a/karbon/render/Makefile.am b/karbon/render/Makefile.am
new file mode 100644
index 00000000..5f604f6c
--- /dev/null
+++ b/karbon/render/Makefile.am
@@ -0,0 +1,34 @@
+SUBDIRS = xrgbrender
+
+INCLUDES = $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/xrgbrender \
+ -I$(srcdir)/../core \
+ $(LIBART_CFLAGS) \
+ $(all_includes)
+
+noinst_LTLIBRARIES = libvpainter.la
+
+noinst_HEADERS = \
+ vpainter.h \
+ vpainterfactory.h \
+ vqpainter.h \
+ art_render_pattern.h \
+ art_render_misc.h \
+ art_rgb_svp.h \
+ art_rgb.h \
+ art_rgba_affine.h \
+ vkopainter.h
+
+libvpainter_la_SOURCES = \
+ vpainterfactory.cc \
+ vqpainter.cc \
+ art_render_pattern.c \
+ art_render_misc.c \
+ art_rgb_svp.c \
+ art_rgb.c \
+ art_rgba_affine.c \
+ vkopainter.cc
+
+libvpainter_la_METASOURCES = \
+ AUTO
diff --git a/karbon/render/art_render_misc.c b/karbon/render/art_render_misc.c
new file mode 100644
index 00000000..088a3984
--- /dev/null
+++ b/karbon/render/art_render_misc.c
@@ -0,0 +1,403 @@
+/* This file is part of the KDE project.
+ * art_render_misc.c: Here I store some routines I feel should be in libart :)
+ *
+ * Copyright (C) 2002, The Karbon Developers
+ *
+ * This code is adapted from :
+ *
+ * art_render_gradient.c: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ * Alexander Larsson <alla@lysator.liu.se>
+ */
+
+#include "config.h"
+#include "art_render_misc.h"
+
+#include <math.h>
+
+typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
+typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
+typedef struct _ArtImageSourceGradCon ArtImageSourceGradCon;
+
+struct _ArtImageSourceGradLin {
+ ArtImageSource super;
+ const ArtGradientLinear *gradient;
+};
+
+struct _ArtImageSourceGradRad {
+ ArtImageSource super;
+ const ArtGradientRadial *gradient;
+ double a;
+};
+
+struct _ArtImageSourceGradCon {
+ ArtImageSource super;
+ const ArtGradientConical *gradient;
+};
+
+
+#define EPSILON 1e-6
+
+/**
+ * art_karbon_render_gradient_setpix: Set a gradient pixel.
+ * @render: The render object.
+ * @dst: Pointer to destination (where to store pixel).
+ * @n_stops: Number of stops in @stops.
+ * @stops: The stops for the gradient.
+ * @offset: The offset.
+ *
+ * @n_stops must be > 0.
+ *
+ * Sets a gradient pixel, storing it at @dst.
+ **/
+static void
+art_karbon_render_gradient_setpix (ArtRender *render,
+ art_u8 *dst,
+ int n_stops, ArtGradientStop *stops,
+ double offset)
+{
+ int ix;
+ int j;
+ double off0, off1;
+ int n_ch = render->n_chan + 1;
+
+ for (ix = 0; ix < n_stops; ix++)
+ if (stops[ix].offset > offset)
+ break;
+ /* stops[ix - 1].offset < offset < stops[ix].offset */
+ if (ix > 0 && ix < n_stops)
+ {
+ off0 = stops[ix - 1].offset;
+ off1 = stops[ix].offset;
+ if (fabs (off1 - off0) > EPSILON)
+ {
+ double interp;
+
+ interp = (offset - off0) / (off1 - off0);
+ for (j = 0; j < n_ch; j++)
+ {
+ int z0, z1;
+ int z;
+ z0 = stops[ix - 1].color[j];
+ z1 = stops[ix].color[j];
+ z = floor (z0 + (z1 - z0) * interp + 0.5);
+ if (render->buf_depth == 8)
+ dst[j] = ART_PIX_8_FROM_MAX (z);
+ else /* (render->buf_depth == 16) */
+ ((art_u16 *)dst)[j] = z;
+ }
+ return;
+ }
+ }
+ else if (ix == n_stops)
+ ix--;
+
+ for (j = 0; j < n_ch; j++)
+ {
+ int z;
+ z = stops[ix].color[j];
+ if (render->buf_depth == 8)
+ dst[j] = ART_PIX_8_FROM_MAX (z);
+ else /* (render->buf_depth == 16) */
+ ((art_u16 *)dst)[j] = z;
+ }
+}
+
+static void
+art_karbon_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_karbon_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+ const ArtGradientLinear *gradient = z->gradient;
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int x;
+ int width = render->x1 - render->x0;
+ double offset, d_offset;
+ double actual_offset;
+ int n_stops = gradient->n_stops;
+ ArtGradientStop *stops = gradient->stops;
+ art_u8 *bufp = render->image_buf;
+ ArtGradientSpread spread = gradient->spread;
+
+ offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
+ d_offset = gradient->a;
+
+ for (x = 0; x < width; x++)
+ {
+ if (spread == ART_GRADIENT_PAD)
+ actual_offset = offset;
+ else if (spread == ART_GRADIENT_REPEAT)
+ actual_offset = offset - floor (offset);
+ else /* (spread == ART_GRADIENT_REFLECT) */
+ {
+ double tmp;
+
+ tmp = offset - 2 * floor (0.5 * offset);
+ actual_offset = tmp > 1 ? 2 - tmp : tmp;
+ }
+ art_karbon_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset);
+ offset += d_offset;
+ bufp += pixstride;
+ }
+}
+
+static void
+art_karbon_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_karbon_render_gradient_linear_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_karbon_render_gradient_linear: Add a linear gradient image source.
+ * @render: The render object.
+ * @gradient: The linear gradient.
+ *
+ * Adds the linear gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_karbon_render_gradient_linear (ArtRender *render,
+ const ArtGradientLinear *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradLin *image_source = art_new (ArtImageSourceGradLin, 1);
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_karbon_render_gradient_linear_done;
+ image_source->super.negotiate = art_karbon_render_gradient_linear_negotiate;
+
+ image_source->gradient = gradient;
+
+ art_render_add_image_source (render, &image_source->super);
+}
+
+static void
+art_karbon_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_karbon_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
+ const ArtGradientRadial *gradient = z->gradient;
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int x;
+ int x0 = render->x0;
+ int width = render->x1 - x0;
+ int n_stops = gradient->n_stops;
+ ArtGradientStop *stops = gradient->stops;
+ art_u8 *bufp = render->image_buf;
+ double fx = gradient->fx;
+ double fy = gradient->fy;
+ double dx, dy;
+ double *affine = gradient->affine;
+ double aff0 = affine[0];
+ double aff1 = affine[1];
+ const double a = z->a;
+ const double arecip = 1.0 / a;
+ double b, db;
+ double c, dc, ddc;
+ double b_a, db_a;
+ double rad, drad, ddrad;
+ ArtGradientSpread spread = gradient->spread;
+
+ dx = x0 * aff0 + y * affine[2] + affine[4] - fx;
+ dy = x0 * aff1 + y * affine[3] + affine[5] - fy;
+ b = dx * fx + dy * fy;
+ db = aff0 * fx + aff1 * fy;
+ c = dx * dx + dy * dy;
+ dc = 2 * aff0 * dx + aff0 * aff0 + 2 * aff1 * dy + aff1 * aff1;
+ ddc = 2 * aff0 * aff0 + 2 * aff1 * aff1;
+
+ b_a = b * arecip;
+ db_a = db * arecip;
+
+ rad = b_a * b_a + c * arecip;
+ drad = 2 * b_a * db_a + db_a * db_a + dc * arecip;
+ ddrad = 2 * db_a * db_a + ddc * arecip;
+
+ for (x = 0; x < width; x++)
+ {
+ double z;
+
+ if (rad > 0)
+ z = b_a + sqrt (rad);
+ else
+ z = b_a;
+
+ if (spread == ART_GRADIENT_REPEAT)
+ z = z - floor (z);
+ else if (spread == ART_GRADIENT_REFLECT)
+ {
+ double tmp;
+
+ tmp = z - 2 * floor (0.5 * z);
+ z = tmp > 1 ? 2 - tmp : tmp;
+ }
+
+ art_karbon_render_gradient_setpix (render, bufp, n_stops, stops, z);
+ bufp += pixstride;
+ b_a += db_a;
+ rad += drad;
+ drad += ddrad;
+ }
+}
+
+static void
+art_karbon_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_karbon_render_gradient_radial_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_karbon_render_gradient_radial: Add a radial gradient image source.
+ * @render: The render object.
+ * @gradient: The radial gradient.
+ *
+ * Adds the radial gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_karbon_render_gradient_radial (ArtRender *render,
+ const ArtGradientRadial *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradRad *image_source = art_new (ArtImageSourceGradRad, 1);
+ double fx = gradient->fx;
+ double fy = gradient->fy;
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_karbon_render_gradient_radial_done;
+ image_source->super.negotiate = art_karbon_render_gradient_radial_negotiate;
+
+ image_source->gradient = gradient;
+ /* todo: sanitycheck fx, fy? */
+ image_source->a = 1 - fx * fx - fy * fy;
+
+ art_render_add_image_source (render, &image_source->super);
+}
+
+/* Conical */
+
+static void
+art_render_gradient_conical_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_render_gradient_conical_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradCon *z = (ArtImageSourceGradCon *)self;
+ const ArtGradientConical *gradient = z->gradient;
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int x;
+ int x0 = render->x0;
+ int width = render->x1 - x0;
+ int n_stops = gradient->n_stops;
+ ArtGradientStop *stops = gradient->stops;
+ art_u8 *bufp = render->image_buf;
+ double cx = gradient->cx;
+ double cy = gradient->cy;
+ double r = gradient->r;
+ double dx, dy;
+ ArtGradientSpread spread = gradient->spread;
+
+ dy = fabs(y) - fabs(cy);
+
+ for (x = 0; x < width; x++)
+ {
+ double z;
+ dx = fabs(x0 + x) - fabs(cx);
+
+ z = (fabs(dx) + fabs(dy)) / (r);
+
+ if (spread == ART_GRADIENT_REPEAT)
+ z = z - floor (z);
+ else if (spread == ART_GRADIENT_REFLECT)
+ {
+ double tmp;
+
+ tmp = z - 2 * floor (0.5 * z);
+ z = tmp > 1 ? 2 - tmp : tmp;
+ }
+
+ art_karbon_render_gradient_setpix (render, bufp, n_stops, stops, z);
+ bufp += pixstride;
+ }
+}
+
+static void
+art_render_gradient_conical_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_render_gradient_conical_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_render_gradient_radial: Add a radial gradient image source.
+ * @render: The render object.
+ * @gradient: The radial gradient.
+ *
+ * Adds the radial gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_karbon_render_gradient_conical (ArtRender *render,
+ const ArtGradientConical *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradCon *image_source = art_new (ArtImageSourceGradCon, 1);
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_render_gradient_conical_done;
+ image_source->super.negotiate = art_render_gradient_conical_negotiate;
+
+ image_source->gradient = gradient;
+
+ art_render_add_image_source (render, &image_source->super);
+}
+
diff --git a/karbon/render/art_render_misc.h b/karbon/render/art_render_misc.h
new file mode 100644
index 00000000..9d4b444c
--- /dev/null
+++ b/karbon/render/art_render_misc.h
@@ -0,0 +1,109 @@
+/* This file is part of the KDE project.
+ * art_render_misc.c: Here I store some routines I feel should be in libart :)
+ *
+ * Copyright (C) 2002, The Karbon Developers
+ *
+ * This code is adapted from :
+ *
+ * art_render_gradient.h: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ * Alexander Larsson <alla@lysator.liu.se>
+ */
+
+#ifndef __ART_RENDER_MISC_H__
+#define __ART_RENDER_MISC_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_render.h"
+#else
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_render.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtGradientLinear ArtGradientLinear;
+typedef struct _ArtGradientRadial ArtGradientRadial;
+typedef struct _ArtGradientConical ArtGradientConical;
+typedef struct _ArtGradientStop ArtGradientStop;
+
+typedef enum {
+ ART_GRADIENT_PAD,
+ ART_GRADIENT_REFLECT,
+ ART_GRADIENT_REPEAT
+} ArtGradientSpread;
+
+struct _ArtGradientLinear {
+ double a;
+ double b;
+ double c;
+ ArtGradientSpread spread;
+ int n_stops;
+ ArtGradientStop *stops;
+};
+
+struct _ArtGradientRadial {
+ double affine[6]; /* transforms user coordinates to unit circle */
+ double fx, fy; /* focal point in unit circle coords */
+ int n_stops;
+ ArtGradientSpread spread;
+ ArtGradientStop *stops;
+};
+
+struct _ArtGradientConical {
+ double cx, cy; /* focal point in unit circle coords */
+ double r; /* focal point in unit circle coords */
+ ArtGradientSpread spread;
+ art_u8 *buf;
+ int n_stops;
+ ArtGradientStop *stops;
+};
+
+
+struct _ArtGradientStop {
+ double offset;
+ ArtPixMaxDepth color[ART_MAX_CHAN + 1];
+};
+
+void
+art_karbon_render_gradient_linear (ArtRender *render,
+ const ArtGradientLinear *gradient,
+ ArtFilterLevel level);
+
+void
+art_karbon_render_gradient_radial (ArtRender *render,
+ const ArtGradientRadial *gradient,
+ ArtFilterLevel level);
+
+void
+art_karbon_render_gradient_conical (ArtRender *render,
+ const ArtGradientConical *gradient,
+ ArtFilterLevel level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_MISC_H__ */
diff --git a/karbon/render/art_render_pattern.c b/karbon/render/art_render_pattern.c
new file mode 100644
index 00000000..9245402d
--- /dev/null
+++ b/karbon/render/art_render_pattern.c
@@ -0,0 +1,111 @@
+/*
+ * art_render_pattern.c:
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "art_render_pattern.h"
+
+#include <math.h>
+
+typedef struct _ArtImageSourcePattern ArtImageSourcePattern;
+
+struct _ArtImageSourcePattern {
+ ArtImageSource super;
+ const ArtPattern *pattern;
+};
+
+static void
+art_render_pattern_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_render_pattern_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourcePattern *z = (ArtImageSourcePattern *)self;
+ const ArtPattern *pattern = z->pattern;
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int n_ch = render->n_chan + 1;
+ int x, j, index;
+ int width = render->x1 - render->x0;
+ int twidth = pattern->twidth;
+ int theight = pattern->theight;
+ art_u8 *bufp = render->image_buf;
+
+ double angle = pattern->angle;
+ double opacity = pattern->opacity;
+ double cosangle = cos(angle);
+ double sinangle = sin(angle);
+
+ y = y - render->y0;
+
+ if(theight == 0) return;
+
+ for (x = 0; x < width; x++)
+ {
+ int x0 = sinangle * y + cosangle * x;
+ int y0 = -sinangle * x + cosangle * y;
+ x0 = (x0 % twidth);
+ if(x0 < 0) x0 += twidth;
+ y0 = (y0 % theight);
+ if(y0 < 0) y0 += theight;
+ index = (((y0 * twidth + x0) * pixstride) % (twidth * theight * 4));
+ /*for (j = 0; j < n_ch - 1; j++)
+ {*/
+ /* bgra -> rgba */
+ bufp[0] = pattern->buffer[index + 2];
+ bufp[1] = pattern->buffer[index + 1];
+ bufp[2] = pattern->buffer[index + 0];
+ bufp[3] = opacity;
+ /*}*/
+ bufp += pixstride;
+ }
+}
+
+static void
+art_render_pattern_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_render_pattern_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_SEPARATE;
+}
+
+void
+art_render_pattern (ArtRender *render,
+ const ArtPattern *pattern,
+ ArtFilterLevel level)
+{
+ ArtImageSourcePattern *image_source = art_new (ArtImageSourcePattern, 1);
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_render_pattern_done;
+ image_source->super.negotiate = art_render_pattern_negotiate;
+
+ image_source->pattern = pattern;
+
+ art_render_add_image_source (render, &image_source->super);
+}
diff --git a/karbon/render/art_render_pattern.h b/karbon/render/art_render_pattern.h
new file mode 100644
index 00000000..c70b76c6
--- /dev/null
+++ b/karbon/render/art_render_pattern.h
@@ -0,0 +1,58 @@
+/*
+ * art_render_pattern.h:
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __ART_RENDER_PATTERN_H__
+#define __ART_RENDER_PATTERN_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_render.h"
+#else
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_render.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtPattern ArtPattern;
+
+struct _ArtPattern {
+ unsigned int twidth; /* width of tile */
+ unsigned int theight; /* height of tile */
+ art_u8 opacity; /* opacity level */
+ double angle;
+ art_u8 *buffer; /* image source */
+};
+
+void
+art_render_pattern (ArtRender *render,
+ const ArtPattern *pattern,
+ ArtFilterLevel level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_PATTERN_H__ */
diff --git a/karbon/render/art_rgb.c b/karbon/render/art_rgb.c
new file mode 100644
index 00000000..4d30fad4
--- /dev/null
+++ b/karbon/render/art_rgb.c
@@ -0,0 +1,174 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "art_rgb.h"
+
+#include <string.h> /* for memset */
+
+/* Basic operators for manipulating 24-bit packed RGB buffers. */
+
+#define COLOR_RUN_SIMPLE
+
+#ifdef COLOR_RUN_SIMPLE
+/* This is really slow. Is there any way we might speed it up?
+ Two ideas:
+
+ First, maybe we should be working at 32-bit alignment. Then,
+ this can be a simple loop over word stores.
+
+ Second, we can keep working at 24-bit alignment, but have some
+ intelligence about storing. For example, we can iterate over
+ 4-pixel chunks (aligned at 4 pixels), with an inner loop
+ something like:
+
+ *buf++ = v1;
+ *buf++ = v2;
+ *buf++ = v3;
+
+ One source of extra complexity is the need to make sure linebuf is
+ aligned to a 32-bit boundary.
+
+ This second alternative has some complexity to it, but is
+ appealing because it really minimizes the memory bandwidth. */
+void
+art_rgb_fill_run_ (art_u8 *buf, art_u32 rgb, int n)
+{
+ int i;
+ art_u32 *b = (art_u32 *)buf;
+ for (i = 0; i < n; i++)
+ {
+ *b = rgb;
+ b++;
+ }
+}
+#endif
+
+#ifdef COLOR_RUN_COMPLEX
+/* This implements the second of the two ideas above. The test results
+ are _very_ encouraging - it seems the speed is within 10% of
+ memset, which is quite good! */
+/**
+ * art_rgb_fill_run: fill a buffer a solid RGB color.
+ * @buf: Buffer to fill.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @n: Number of RGB triples to fill.
+ *
+ * Fills a buffer with @n copies of the (@r, @g, @b) triple. Thus,
+ * locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
+ * written.
+ *
+ * The implementation of this routine is very highly optimized.
+ **/
+void
+art_rgb_fill_run_ (art_u8 *buf, art_u32 rgb, int n)
+{
+ int i;
+ unsigned int v1, v2, v3;
+
+ if (r == g && g == b)
+ {
+ memset (buf, g, 4*n);
+ }
+ else
+ {
+ if (n < 8)
+ {
+ for (i = 0; i < n; i++)
+ {
+ buf++;
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+ } else {
+ /* handle prefix up to byte alignment */
+ /* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
+ architectures, but it _should_ work. */
+ for (i = 0; ((unsigned long)buf) & 3; i++)
+ {
+ buf++;
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+#ifndef WORDS_BIGENDIAN
+ v1 = r | (g << 8) | (b << 16) | (r << 24);
+ v3 = (v1 << 8) | b;
+ v2 = (v3 << 8) | g;
+#else
+ v1 = (r << 24) | (g << 16) | (b << 8) | r;
+ v2 = (v1 << 8) | g;
+ v3 = (v2 << 8) | b;
+#endif
+ for (; i < n - 3; i += 4)
+ {/*
+ ((art_u32 *)buf)[0] = v1;
+ ((art_u32 *)buf)[1] = v2;
+ ((art_u32 *)buf)[2] = v3;
+ buf += 12;*/
+ ((art_u32 *)buf)[1] = v1;
+ ((art_u32 *)buf)[2] = v2;
+ ((art_u32 *)buf)[3] = v3;
+ buf += 16;
+ }
+ /* handle postfix */
+ for (; i < n; i++)
+ {
+ buf++;
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+ }
+ }
+}
+#endif
+
+/**
+ * art_rgb_run_alpha: Render semitransparent color over RGB buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..256.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha.
+ **/
+void
+art_rgb_run_alpha_ (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+ int v;
+ for (i = 0; i < n; i++)
+ {
+ v = *buf;
+ *buf++ = v + (((b - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ *buf++ = v + (((g - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ *buf++ = v + (((r - v) * alpha + 0x80) >> 8);
+ buf++;
+ }
+}
+
diff --git a/karbon/render/art_rgb.h b/karbon/render/art_rgb.h
new file mode 100644
index 00000000..1f2c6919
--- /dev/null
+++ b/karbon/render/art_rgb.h
@@ -0,0 +1,44 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ART_RGB_H__
+#define __ART_RGB_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include <libart_lgpl/art_misc.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_fill_run_ (art_u8 *buf, art_u32 rgb, int n);
+
+void
+art_rgb_run_alpha_ (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha,
+ int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/karbon/render/art_rgb_affine_private.c b/karbon/render/art_rgb_affine_private.c
new file mode 100644
index 00000000..4a92a301
--- /dev/null
+++ b/karbon/render/art_rgb_affine_private.c
@@ -0,0 +1,127 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_affine_private.h"
+
+#include <math.h>
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_point.h>
+#include <libart_lgpl/art_affine.h>
+
+/* Private functions for the rgb affine image compositors - primarily,
+ the determination of runs, eliminating the need for source image
+ bbox calculation in the inner loop. */
+
+/* Determine a "run", such that the inverse affine of all pixels from
+ (x0, y) inclusive to (x1, y) exclusive fit within the bounds
+ of the source image.
+
+ Initial values of x0, x1, and result values stored in first two
+ pointer arguments.
+*/
+
+#define EPSILON 1e-6
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+ int src_width, int src_height,
+ const double affine[6])
+{
+ int x0, x1;
+ double z;
+ double x_intercept;
+ int xi;
+
+ x0 = *p_x0;
+ x1 = *p_x1;
+
+ /* do left and right edges */
+ if (affine[0] > EPSILON)
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ x_intercept = -z / affine[0];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = (-z + src_width) / affine[0];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else if (affine[0] < -EPSILON)
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ x_intercept = (-z + src_width) / affine[0];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = -z / affine[0];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ if (z < 0 || z >= src_width)
+ {
+ *p_x1 = *p_x0;
+ return;
+ }
+ }
+
+ /* do top and bottom edges */
+ if (affine[1] > EPSILON)
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ x_intercept = -z / affine[1];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = (-z + src_height) / affine[1];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else if (affine[1] < -EPSILON)
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ x_intercept = (-z + src_height) / affine[1];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = -z / affine[1];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ if (z < 0 || z >= src_height)
+ {
+ *p_x1 = *p_x0;
+ return;
+ }
+ }
+
+ *p_x0 = x0;
+ *p_x1 = x1;
+}
diff --git a/karbon/render/art_rgb_affine_private.h b/karbon/render/art_rgb_affine_private.h
new file mode 100644
index 00000000..a2424999
--- /dev/null
+++ b/karbon/render/art_rgb_affine_private.h
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_PRIVATE_H__
+#define __ART_RGB_AFFINE_PRIVATE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+ int src_width, int src_height,
+ const double affine[6]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/karbon/render/art_rgb_svp.c b/karbon/render/art_rgb_svp.c
new file mode 100644
index 00000000..617f1abe
--- /dev/null
+++ b/karbon/render/art_rgb_svp.c
@@ -0,0 +1,458 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#include "config.h"
+#include "art_rgb_svp.h"
+
+#include <libart_lgpl/art_svp.h>
+#include <libart_lgpl/art_svp_render_aa.h>
+#include "art_rgb.h"
+
+typedef struct _ArtRgbSVPData ArtRgbSVPData;
+typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
+
+struct _ArtRgbSVPData {
+ art_u32 rgbtab[256];
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+};
+
+struct _ArtRgbSVPAlphaData {
+ int alphatab[256];
+ art_u8 r, g, b, alpha;
+ art_u32 rgb;
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+};
+
+static void
+art_rgb_svp_callback_ (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ art_u32 rgb;
+ int x0, x1;
+ int k;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+/* art_rgb_fill_run (linebuf,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - x0);*/
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+/* art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - run_x0);*/
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+/* art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ x1 - run_x1);*/
+ }
+ }
+ else
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+/* art_rgb_fill_run (linebuf,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ x1 - x0);*/
+ }
+
+ data->buf += data->rowstride;
+}
+
+/* Render the vector path into the RGB buffer. */
+
+/**
+ * art_rgb_svp_aa: Render sorted vector path into RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @fg_color: Foreground color in 0xRRGGBB format.
+ * @bg_color: Background color in 0xRRGGBB format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
+ *
+ * Renders the shape specified with @svp into the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @fg_color and @bg_color arguments specify the opaque colors to
+ * be used for rendering. For pixels of entirely 0 winding-number,
+ * @bg_color is used. For pixels of entirely 1 winding number,
+ * @fg_color is used. In between, the color is interpolated based on
+ * the fraction of the pixel with a winding number of 1. If
+ * @alphagamma is NULL, then linear interpolation (in pixel counts) is
+ * the default. Otherwise, the interpolation is as specified by
+ * @alphagamma.
+ **/
+void
+art_rgb_svp_aa_ (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 fg_color, art_u32 bg_color,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma)
+{
+ ArtRgbSVPData data;
+
+ int r_fg, g_fg, b_fg;
+ int r_bg, g_bg, b_bg;
+ int r, g, b;
+ int dr, dg, db;
+ int i;
+
+ if (alphagamma == NULL)
+ {
+ r_fg = fg_color >> 16;
+ g_fg = (fg_color >> 8) & 0xff;
+ b_fg = fg_color & 0xff;
+
+ r_bg = bg_color >> 16;
+ g_bg = (bg_color >> 8) & 0xff;
+ b_bg = bg_color & 0xff;
+
+ r = (r_bg << 16) + 0x8000;
+ g = (g_bg << 16) + 0x8000;
+ b = (b_bg << 16) + 0x8000;
+ dr = ((r_fg - r_bg) << 16) / 255;
+ dg = ((g_fg - g_bg) << 16) / 255;
+ db = ((b_fg - b_bg) << 16) / 255;
+
+ for (i = 0; i < 256; i++)
+ {
+ data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
+ r += dr;
+ g += dg;
+ b += db;
+ }
+ }
+ else
+ {
+ int *table;
+ art_u8 *invtab;
+
+ table = alphagamma->table;
+
+ r_fg = table[fg_color >> 16];
+ g_fg = table[(fg_color >> 8) & 0xff];
+ b_fg = table[fg_color & 0xff];
+
+ r_bg = table[bg_color >> 16];
+ g_bg = table[(bg_color >> 8) & 0xff];
+ b_bg = table[bg_color & 0xff];
+
+ r = (r_bg << 16) + 0x8000;
+ g = (g_bg << 16) + 0x8000;
+ b = (b_bg << 16) + 0x8000;
+ dr = ((r_fg - r_bg) << 16) / 255;
+ dg = ((g_fg - g_bg) << 16) / 255;
+ db = ((b_fg - b_bg) << 16) / 255;
+
+ invtab = alphagamma->invtable;
+ for (i = 0; i < 256; i++)
+ {
+ data.rgbtab[i] = (invtab[r >> 16] << 16) |
+ (invtab[g >> 16] << 8) |
+ invtab[b >> 16];
+ r += dr;
+ g += dg;
+ b += db;
+ }
+ }
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback_, &data);
+}
+
+static void
+art_rgb_svp_alpha_callback_ (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ art_u8 r, g, b;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ alphatab = data->alphatab;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha_ (linebuf,
+ r, g, b, alphatab[alpha],
+ run_x1 - x0);
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha_ (linebuf + (run_x0 - x0) * 4,
+ r, g, b, alphatab[alpha],
+ run_x1 - run_x0);
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha_ (linebuf + (run_x1 - x0) * 4,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha_ (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+
+ data->buf += data->rowstride;
+}
+
+static void
+art_rgb_svp_alpha_opaque_callback_ (void *callback_data, int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ art_u8 r, g, b;
+ art_u32 rgb;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ rgb = data->rgb;
+ alphatab = data->alphatab;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run_ (linebuf,
+ rgb,
+ run_x1 - x0);
+ else
+ art_rgb_run_alpha_ (linebuf,
+ r, g, b, alphatab[alpha],
+ run_x1 - x0);
+ }
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run_ (linebuf + (run_x0 - x0) * 4,
+ rgb,
+ run_x1 - run_x0);
+ else
+ art_rgb_run_alpha_ (linebuf + (run_x0 - x0) * 4,
+ r, g, b, alphatab[alpha],
+ run_x1 - run_x0);
+ }
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run_ (linebuf + (run_x1 - x0) * 4,
+ rgb,
+ x1 - run_x1);
+ else
+ art_rgb_run_alpha_ (linebuf + (run_x1 - x0) * 4,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ }
+ else
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run_ (linebuf,
+ rgb,
+ x1 - x0);
+ else
+ art_rgb_run_alpha_ (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+ }
+ data->buf += data->rowstride;
+}
+
+/**
+ * art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @rgba: Color in 0xRRGGBBAA format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Renders the shape specified with @svp over the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @rgba argument specifies the color for the rendering. Pixels of
+ * entirely 0 winding number are left untouched. Pixels of entirely
+ * 1 winding number have the color @rgba composited over them (ie,
+ * are replaced by the red, green, blue components of @rgba if the alpha
+ * component is 0xff). Pixels of intermediate coverage are interpolated
+ * according to the rule in @alphagamma, or default to linear if
+ * @alphagamma is NULL.
+ **/
+void
+art_rgb_svp_alpha_ (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgb, int alpha,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma)
+{
+ ArtRgbSVPAlphaData data;
+ int r, g, b;
+ int i;
+ int a, da;
+
+ r = (rgb >> 16) & 0xff;
+ g = (rgb >> 8) & 0xff;
+ b = rgb & 0xff;
+
+ data.r = r;
+ data.g = g;
+ data.b = b;
+ data.alpha = alpha;
+ data.rgb = rgb;
+
+ a = 0x8000;
+ da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
+
+ for (i = 0; i < 256; i++)
+ {
+ data.alphatab[i] = a >> 16;
+ a += da;
+ }
+
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ if (alpha == 255)
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback_,
+ &data);
+ else
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback_, &data);
+}
diff --git a/karbon/render/art_rgb_svp.h b/karbon/render/art_rgb_svp.h
new file mode 100644
index 00000000..77b32dd9
--- /dev/null
+++ b/karbon/render/art_rgb_svp.h
@@ -0,0 +1,55 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ART_RGB_SVP_H__
+#define __ART_RGB_SVP_H__
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#ifdef LIBART_COMPILATION
+#include "art_alphagamma.h"
+#include "art_svp.h"
+#else
+#include <libart_lgpl/art_alphagamma.h>
+#include <libart_lgpl/art_svp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_rgb_svp_aa_ (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 fg_color, art_u32 bg_color,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma);
+
+void
+art_rgb_svp_alpha_ (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgb, int alpha,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RGB_SVP_H__ */
diff --git a/karbon/render/art_rgba_affine.c b/karbon/render/art_rgba_affine.c
new file mode 100644
index 00000000..9ff88d5f
--- /dev/null
+++ b/karbon/render/art_rgba_affine.c
@@ -0,0 +1,107 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "art_rgba_affine.h"
+
+#include <math.h>
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_point.h>
+#include <libart_lgpl/art_affine.h>
+#include <art_rgb_affine_private.h>
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+/**
+ * art_rgb_affine: Affine transform source RGB image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGB buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be done
+ * in a gamma-corrected color space. Since the source image is opaque RGB,
+ * this argument only affects the edges. In the current implementation,
+ * it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgba_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int run_x0, run_x1;
+
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 4;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+ dst_p[0] = src_p[0];
+ dst_p[1] = src_p[1];
+ dst_p[2] = src_p[2];
+ dst_p[3] = src_p[3];
+ dst_p += 4;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
diff --git a/karbon/render/art_rgba_affine.h b/karbon/render/art_rgba_affine.h
new file mode 100644
index 00000000..3403691b
--- /dev/null
+++ b/karbon/render/art_rgba_affine.h
@@ -0,0 +1,50 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_H__
+#define __ART_RGB_AFFINE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgba_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/karbon/render/vkopainter.cc b/karbon/render/vkopainter.cc
new file mode 100644
index 00000000..21ab911c
--- /dev/null
+++ b/karbon/render/vkopainter.cc
@@ -0,0 +1,943 @@
+/* This file is part of the KDE project.
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+// kopainter/libart wrapper
+
+#include "vkopainter.h"
+#include "vstroke.h"
+#include "vfill.h"
+#include "vcolor.h"
+#include "vpattern.h"
+
+#include <qpaintdevice.h>
+#include <qpixmap.h>
+#include <qpointarray.h>
+#include <qimage.h>
+
+#include "libart_lgpl/art_vpath.h"
+#include <libart_lgpl/art_bpath.h>
+#include <libart_lgpl/art_vpath_bpath.h>
+#include <libart_lgpl/art_svp_vpath.h>
+#include <libart_lgpl/art_svp_vpath_stroke.h>
+#include <libart_lgpl/art_svp.h>
+#include <libart_lgpl/art_svp_ops.h>
+#include <libart_lgpl/art_affine.h>
+#include <libart_lgpl/art_svp_intersect.h>
+#include <libart_lgpl/art_rect_svp.h>
+#include <libart_lgpl/art_pathcode.h>
+#include <libart_lgpl/art_vpath_dash.h>
+#include "art_rgba_affine.h"
+#include "art_render_misc.h"
+#include <libart_lgpl/art_render_svp.h>
+
+#include "art_rgb_svp.h"
+#include "art_render_pattern.h"
+
+#include <X11/Xlib.h>
+
+#include <gdk-pixbuf-xlibrgb.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <math.h>
+
+#include <KoPoint.h>
+#include <KoRect.h>
+#include <karbon_factory.h>
+#include <karbon_resourceserver.h>
+
+
+#define INITIAL_ALLOC 300
+#define ALLOC_INCREMENT 100
+
+VKoPainter::VKoPainter( QPaintDevice *target, unsigned int w, unsigned int h, bool bDrawNodes )
+: VPainter( target, w, h ), m_target( target ), m_bDrawNodes( bDrawNodes )
+{
+ //kdDebug(38000) << "w : " << w << endl;
+ //kdDebug(38000) << "h : " << h << endl;
+ m_width = w;//( w > 0 ) ? w : target->width();
+ m_height= h;//( h > 0 ) ? h : target->height();
+ m_buffer = 0L;
+ m_path = 0L;
+ m_index = 0;
+ resize( m_width, m_height );
+ clear();
+ m_clipPaths.setAutoDelete( false );
+
+ m_stroke = 0L;
+ m_fill = 0L;
+ m_fillRule = evenOdd;
+
+ xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(),
+ target->x11Screen() ), target->x11Depth() );
+
+ gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 );
+
+ m_zoomFactor = 1;
+}
+
+VKoPainter::VKoPainter( unsigned char *buffer, unsigned int w, unsigned int h, bool bDrawNodes )
+: VPainter( 0L, w, h ), m_buffer( buffer ), m_bDrawNodes( bDrawNodes )
+{
+ //kdDebug(38000) << "w : " << w << endl;
+ //kdDebug(38000) << "h : " << h << endl;
+ m_target = 0L;
+ m_width = w;
+ m_height= h;
+ m_path = 0L;
+ m_index = 0;
+ clear();
+ m_clipPaths.setAutoDelete( false );
+
+ m_stroke = 0L;
+ m_fill = 0L;
+
+ gc = 0L;
+
+ m_zoomFactor = 1;
+}
+
+VKoPainter::~VKoPainter()
+{
+ // If we are in target mode, we created a buffer, else if we used the other ctor
+ // we didn't.
+ if( m_target )
+ art_free( m_buffer );
+
+ delete m_stroke;
+ delete m_fill;
+ if( m_path )
+ art_free( m_path );
+
+ if( gc )
+ XFreeGC( m_target->x11Display(), gc );
+}
+
+void
+VKoPainter::resize( unsigned int w, unsigned int h )
+{
+ if( !m_buffer || w != m_width || h != m_height )
+ {
+ // TODO : realloc?
+ art_free( m_buffer );
+ m_buffer = 0;
+ m_width = w;
+ m_height = h;
+ if ( m_width != 0 && m_height != 0 )
+ m_buffer = art_new( art_u8, m_width * m_height * 4 );
+ clear();
+ }
+}
+
+void
+VKoPainter::begin()
+{
+}
+
+void
+VKoPainter::end()
+{
+ //xlib_draw_rgb_image( m_target->handle(), gc, 0, 0, m_width, m_height,
+ // XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
+ xlib_draw_rgb_32_image( m_target->handle(), gc, 0, 0, m_width, m_height,
+ XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
+ /*xlib_draw_rgb_image( pix.handle(), gc, 0, 0, m_width, m_height,
+ XLIB_RGB_DITHER_NONE, m_buffer, m_width * 3 );
+ bitBlt( m_target, 0, 0, &pix, 0, 0, m_width, m_height );*/
+}
+
+void
+VKoPainter::blit( const KoRect &r )
+{
+ //kdDebug(38000) << "m_width : " << m_width << endl;
+ //kdDebug(38000) << "m_height : " << m_height << endl;
+ int x = KMAX( 0, int( r.x() ) );
+ int y = KMAX( 0, int( r.y() ) );
+ int width = KMIN( m_width, (unsigned int)KMAX( 0, int( r.x() + r.width() ) ) );
+ int height = KMIN( m_height, (unsigned int)KMAX( 0, int( r.y() + r.height() ) ) );
+ xlib_draw_rgb_32_image( m_target->handle(), gc, x, y, width - x, height - y,
+ XLIB_RGB_DITHER_NONE, m_buffer + (x * 4) + (y * m_width * 4), m_width * 4 );
+}
+
+void
+VKoPainter::clear()
+{
+ if( m_buffer )
+ memset( m_buffer, qRgba( 255, 255, 255, 255 ), m_width * m_height * 4 );
+}
+
+void
+VKoPainter::clear( const QColor &c )
+{
+ if( m_buffer )
+ memset( m_buffer, c.rgb(), m_width * m_height * 4 );
+}
+
+void
+VKoPainter::clear( const KoRect &r, const QColor &c )
+{
+ unsigned int color = c.rgb();
+ int x = KMAX( 0, int( r.x() ) );
+ int y = KMAX( 0, int( r.y() ) );
+ int width = KMIN( m_width, (unsigned int)KMAX( 0, int( r.x() + r.width() ) ) );
+ int height = KMIN( m_height, (unsigned int)KMAX( 0, int( r.y() + r.height() ) ) );
+ if( m_buffer )
+ {
+ for( int i = y;i < height;i++)
+ memset( m_buffer + int( x * 4) + int( i * ( m_width * 4 ) ),
+ qRgba( qRed( color ), qGreen( color ), qBlue( color ), 100 ), int( width * 4 ) );
+ }
+}
+
+void
+VKoPainter::setWorldMatrix( const QWMatrix &mat )
+{
+ m_matrix = mat;
+}
+
+void
+VKoPainter::setZoomFactor( double zoomFactor )
+{
+ m_zoomFactor = zoomFactor;
+}
+
+void
+VKoPainter::ensureSpace( unsigned int newindex )
+{
+ if( m_index == 0 )
+ {
+ if( !m_path )
+ m_path = art_new( ArtBpath, INITIAL_ALLOC );
+ m_alloccount = INITIAL_ALLOC;
+ }
+ else if( newindex > m_alloccount )
+ {
+ m_alloccount += ALLOC_INCREMENT;
+ m_path = art_renew( m_path, ArtBpath, m_alloccount );
+ }
+}
+
+void
+VKoPainter::moveTo( const KoPoint &p )
+{
+ ensureSpace( m_index + 1 );
+
+ m_path[ m_index ].code = ART_MOVETO;
+
+ m_path[ m_index ].x3 = p.x() * m_zoomFactor;
+ m_path[ m_index ].y3 = p.y() * m_zoomFactor;
+
+ m_index++;
+}
+
+void
+VKoPainter::lineTo( const KoPoint &p )
+{
+ ensureSpace( m_index + 1 );
+
+ m_path[ m_index ].code = ART_LINETO;
+ m_path[ m_index ].x3 = p.x() * m_zoomFactor;
+ m_path[ m_index ].y3 = p.y() * m_zoomFactor;
+
+ m_index++;
+}
+
+void
+VKoPainter::curveTo( const KoPoint &p1, const KoPoint &p2, const KoPoint &p3 )
+{
+ ensureSpace( m_index + 1 );
+
+ m_path[ m_index ].code = ART_CURVETO;
+ m_path[ m_index ].x1 = p1.x() * m_zoomFactor;
+ m_path[ m_index ].y1 = p1.y() * m_zoomFactor;
+ m_path[ m_index ].x2 = p2.x() * m_zoomFactor;
+ m_path[ m_index ].y2 = p2.y() * m_zoomFactor;
+ m_path[ m_index ].x3 = p3.x() * m_zoomFactor;
+ m_path[ m_index ].y3 = p3.y() * m_zoomFactor;
+
+ m_index++;
+}
+
+void
+VKoPainter::newPath()
+{
+ m_index = 0;
+}
+
+void
+VKoPainter::setFillRule( VFillRule fillRule )
+{
+ m_fillRule = fillRule;
+}
+
+void
+VKoPainter::fillPath()
+{
+ if( m_index == 0 ) return;
+
+ // find begin of last subpath
+ int find = -1;
+ for( int i = m_index - 1; i >= 0; i-- )
+ {
+ if( m_path[i].code == ART_MOVETO_OPEN || m_path[i].code == ART_MOVETO )
+ {
+ find = i;
+ break;
+ }
+ }
+
+ // for now, always close
+ if( find != -1 && ( m_path[ find ].x3 != m_path[ m_index - 1 ].x3 ||
+ m_path[ find ].y3 != m_path[ m_index - 1 ].y3 ) )
+ {
+ ensureSpace( m_index + 1 );
+
+ m_path[ m_index ].code = ART_LINETO;
+ m_path[ m_index ].x3 = m_path[ find ].x3;
+ m_path[ m_index ].y3 = m_path[ find ].y3;
+
+ m_index++;
+ m_path[ m_index ].code = ART_END;
+ }
+ else
+ m_path[ m_index++ ].code = ART_END;
+
+ if( m_fill && m_fill->type() != VFill::none )
+ {
+ ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
+ drawVPath( path );
+ }
+
+ m_index--;
+}
+
+void
+VKoPainter::strokePath()
+{
+ if( m_index == 0 ) return;
+
+ if( m_stroke && m_stroke->lineWidth() == 0 )
+ return;
+ if( m_path[ m_index ].code != ART_END)
+ m_path[ m_index ].code = ART_END;
+
+ ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
+
+ drawVPath( path );
+}
+
+void
+VKoPainter::setClipPath()
+{
+ ArtVpath *path;
+ path = art_bez_path_to_vec( m_path , 0.25 );
+ m_clipPaths.append( art_svp_from_vpath( path ) );
+ art_free( path );
+}
+
+void
+VKoPainter::resetClipPath()
+{
+ art_svp_free( m_clipPaths.current() );
+ m_clipPaths.remove();
+}
+
+void
+VKoPainter::setPen( const VStroke &stroke )
+{
+ delete m_stroke;
+ m_stroke = new VStroke;
+ *m_stroke = stroke;
+}
+
+void
+VKoPainter::setPen( const QColor &c )
+{
+ delete m_stroke;
+ m_stroke = new VStroke;
+
+ float r = static_cast<float>( c.red() ) / 255.0;
+ float g = static_cast<float>( c.green() ) / 255.0;
+ float b = static_cast<float>( c.blue() ) / 255.0;
+
+ VColor color;
+ color.set( r, g, b );
+ m_stroke->setColor( color );
+}
+
+void
+VKoPainter::setPen( Qt::PenStyle style )
+{
+ if( style == Qt::NoPen )
+ {
+ delete m_stroke;
+ m_stroke = 0L;
+ }
+}
+
+void
+VKoPainter::setBrush( const QColor &c )
+{
+ delete m_fill;
+ m_fill = new VFill;
+
+ float r = static_cast<float>( c.red() ) / 255.0;
+ float g = static_cast<float>( c.green() ) / 255.0;
+ float b = static_cast<float>( c.blue() ) / 255.0;
+
+ VColor color;
+ color.set( r, g, b );
+ m_fill->setColor( color );
+}
+
+void
+VKoPainter::setBrush( Qt::BrushStyle style )
+{
+ if( style == Qt::NoBrush )
+ {
+ delete m_fill;
+ m_fill = 0L;
+ }
+}
+
+void
+VKoPainter::setBrush( const VFill &fill )
+{
+ delete m_fill;
+ m_fill = new VFill;
+ *m_fill = fill;
+}
+
+void
+VKoPainter::save()
+{
+}
+
+void
+VKoPainter::restore()
+{
+}
+
+void
+VKoPainter::setRasterOp( Qt::RasterOp )
+{
+}
+
+void
+VKoPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 )
+{
+ // clamp to viewport
+ x0 = kMax( x0, 0 );
+ x0 = kMin( x0, int( m_width ) );
+ y0 = kMax( y0, 0 );
+ y0 = kMin( y0, int ( m_height ) );
+ x1 = kMax( x1, 0 );
+ x1 = kMin( x1, int( m_width ) );
+ y1 = kMax( y1, 0 );
+ y1 = kMin( y1, int( m_height ) );
+}
+
+void
+VKoPainter::clampToViewport( const ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 )
+{
+ // get SVP bbox
+ ArtDRect bbox;
+ art_drect_svp( &bbox, &svp );
+ // Remove comments if we really decide for SVP bbox usage
+ //m_bbox = KoRect( bbox.x0, bbox.y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0 );
+
+ // clamp to viewport
+ x0 = int( bbox.x0 );
+ x0 = kMax( x0, 0 );
+ x0 = kMin( x0, int( m_width ) );
+ y0 = int( bbox.y0 );
+ y0 = kMax( y0, 0 );
+ y0 = kMin( y0, int ( m_height ) );
+ x1 = int( bbox.x1 ) + 1;
+ x1 = kMax( x1, 0 );
+ x1 = kMin( x1, int( m_width ) );
+ y1 = int( bbox.y1 ) + 1;
+ y1 = kMax( y1, 0 );
+ y1 = kMin( y1, int( m_height ) );
+}
+
+void
+VKoPainter::drawVPath( ArtVpath *vec )
+{
+ ArtSVP *strokeSvp = 0L;
+ ArtSVP *fillSvp = 0L;
+
+ // set up world matrix
+ double affine[6];
+ affine[0] = m_matrix.m11();
+ affine[1] = 0;//m_matrix.m12();
+ affine[2] = 0;//m_matrix.m21();
+ affine[3] = m_matrix.m22();
+ affine[4] = m_matrix.dx();
+ affine[5] = m_matrix.dy();
+ ArtVpath *temp = art_vpath_affine_transform( vec, affine );
+ art_free( vec );
+ vec = temp;
+
+ int af = 0;
+ int as = 0;
+ art_u32 fillColor = 0;
+
+ // filling
+ QColor color;
+ if( m_fill && m_fill->type() != VFill::none )
+ {
+ color = m_fill->color();
+ af = qRound( 255 * m_fill->color().opacity() );
+ fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
+
+ ArtSvpWriter *swr;
+ ArtSVP *temp;
+ temp = art_svp_from_vpath( vec );
+
+ if( m_fillRule == evenOdd )
+ swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
+ else
+ swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
+
+ art_svp_intersector( temp, swr );
+ fillSvp = art_svp_writer_rewind_reap( swr );
+
+ art_svp_free( temp );
+ }
+
+ art_u32 strokeColor = 0;
+ // stroke
+ if( m_stroke && m_stroke->type() != VStroke::none )
+ {
+ ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
+ ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
+ // TODO : non rgb support ?
+
+ color = m_stroke->color();
+ as = qRound( 255 * m_stroke->color().opacity() );
+ strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
+
+ double ratio = m_zoomFactor;//sqrt(pow(affine[0], 2) + pow(affine[3], 2)) / sqrt(2);
+ if( m_stroke->dashPattern().array().count() > 0 )
+ {
+ // there are dashes to be rendered
+ ArtVpathDash dash;
+ dash.offset = m_stroke->dashPattern().offset() * ratio;
+ dash.n_dash = m_stroke->dashPattern().array().count();
+ double *dashes = new double[ dash.n_dash ];
+ for( int i = 0; i < dash.n_dash; i++ )
+ dashes[i] = m_stroke->dashPattern().array()[i] * ratio;
+
+ dash.dash = dashes;
+ // get the dashed VPath and use that for the stroke render operation
+ ArtVpath *vec2 = art_vpath_dash( vec, &dash );
+ art_free( vec );
+
+ vec = vec2;
+ delete [] dashes;
+ }
+ // caps translation karbon -> art
+ if( m_stroke->lineCap() == VStroke::capRound )
+ capStyle = ART_PATH_STROKE_CAP_ROUND;
+ else if( m_stroke->lineCap() == VStroke::capSquare )
+ capStyle = ART_PATH_STROKE_CAP_SQUARE;
+
+ // join translation karbon -> art
+ if( m_stroke->lineJoin() == VStroke::joinRound )
+ joinStyle = ART_PATH_STROKE_JOIN_ROUND;
+ else if( m_stroke->lineJoin() == VStroke::joinBevel )
+ joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
+
+ // zoom stroke width;
+ strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * m_stroke->lineWidth(), m_stroke->miterLimit(), 0.25 );
+ }
+
+ int x0, y0, x1, y1;
+
+ // render the svp to the buffer
+ if( strokeSvp )
+ {
+ if( m_stroke && m_stroke->type() == VStroke::grad )
+ applyGradient( strokeSvp, false );
+ else if( m_stroke && m_stroke->type() == VStroke::patt )
+ applyPattern( strokeSvp, false );
+ else
+ {
+ clampToViewport( *strokeSvp, x0, y0, x1, y1 );
+ if( x0 != x1 && y0 != y1 )
+ art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
+ }
+ art_svp_free( strokeSvp );
+ }
+
+ if( fillSvp )
+ {
+ if( m_fill && m_fill->type() == VFill::grad )
+ applyGradient( fillSvp, true );
+ else if( m_fill && m_fill->type() == VFill::patt )
+ applyPattern( fillSvp, true );
+ else
+ {
+ clampToViewport( *fillSvp, x0, y0, x1, y1 );
+ if( x0 != x1 && y0 != y1 )
+ art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
+ }
+ art_svp_free( fillSvp );
+ }
+
+ //delete m_stroke;
+ //m_stroke = 0L;
+ //delete m_fill;
+ //m_fill = 0L;
+
+ art_free( vec );
+}
+
+void
+VKoPainter::applyPattern( ArtSVP *svp, bool fill )
+{
+ if(!svp) {
+ return;
+ }
+
+ int x0, y0, x1, y1;
+ clampToViewport( *svp, x0, y0, x1, y1 );
+
+ ArtRender *render = 0L;
+
+ VPattern pat = fill ? m_fill->pattern() : m_stroke->pattern();
+ if( !pat.isValid() ) {
+ pat.load( KGlobal::iconLoader()->iconPath( "karbon.png", -KIcon::SizeMedium ) ); }
+ if( !pat.isValid() ) {
+ pat = *(dynamic_cast<VPattern *>(KarbonFactory::rServer()->patterns().getFirst() )) ;}
+
+ ArtPattern *pattern = art_new( ArtPattern, 1 );
+
+ double dx = ( pat.vector().x() - pat.origin().x() ) * m_zoomFactor;
+ double dy = ( pat.vector().y() - pat.origin().y() ) * m_zoomFactor;
+
+ pattern->twidth = pat.tileWidth();
+ pattern->theight = pat.tileHeight();
+ pattern->buffer = pat.pixels();
+ pattern->opacity = fill ? short( m_fill->color().opacity() * 255.0 ) : short( m_stroke->color().opacity() * 255.0 );
+ pattern->angle = atan2( -dy, dx );
+
+ if( x0 != x1 && y0 != y1 )
+ {
+ render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * int(x0) + m_width * 4 * int(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
+ art_render_svp( render, svp );
+ art_render_pattern( render, pattern, ART_FILTER_HYPER );
+ }
+
+ if( render )
+ art_render_invoke( render );
+ art_free( pattern );
+}
+
+void
+VKoPainter::applyGradient( ArtSVP *svp, bool fill )
+{
+ int x0, y0, x1, y1;
+ clampToViewport( *svp, x0, y0, x1, y1 );
+
+ ArtRender *render = 0L;
+
+ VGradient gradient = fill ? m_fill->gradient() : m_stroke->gradient();
+ float opa = fill ? m_fill->color().opacity() : m_stroke->color().opacity();
+
+ if( gradient.type() == VGradient::linear )
+ {
+ ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 );
+
+ // TODO : make variable
+ if( gradient.repeatMethod() == VGradient::none )
+ linear->spread = ART_GRADIENT_PAD;
+ else if( gradient.repeatMethod() == VGradient::repeat )
+ linear->spread = ART_GRADIENT_REPEAT;
+ else if( gradient.repeatMethod() == VGradient::reflect )
+ linear->spread = ART_GRADIENT_REFLECT;
+
+ double _x1 = gradient.origin().x();
+ double _x2 = gradient.vector().x();
+ double _y2 = gradient.origin().y();
+ double _y1 = gradient.vector().y();
+
+ double dx = ( _x2 - _x1 ) * m_zoomFactor;
+ _y1 = m_matrix.m22() * _y1 + m_matrix.dy() / m_zoomFactor;
+ _y2 = m_matrix.m22() * _y2 + m_matrix.dy() / m_zoomFactor;
+ double dy = ( _y1 - _y2 ) * m_zoomFactor;
+ double scale = 1.0 / ( dx * dx + dy * dy );
+
+ linear->a = dx * scale;
+ linear->b = dy * scale;
+ linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a +
+ ( _y2 * m_zoomFactor ) * linear->b );
+
+ // get stop array
+ int offsets = -1;
+ linear->stops = buildStopArray( gradient, offsets );
+ linear->n_stops = offsets;
+
+ if( x0 != x1 && y0 != y1 && offsets >= 0 )
+ {
+ render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * int(x0) + m_width * 4 * int(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
+ int opacity = int( opa * 255.0 );
+ art_render_svp( render, svp );
+ art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
+ art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST );
+ art_render_invoke( render );
+ }
+ art_free( linear->stops );
+ art_free( linear );
+ }
+ else if( gradient.type() == VGradient::radial )
+ {
+ ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 );
+
+ // TODO : make variable
+ if( gradient.repeatMethod() == VGradient::none )
+ radial->spread = ART_GRADIENT_PAD;
+ else if( gradient.repeatMethod() == VGradient::repeat )
+ radial->spread = ART_GRADIENT_REPEAT;
+ else if( gradient.repeatMethod() == VGradient::reflect )
+ radial->spread = ART_GRADIENT_REFLECT;
+
+ radial->affine[0] = m_matrix.m11();
+ radial->affine[1] = m_matrix.m12();
+ radial->affine[2] = m_matrix.m21();
+ radial->affine[3] = m_matrix.m22();
+ radial->affine[4] = m_matrix.dx();
+ radial->affine[5] = m_matrix.dy();
+
+ double cx = gradient.origin().x() * m_zoomFactor;
+ double cy = gradient.origin().y() * m_zoomFactor;
+ double fx = gradient.focalPoint().x() * m_zoomFactor;
+ double fy = gradient.focalPoint().y() * m_zoomFactor;
+ double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) +
+ pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
+ r *= m_zoomFactor;
+
+ radial->fx = (fx - cx) / r;
+ radial->fy = (fy - cy) / r;
+
+ double aff1[6], aff2[6];
+ art_affine_scale( aff1, r, r);
+ art_affine_translate( aff2, cx, cy );
+ art_affine_multiply( aff1, aff1, aff2 );
+ art_affine_multiply( aff1, aff1, radial->affine );
+ art_affine_invert( radial->affine, aff1 );
+
+ // get stop array
+ int offsets = -1;
+ radial->stops = buildStopArray( gradient, offsets );
+ radial->n_stops = offsets;
+
+ if( x0 != x1 && y0 != y1 && offsets >= 0 )
+ {
+ render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * x0 + m_width * 4 * y0, m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
+ int opacity = int( opa * 255.0 );
+ art_render_svp( render, svp );
+ art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
+ art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST );
+ art_render_invoke( render );
+ }
+ art_free( radial->stops );
+ art_free( radial );
+ }
+ else if( gradient.type() == VGradient::conic )
+ {
+ ArtGradientConical *conical = art_new( ArtGradientConical, 1 );
+
+ // TODO : make variable
+ if( gradient.repeatMethod() == VGradient::none )
+ conical->spread = ART_GRADIENT_PAD;
+ else if( gradient.repeatMethod() == VGradient::repeat )
+ conical->spread = ART_GRADIENT_REPEAT;
+ else if( gradient.repeatMethod() == VGradient::reflect )
+ conical->spread = ART_GRADIENT_REFLECT;
+
+ double cx = gradient.origin().x() * m_zoomFactor;
+ cx = m_matrix.m11() * cx + m_matrix.dx();
+ double cy = gradient.origin().y() * m_zoomFactor;
+ cy = m_matrix.m22() * cy + m_matrix.dy();
+ double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) +
+ pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
+ r *= m_zoomFactor;
+
+ conical->cx = cx;
+ conical->cy = cy;
+ conical->r = r;
+
+ // get stop array
+ int offsets = -1;
+ conical->stops = buildStopArray( gradient, offsets );
+ conical->n_stops = offsets;
+
+ if( x0 != x1 && y0 != y1 && offsets >= 0 )
+ {
+ render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * x0 + m_width * 4 * y0, m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 );
+ int opacity = int( opa * 255.0 );
+ art_render_svp( render, svp );
+ art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
+ art_karbon_render_gradient_conical( render, conical, ART_FILTER_NEAREST );
+ art_render_invoke( render );
+ }
+ art_free( conical->stops );
+ art_free( conical );
+ }
+}
+
+ArtGradientStop *
+VKoPainter::buildStopArray( VGradient &gradient, int &offsets )
+{
+ // TODO : make this generic
+ QPtrVector<VColorStop> colorStops = gradient.colorStops();
+ offsets = colorStops.count();
+
+ ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 );
+
+ for( int offset = 0 ; offset < offsets ; offset++ )
+ {
+ double ramp = colorStops[ offset ]->rampPoint;
+ //double mid = colorStops[ offset ]->midPoint;
+ stopArray[ offset * 2 ].offset = ramp;
+
+ QColor qStopColor = colorStops[ offset ]->color;
+ int r = qRed( qStopColor.rgb() );
+ int g = qGreen( qStopColor.rgb() );
+ int b = qBlue( qStopColor.rgb() );
+ art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb());
+ /* convert from separated to premultiplied alpha */
+ int a = int( colorStops[ offset]->color.opacity() * 255.0 );
+ r = (rgba >> 24) * a + 0x80;
+ r = (r + (r >> 8)) >> 8;
+ g = ((rgba >> 16) & 0xff) * a + 0x80;
+ g = (g + (g >> 8)) >> 8;
+ b = ((rgba >> 8) & 0xff) * a + 0x80;
+ b = (b + (b >> 8)) >> 8;
+ stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
+ stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
+ stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
+ stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
+
+ if( offset + 1 != offsets )
+ {
+ stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint;
+
+ QColor qStopColor2 = colorStops[ offset + 1 ]->color;
+ rgba = int(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 |
+ int(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 |
+ int(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 |
+ qAlpha(qStopColor2.rgb());
+ /* convert from separated to premultiplied alpha */
+ int a = int( colorStops[ offset]->color.opacity() * 255.0 );
+ r = (rgba >> 24) * a + 0x80;
+ r = (r + (r >> 8)) >> 8;
+ g = ((rgba >> 16) & 0xff) * a + 0x80;
+ g = (g + (g >> 8)) >> 8;
+ b = ((rgba >> 8) & 0xff) * a + 0x80;
+ b = (b + (b >> 8)) >> 8;
+ stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
+ stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
+ stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
+ stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
+ }
+ }
+
+ offsets = offsets * 2 - 1;
+ return stopArray;
+}
+
+void
+VKoPainter::drawNode( const KoPoint& p, int width )
+{
+ if( !m_bDrawNodes ) return;
+
+ KoPoint _p( m_matrix.map( QPoint( int( p.x() * m_zoomFactor ), int( p.y() * m_zoomFactor ) ) ) );
+ int x1 = int( _p.x() - width );
+ int x2 = int( _p.x() + width );
+ int y1 = int( _p.y() - width );
+ int y2 = int( _p.y() + width );
+
+ clampToViewport( x1, y1, x2, y2 );
+
+ int baseindex = 4 * x1 + ( m_width * 4 * y1 );
+
+ QColor color = m_fill->color();
+ for( int i = 0; i < y2 - y1; i++ )
+ {
+ for( int j = 0; j < x2 - x1; j++ )
+ {
+ m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) ] = color.red();
+ m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 1 ] = color.green();
+ m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 2 ] = color.blue();
+ m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 3 ] = 0xFF;
+ }
+ }
+}
+
+void
+VKoPainter::drawImage( const QImage &image, const QWMatrix &affine )
+{
+ // set up world matrix
+ double affineresult[6];
+
+ affineresult[0] = affine.m11() * m_matrix.m11() * m_zoomFactor + affine.m12() * m_matrix.m21();
+ affineresult[1] = (affine.m11() * m_matrix.m12() + affine.m12() * m_matrix.m22() ) * m_zoomFactor;
+ affineresult[2] = (affine.m21() * m_matrix.m11() + affine.m22() * m_matrix.m21() ) * m_zoomFactor;
+ affineresult[3] = affine.m22() * m_matrix.m22() * m_zoomFactor + affine.m21() * m_matrix.m12();
+ affineresult[4] = m_matrix.dx() + affine.dx() * m_zoomFactor;
+ affineresult[5] = m_matrix.dy() - affine.dy() * m_zoomFactor;
+
+ //art_affine_scale( affineresult, m_zoomFactor, m_zoomFactor);
+ /*kdDebug(38000) << "affineresult[0] : " << affineresult[0] << endl;
+ kdDebug(38000) << "affineresult[1] : " << affineresult[1] << endl;
+ kdDebug(38000) << "affineresult[2] : " << affineresult[2] << endl;
+ kdDebug(38000) << "affineresult[3] : " << affineresult[3] << endl;
+ kdDebug(38000) << "affineresult[4] : " << affineresult[4] << endl;
+ kdDebug(38000) << "affineresult[5] : " << affineresult[5] << endl;
+ kdDebug(38000) << "m_matrix.dx() : " << m_matrix.dx() << endl;
+ kdDebug(38000) << "affine.dx() : " << affine.dx() << endl;
+ kdDebug(38000) << "image.height() : " << image.height() << endl;*/
+ art_rgba_affine( m_buffer, 0, 0, m_width, m_height, m_width * 4,
+ image.bits(), image.width(), image.height(), image.width() * 4,
+ affineresult, ART_FILTER_NEAREST, 0L );
+}
+
+void
+VKoPainter::drawRect( const KoRect &r )
+{
+ newPath();
+ moveTo( r.topLeft() );
+ lineTo( r.topRight() );
+ lineTo( r.bottomRight() );
+ lineTo( r.bottomLeft() );
+ lineTo( r.topLeft() );
+ fillPath();
+ strokePath();
+}
+
+void
+VKoPainter::drawRect( double x, double y, double w, double h )
+{
+ drawRect( KoRect( x, y, w, h ) );
+}
+
diff --git a/karbon/render/vkopainter.h b/karbon/render/vkopainter.h
new file mode 100644
index 00000000..48336092
--- /dev/null
+++ b/karbon/render/vkopainter.h
@@ -0,0 +1,124 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VKOPAINTER_H__
+#define __VKOPAINTER_H__
+
+// kopainter/libart wrapper
+
+#include "vpainter.h"
+#include <qwmatrix.h>
+#include <qptrlist.h>
+#include <koffice_export.h>
+class QPainter;
+struct _ArtVpath;
+struct _ArtBpath;
+struct _ArtSVP;
+struct _ArtGradientStop;
+class VGradient;
+class VPattern;
+class KoRect;
+
+class KARBONBASE_EXPORT VKoPainter : public VPainter
+{
+public:
+ VKoPainter( QPaintDevice *target, unsigned int w = 0, unsigned int h = 0, bool = true );
+ VKoPainter( unsigned char *buffer, unsigned int w = 0, unsigned int h = 0, bool = true );
+ virtual ~VKoPainter();
+
+ virtual void resize( unsigned int w, unsigned int h );
+ virtual void begin();
+ virtual void end();
+ virtual void blit( const KoRect & );
+ void clear();
+ virtual void clear( const QColor & );
+ virtual void clear( const KoRect &, const QColor & );
+
+ // matrix manipulation
+ virtual void setWorldMatrix( const QWMatrix & );
+ virtual const QWMatrix worldMatrix() { return m_matrix; }
+ virtual void setZoomFactor( double );
+ virtual double zoomFactor() { return m_zoomFactor; }
+
+ // drawing
+ virtual void moveTo( const KoPoint & );
+ virtual void lineTo( const KoPoint & );
+ virtual void curveTo( const KoPoint &, const KoPoint &, const KoPoint & );
+ virtual void newPath();
+ virtual void fillPath();
+ virtual void setFillRule( VFillRule );
+ virtual void strokePath();
+ virtual void setClipPath();
+ virtual void resetClipPath();
+
+ // helper
+ virtual void drawNode( const KoPoint& p, int width );
+ virtual void drawRect( const KoRect & );
+ virtual void drawRect( double, double, double, double );
+
+ // pen + brush
+ virtual void setPen( const VStroke & );
+ virtual void setPen( const QColor & );
+ virtual void setPen( Qt::PenStyle style );
+ virtual void setBrush( const VFill & );
+ virtual void setBrush( const QColor & );
+ virtual void setBrush( Qt::BrushStyle style );
+
+ virtual void drawImage( const QImage &, const QWMatrix & );
+
+ // stack management
+ virtual void save();
+ virtual void restore();
+
+ //
+ virtual void setRasterOp( Qt::RasterOp );
+
+ virtual QPaintDevice *device() { return m_target; }
+ unsigned char *buffer() { return m_buffer; }
+
+private:
+ void drawVPath( struct _ArtVpath * );
+ void applyGradient( _ArtSVP *, bool );
+ void applyPattern( _ArtSVP *, bool );
+ _ArtGradientStop *buildStopArray( VGradient &gradient, int & );
+ void clampToViewport( const _ArtSVP &, int &, int &, int &, int & );
+ void clampToViewport( int &, int &, int &, int & );
+ void ensureSpace( unsigned int );
+
+private:
+ struct _ArtBpath *m_path;
+ unsigned int m_index;
+ unsigned int m_alloccount;
+ unsigned char *m_buffer;
+ QPaintDevice *m_target;
+ unsigned int m_width;
+ unsigned int m_height;
+ QWMatrix m_matrix;
+ VStroke *m_stroke;
+ VFill *m_fill;
+ VFillRule m_fillRule;
+ double m_zoomFactor;
+ QPtrList<_ArtSVP> m_clipPaths;
+
+ bool m_bDrawNodes;
+
+ GC gc;
+};
+
+#endif
diff --git a/karbon/render/vpainter.h b/karbon/render/vpainter.h
new file mode 100644
index 00000000..b638ddcc
--- /dev/null
+++ b/karbon/render/vpainter.h
@@ -0,0 +1,102 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, The Karbon Developers
+ Copyright (C) 2002, The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef __VPAINTER_H__
+#define __VPAINTER_H__
+
+// painter abstraction
+
+#include <qnamespace.h>
+#include <KoRect.h>
+#include <vfillrule.h>
+
+class QWMatrix;
+class QPaintDevice;
+class QColor;
+class QPen;
+class QBrush;
+class QImage;
+
+class VStroke;
+class VFill;
+
+class KoPoint;
+class KoRect;
+
+class VPainter
+{
+public:
+ VPainter( QPaintDevice *, unsigned int /*w*/ = 0, unsigned int /*h*/ = 0 ) {};
+ virtual ~VPainter() {};
+
+ //
+ virtual void resize( unsigned int w, unsigned int h ) = 0;
+ virtual void begin() = 0;
+ virtual void end() = 0;
+ virtual void blit( const KoRect & ) = 0;
+ virtual void clear( const QColor & ) = 0;
+ virtual void clear( const KoRect &, const QColor & ) = 0;
+
+ // matrix manipulation
+ virtual void setWorldMatrix( const QWMatrix & ) = 0;
+ virtual const QWMatrix worldMatrix() = 0;
+ virtual void setZoomFactor( double ) = 0;
+ virtual double zoomFactor() { return 1.0; }
+
+ // drawing
+ virtual void moveTo( const KoPoint & ) = 0;
+ virtual void lineTo( const KoPoint & ) = 0;
+ virtual void curveTo( const KoPoint &, const KoPoint &, const KoPoint & ) = 0;
+ virtual void newPath() = 0;
+ virtual void strokePath() = 0;
+ virtual void fillPath() = 0;
+ virtual void setFillRule( VFillRule ) = 0;
+ virtual void setClipPath() = 0;
+ virtual void resetClipPath() = 0;
+
+ // helper
+ virtual void drawNode( const KoPoint& , int ) {}
+ virtual void drawRect( const KoRect & ) {}
+ virtual void drawRect( double, double, double, double ) {}
+
+ // pen + brush
+ virtual void setPen( const VStroke & ) = 0;
+ // compatibility, use VPen/VBrush later ?
+ virtual void setPen( const QColor & ) = 0;
+ virtual void setPen( Qt::PenStyle style ) = 0;
+ virtual void setBrush( const VFill & ) = 0;
+ virtual void setBrush( const QColor & ) = 0;
+ virtual void setBrush( Qt::BrushStyle style ) = 0;
+
+ virtual void drawImage( const QImage &, const QWMatrix & ) {}
+
+ // stack management
+ virtual void save() = 0;
+ virtual void restore() = 0;
+
+ // we have to see how this fits in
+ virtual void setRasterOp( Qt::RasterOp ) = 0;
+
+ // access to device
+ virtual QPaintDevice *device() = 0;
+};
+
+#endif
diff --git a/karbon/render/vpainterfactory.cc b/karbon/render/vpainterfactory.cc
new file mode 100644
index 00000000..a4d52c62
--- /dev/null
+++ b/karbon/render/vpainterfactory.cc
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, The Karbon Developers
+ Copyright (C) 2002, The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+// painter factory
+
+#include "vpainterfactory.h"
+#include "vkopainter.h"
+#include "vqpainter.h"
+
+VPainterFactory::VPainterFactory()
+{
+ m_painter = 0L;
+ m_editpainter = 0L;
+}
+
+VPainterFactory::~VPainterFactory()
+{
+ delete m_painter;
+ delete m_editpainter;
+}
+
+VPainter *
+VPainterFactory::painter()
+{
+ return m_painter;
+}
+
+void
+VPainterFactory::setPainter( QPaintDevice *target, int w, int h )
+{
+ if( m_painter )
+ delete m_painter;
+ m_painter = new VKoPainter( target, w, h );
+}
+
+VPainter *
+VPainterFactory::editpainter()
+{
+ return m_editpainter;
+}
+
+void
+VPainterFactory::setEditPainter( QPaintDevice *target, int w, int h )
+{
+ if( m_editpainter )
+ delete m_editpainter;
+ m_editpainter = new VQPainter( target, w, h );
+}
+
+void
+VPainterFactory::setWireframePainter( QPaintDevice *target, int w, int h )
+{
+ if( m_painter )
+ delete m_painter;
+ m_painter = new VQPainter( target, w, h );
+}
+
diff --git a/karbon/render/vpainterfactory.h b/karbon/render/vpainterfactory.h
new file mode 100644
index 00000000..df36819d
--- /dev/null
+++ b/karbon/render/vpainterfactory.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, The Karbon Developers
+ Copyright (C) 2002, The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VPAINTERDACTORY_H__
+#define __VPAINTERDACTORY_H__
+
+// painter factory
+#include <koffice_export.h>
+class VPainter;
+class QPaintDevice;
+
+class KARBONBASE_EXPORT VPainterFactory
+{
+public:
+ VPainterFactory();
+ ~VPainterFactory();
+
+ VPainter *painter();
+ void setPainter( QPaintDevice *target, int w = 0, int h = 0 );
+
+ VPainter *editpainter();
+ void setEditPainter( QPaintDevice *target, int w = 0, int h = 0 );
+
+ void setWireframePainter( QPaintDevice *target, int w = 0, int h = 0 );
+
+private:
+ VPainter *m_painter;
+ VPainter *m_editpainter;
+};
+
+#endif
diff --git a/karbon/render/vqpainter.cc b/karbon/render/vqpainter.cc
new file mode 100644
index 00000000..31e5593e
--- /dev/null
+++ b/karbon/render/vqpainter.cc
@@ -0,0 +1,284 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, The Karbon Developers
+ Copyright (C) 2002, The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+// qpainter wrapper
+
+#include "vqpainter.h"
+#include "vstroke.h"
+#include "vcolor.h"
+#include "vfill.h"
+
+#include <qpainter.h>
+#include <qpaintdevice.h>
+#include <qpen.h>
+
+#include <KoPoint.h>
+#include <kdebug.h>
+
+VQPainter::VQPainter( QPaintDevice *target, unsigned int w, unsigned int h ) : VPainter( target, w, h ), m_painter( 0L ), m_target( target ), m_width( w ), m_height( h )
+{
+ m_zoomFactor = 1;
+ m_index = 0;
+ m_painter = new QPainter( target );
+}
+
+VQPainter::~VQPainter()
+{
+ delete m_painter;
+}
+
+void
+VQPainter::resize( unsigned int w, unsigned int h )
+{
+ m_width = w;
+ m_height = h;
+}
+
+void
+VQPainter::blit( const KoRect & )
+{
+ end();
+}
+
+void
+VQPainter::clear( const QColor &c )
+{
+ m_painter->setBackgroundColor( c );
+ m_painter->eraseRect( 0, 0, m_width, m_height );
+}
+
+void
+VQPainter::begin()
+{
+ if( !m_painter->isActive() )
+ {
+ m_painter->begin( m_target );
+ m_painter->eraseRect( 0, 0, m_width, m_height );
+ }
+}
+
+void
+VQPainter::end()
+{
+ m_painter->end();
+}
+
+const QWMatrix
+VQPainter::worldMatrix()
+{
+ return m_painter->worldMatrix();
+}
+
+void
+VQPainter::setWorldMatrix( const QWMatrix& mat )
+{
+ m_painter->setWorldMatrix( mat );
+}
+
+void
+VQPainter::setZoomFactor( double zoomFactor )
+{
+ m_zoomFactor = zoomFactor;
+ /*QWMatrix mat;
+ mat.scale( zoomFactor, zoomFactor );
+ m_painter->setWorldMatrix( mat );*/
+}
+
+void
+VQPainter::moveTo( const KoPoint &p )
+{
+ //m_index = 0;
+ if( m_pa.size() <= m_index )
+ m_pa.resize( m_index + 10 );
+
+ m_pa.setPoint( m_index, static_cast<int>(p.x() * m_zoomFactor), static_cast<int>(p.y() * m_zoomFactor) );
+
+ m_index++;
+}
+
+void
+VQPainter::lineTo( const KoPoint &p )
+{
+ if( m_pa.size() <= m_index )
+ m_pa.resize( m_index + 10 );
+
+ m_pa.setPoint( m_index, static_cast<int>(p.x() * m_zoomFactor), static_cast<int>(p.y() * m_zoomFactor) );
+
+ m_index++;
+}
+
+void
+VQPainter::curveTo( const KoPoint &p1, const KoPoint &p2, const KoPoint &p3 )
+{
+ // calculate cubic bezier using a temp QPointArray
+ QPointArray pa( 4 );
+ pa.setPoint( 0, m_pa.point( m_index - 1 ).x(), m_pa.point( m_index - 1 ).y() );
+ pa.setPoint( 1, static_cast<int>(p1.x() * m_zoomFactor), static_cast<int>(p1.y() * m_zoomFactor) );
+ pa.setPoint( 2, static_cast<int>(p2.x() * m_zoomFactor), static_cast<int>(p2.y() * m_zoomFactor) );
+ pa.setPoint( 3, static_cast<int>(p3.x() * m_zoomFactor), static_cast<int>(p3.y() * m_zoomFactor) );
+
+ QPointArray pa2( pa.cubicBezier() );
+
+ m_pa.resize( m_index + pa2.size() );
+ m_pa.putPoints( m_index, pa2.size(), pa2 );
+
+ m_index += pa2.size();
+}
+
+void
+VQPainter::newPath()
+{
+ m_index = 0;
+}
+
+void
+VQPainter::fillPath()
+{
+ // we probably dont need filling for qpainter
+ //m_index = 0;
+ m_painter->drawPolygon( m_pa, FALSE, 0, m_index );
+}
+
+void
+VQPainter::strokePath()
+{
+ m_painter->drawPolyline( m_pa, 0, m_index );
+ m_index = 0;
+}
+
+void
+VQPainter::setPen( const VStroke &stroke )
+{
+ QPen pen;
+
+ // color + linewidth
+ pen.setColor( stroke.color() );
+ pen.setWidth( static_cast<int>(stroke.lineWidth()) );
+
+ // caps
+ if( stroke.lineCap() == VStroke::capButt )
+ pen.setCapStyle( Qt::FlatCap );
+ else if( stroke.lineCap() == VStroke::capRound )
+ pen.setCapStyle( Qt::RoundCap );
+ else if( stroke.lineCap() == VStroke::capSquare )
+ pen.setCapStyle( Qt::SquareCap );
+
+ m_painter->setPen( pen );
+}
+
+void
+VQPainter::setBrush( const VFill &fill )
+{
+ switch( fill.type() )
+ {
+ case VFill::none:
+ m_painter->setBrush( Qt::NoBrush );
+ break;
+ case VFill::solid:
+ m_painter->setBrush( QBrush( fill.color(), Qt::SolidPattern ) );
+ break;
+ case VFill::grad:
+ // gradients are nor supported by qpainter
+ m_painter->setBrush( Qt::NoBrush );
+ break;
+ case VFill::patt:
+ // pixmap brushes not supported for printing
+ m_painter->setBrush( QBrush( fill.color(), fill.pattern().pixmap() ) );
+ break;
+ default:
+ break;
+ }
+}
+
+void
+VQPainter::setPen( const QColor &c )
+{
+ m_painter->setPen( c );
+}
+
+void
+VQPainter::setPen( Qt::PenStyle style )
+{
+ m_painter->setPen( style );
+}
+
+void
+VQPainter::setBrush( const QColor &c )
+{
+ m_painter->setBrush( c );
+}
+
+void
+VQPainter::setBrush( Qt::BrushStyle style )
+{
+ m_painter->setBrush( style );
+}
+
+void
+VQPainter::save()
+{
+ m_painter->save();
+}
+
+void
+VQPainter::restore()
+{
+ m_painter->restore();
+}
+
+void
+VQPainter::setRasterOp( Qt::RasterOp r )
+{
+ m_painter->setRasterOp( r );
+}
+
+void
+VQPainter::drawNode( const KoPoint &p, int width )
+{
+ m_painter->drawRect( QRect( int( p.x() * m_zoomFactor ) - width, int( p.y() * m_zoomFactor ) - width,
+ 2 * width + 1, 2 * width + 1 ) );
+}
+
+void
+VQPainter::drawRect( const KoRect &rect )
+{
+ m_painter->drawRect( QRect( int( rect.x() ), int( rect.y() ), int( rect.width() ), int( rect.height() ) ) );
+}
+
+void
+VQPainter::drawImage( const QImage &image, const QWMatrix &affine )
+{
+ QWMatrix matrix = m_painter->worldMatrix();
+
+ double m11 = affine.m11() * matrix.m11() * m_zoomFactor + affine.m12() * matrix.m21();
+ double m12 = (affine.m11() * matrix.m12() + affine.m12() * matrix.m22() ) * m_zoomFactor;
+ double m21 = (affine.m21() * matrix.m11() + affine.m22() * matrix.m21() ) * m_zoomFactor;
+ double m22 = affine.m22() * matrix.m22() * m_zoomFactor + affine.m21() * matrix.m12();
+ double dx = matrix.dx() + affine.dx() * m_zoomFactor;
+ double dy = matrix.dy() - affine.dy() * m_zoomFactor;
+
+ QWMatrix world( m11, m12, m21, m22, dx, dy );
+
+ m_painter->setWorldMatrix( world );
+
+ m_painter->drawImage( QPoint( 0, 0 ), image );
+ // restore old world matrix
+ m_painter->setWorldMatrix( matrix );
+}
diff --git a/karbon/render/vqpainter.h b/karbon/render/vqpainter.h
new file mode 100644
index 00000000..7f4f501b
--- /dev/null
+++ b/karbon/render/vqpainter.h
@@ -0,0 +1,95 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, The Karbon Developers
+ Copyright (C) 2002, The Karbon Developers
+
+ 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; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VQPAINTER_H__
+#define __VQPAINTER_H__
+
+// qpainter wrapper
+
+#include "vpainter.h"
+#include "qpointarray.h"
+
+class QPainter;
+
+class VQPainter : public VPainter
+{
+public:
+ VQPainter( QPaintDevice *target, unsigned int w = 0, unsigned int h = 0 );
+ virtual ~VQPainter();
+
+ //
+ virtual void resize( unsigned int w, unsigned int h );
+ virtual void begin();
+ virtual void end();
+ virtual void blit( const KoRect & );
+ virtual void clear( const QColor & );
+ virtual void clear( const KoRect &, const QColor & ) {}
+
+ // matrix manipulation
+ virtual void setWorldMatrix( const QWMatrix & );
+ virtual const QWMatrix worldMatrix();
+ virtual void setZoomFactor( double );
+ virtual double zoomFactor() { return m_zoomFactor; }
+
+ // drawing
+ virtual void moveTo( const KoPoint & );
+ virtual void lineTo( const KoPoint & );
+ virtual void curveTo( const KoPoint &, const KoPoint &, const KoPoint & );
+ virtual void newPath();
+ virtual void strokePath();
+ virtual void fillPath();
+ virtual void setFillRule( VFillRule ) {}
+ virtual void setClipPath() {}
+ virtual void resetClipPath() {}
+
+ // pen + brush
+ virtual void setPen( const VStroke & );
+ virtual void setPen( const QColor & );
+ virtual void setPen( Qt::PenStyle style );
+ virtual void setBrush( const VFill & );
+ virtual void setBrush( const QColor & );
+ virtual void setBrush( Qt::BrushStyle style );
+
+ virtual void drawImage( const QImage &, const QWMatrix & );
+
+ // stack management
+ virtual void save();
+ virtual void restore();
+
+ // helper
+ virtual void drawNode( const KoPoint& , int );
+ virtual void drawRect( const KoRect & );
+
+ //
+ virtual void setRasterOp( Qt::RasterOp );
+
+ virtual QPaintDevice *device() { return m_target; }
+
+private:
+ double m_zoomFactor;
+ unsigned int m_index;
+ QPointArray m_pa;
+ QPainter *m_painter;
+ QPaintDevice *m_target;
+ unsigned int m_width;
+ unsigned int m_height;
+};
+
+#endif
diff --git a/karbon/render/xrgbrender/Makefile.am b/karbon/render/xrgbrender/Makefile.am
new file mode 100644
index 00000000..dcfe376a
--- /dev/null
+++ b/karbon/render/xrgbrender/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libkarbonxrgbrender.la
+
+libkarbonxrgbrender_la_SOURCES = gdk-pixbuf-xlib.c gdk-pixbuf-xlib-render.c gdk-pixbuf-xlib-drawable.c gdk-pixbuf-xlibrgb.c
diff --git a/karbon/render/xrgbrender/gdk-pixbuf-xlib-drawable.c b/karbon/render/xrgbrender/gdk-pixbuf-xlib-drawable.c
new file mode 100644
index 00000000..7e955610
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlib-drawable.c
@@ -0,0 +1,1137 @@
+/* -*- 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* Ported to Xlib by John Harper <john@dcs.warwick.ac.uk> */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include "gdk-pixbuf-xlib-private.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#if (KSVG_BYTE_ORDER == KSVG_LITTLE_ENDIAN)
+#define LITTLE
+#endif
+#define d(x)
+
+
+
+static unsigned int 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;
+};
+
+
+/* from gdkvisual.c */
+static void
+visual_decompose_mask (unsigned long mask,
+ int *shift,
+ int *prec)
+{
+ *shift = 0;
+ *prec = 0;
+
+ while (!(mask & 0x1)) {
+ (*shift)++;
+ mask >>= 1;
+ }
+
+ while (mask & 0x1) {
+ (*prec)++;
+ mask >>= 1;
+ }
+}
+
+static int x_error;
+
+static int
+handle_x_error (Display *dpy, XErrorEvent *ev)
+{
+ x_error = 1;
+ return 0;
+}
+
+static int
+drawable_is_pixmap (Drawable d)
+{
+ /* copied from Imlib */
+
+ XErrorHandler errh;
+ XWindowAttributes wa;
+ int is_pixmap;
+
+ errh = XSetErrorHandler (handle_x_error);
+ x_error = 0;
+ 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned char *s;
+ register unsigned char data;
+ unsigned char *o;
+ unsigned char *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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned char *s;
+ register unsigned char data;
+ unsigned char *o;
+ unsigned char *srow = image->data, *orow = pixels;
+ unsigned int 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned int mask;
+ register unsigned int data;
+ unsigned char *srow = image->data, *orow = pixels;
+ register unsigned char *s;
+ register unsigned char *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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned int mask;
+ register unsigned int data;
+ unsigned int remap[256];
+ register unsigned char *s; /* read 2 pixels at once */
+ register unsigned int *o;
+ unsigned char *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 = (unsigned int *) 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned int *s; /* read 2 pixels at once */
+#else
+ register unsigned char *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *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 = (unsigned int *) srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned short *) orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned int 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 unsigned short 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned char *s; /* need to swap data order */
+#else
+ register unsigned int *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *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 = (unsigned int *) srow;
+#endif
+ o = (unsigned short *) orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned int 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 unsigned short 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned int *o;
+
+ unsigned char *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 = (unsigned short *) srow;
+#else
+ s = (unsigned char *) srow;
+#endif
+ o = (unsigned int *) orow;
+ for (xx = 0; xx < width; xx ++) {
+ register unsigned int 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned char *s;
+#else
+ register unsigned short *s; /* read 1 pixels at once */
+#endif
+ register unsigned int *o;
+
+ unsigned char *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 = (unsigned int *) orow;
+ for (xx = 0; xx < width; xx ++) {
+ register unsigned int 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned int *s; /* read 2 pixels at once */
+#else
+ register unsigned char *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *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 = (unsigned int *) srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned short *) orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned int 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 unsigned short 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned char *s; /* read 2 pixels at once */
+#else
+ register unsigned int *s; /* read 2 pixels at once */
+#endif
+ register unsigned short *o;
+ unsigned char *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 = (unsigned short *) orow;
+ for (xx = 1; xx < width; xx += 2) {
+ register unsigned int 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 unsigned short 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned int *o;
+
+ unsigned char *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 = (unsigned short *) srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned int *) orow;
+ for (xx = 0; xx < width; xx++) {
+ register unsigned int 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+#ifdef LITTLE
+ register unsigned short *s; /* read 1 pixels at once */
+#else
+ register unsigned char *s;
+#endif
+ register unsigned int *o;
+
+ unsigned char *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 = (unsigned short *) srow;
+#else
+ s = srow;
+#endif
+ o = (unsigned int *) orow;
+ for (xx = 0; xx < width; xx++) {
+ register unsigned int 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *s; /* for byte order swapping */
+ unsigned char *o;
+ unsigned char *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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *srow = image->data, *orow = pixels;
+ unsigned char *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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *srow = image->data, *orow = pixels;
+#ifdef LITTLE
+ unsigned int *o;
+ unsigned int *s;
+#else
+ unsigned char *s; /* for byte order swapping */
+ unsigned char *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 = (unsigned int *) srow;
+ o = (unsigned int *) 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, unsigned char *pixels, int rowstride, xlib_colormap *colormap)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+
+ unsigned char *srow = image->data, *orow = pixels;
+ unsigned char *s;
+ unsigned char *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, unsigned char *pixels, int rowstride, xlib_colormap *cmap, int alpha)
+{
+ int xx, yy;
+ int width, height;
+ int bpl;
+ unsigned char *srow = image->data, *orow = pixels;
+ unsigned char *s;
+ unsigned char *o;
+ unsigned int pixel;
+ Visual *v;
+ unsigned char 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, unsigned char *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, unsigned char *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 int
+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 0;
+
+ if (!XQueryTree (gdk_pixbuf_dpy, w, &root,
+ &parent, &children, &nchildren))
+ return 0;
+
+ if (nchildren > 0)
+ XFree (children);
+
+ if (parent == root)
+ return 1;
+
+ w = parent;
+ }
+
+ return 0;
+}
+
+static int
+xlib_window_get_origin (Window w, int *x, int *y)
+{
+ Window child;
+ return XTranslateCoordinates (gdk_pixbuf_dpy, w,
+ RootWindow (gdk_pixbuf_dpy,
+ gdk_pixbuf_screen),
+ 0, 0, x, y, &child);
+}
diff --git a/karbon/render/xrgbrender/gdk-pixbuf-xlib-private.h b/karbon/render/xrgbrender/gdk-pixbuf-xlib-private.h
new file mode 100644
index 00000000..0198ec00
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlib-private.h
@@ -0,0 +1,39 @@
+/* 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GDK_PIXBUF_XLIB_PRIVATE_H
+#define GDK_PIXBUF_XLIB_PRIVATE_H
+
+#include <config.h>
+#include "gdk-pixbuf-xlib.h"
+#include <X11/Xlib.h>
+
+extern Display *gdk_pixbuf_dpy;
+extern int gdk_pixbuf_screen;
+
+#define KSVG_LITTLE_ENDIAN 1
+#define KSVG_BIG_ENDIAN 2
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define KSVG_BYTE_ORDER KSVG_BIG_ENDIAN
+#else
+#define KSVG_BYTE_ORDER KSVG_LITTLE_ENDIAN
+#endif
+#endif
diff --git a/karbon/render/xrgbrender/gdk-pixbuf-xlib-render.c b/karbon/render/xrgbrender/gdk-pixbuf-xlib-render.c
new file mode 100644
index 00000000..f2439138
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlib-render.c
@@ -0,0 +1,380 @@
+/* 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, 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);
+}
+
+
+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;
+
+ 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) {
+
+ 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);
+}
+
+ * @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/karbon/render/xrgbrender/gdk-pixbuf-xlib.c b/karbon/render/xrgbrender/gdk-pixbuf-xlib.c
new file mode 100644
index 00000000..ff41ccdf
--- /dev/null
+++ b/karbon/render/xrgbrender/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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, 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/karbon/render/xrgbrender/gdk-pixbuf-xlib.h b/karbon/render/xrgbrender/gdk-pixbuf-xlib.h
new file mode 100644
index 00000000..2b31ed7e
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlib.h
@@ -0,0 +1,80 @@
+/* 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, 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);
+
+
+
+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/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.c b/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.c
new file mode 100644
index 00000000..171db33d
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.c
@@ -0,0 +1,3724 @@
+/* -*- 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"
+#include "gdk-pixbuf-xlib-private.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;
+ }
+}
+
+/**
+ * xlib_rgb_set_verbose:
+ * @verbose: %True to be verbose
+ *
+ * Enables/disables debug spew.
+ **/
+void
+xlib_rgb_set_verbose (Bool verbose)
+{
+ xlib_rgb_verbose = verbose;
+}
+
+/**
+ * xlib_rgb_set_install:
+ * @install: %True to install a colormap
+ *
+ * Sets whether we install an RGB colormap.
+ **/
+void
+xlib_rgb_set_install (Bool install)
+{
+ xlib_rgb_install_cmap = install;
+}
+
+/**
+ * xlib_rgb_set_min_colors:
+ * @min_colors: minimum colors to use
+ *
+ * Sets the minimum number of colors in the color cube.
+ **/
+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 unsigned int
+xlib_rgb_score_visual (XVisualInfo *visual)
+{
+ unsigned int 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;
+ unsigned int 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;
+
+#if KSVG_BYTE_ORDER == KSVG_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 (unsigned int 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, unsigned int rgb)
+{
+ unsigned long color;
+
+ color = xlib_rgb_xpixel_from_rgb (rgb);
+ XSetForeground(image_info->display, gc, color);
+}
+
+/**
+ * xlib_rgb_gc_set_background:
+ * @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, unsigned int rgb)
+{
+ unsigned long color;
+
+ color = xlib_rgb_xpixel_from_rgb (rgb);
+ XSetBackground(image_info->display, gc, color);
+}
+
+#if KSVG_BYTE_ORDER == KSVG_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)
+ {
+ unsigned int r1b0g0r0;
+ unsigned int g2r2b1g1;
+ unsigned int b3g3r3b2;
+
+ r1b0g0r0 = ((unsigned int *)bp2)[0];
+ g2r2b1g1 = ((unsigned int *)bp2)[1];
+ b3g3r3b2 = ((unsigned int *)bp2)[2];
+ ((unsigned int *)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 unsigned int *DM_565 = NULL;
+
+static void
+xlib_rgb_preprocess_dm_565 (void)
+{
+ int i;
+ unsigned int dith;
+
+ if (DM_565 == NULL)
+ {
+ DM_565 = malloc(sizeof(unsigned int) * 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 KSVG_BYTE_ORDER == KSVG_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++;
+ ((unsigned short *)obptr)[0] = ((r & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ (b >> 3);
+ obptr += 2;
+ }
+ }
+ else
+ {
+ for (x = 0; x < width - 3; x += 4)
+ {
+ unsigned int r1b0g0r0;
+ unsigned int g2r2b1g1;
+ unsigned int b3g3r3b2;
+
+ r1b0g0r0 = ((unsigned int *)bp2)[0];
+ g2r2b1g1 = ((unsigned int *)bp2)[1];
+ b3g3r3b2 = ((unsigned int *)bp2)[2];
+ ((unsigned int *)obptr)[0] =
+ ((r1b0g0r0 & 0xf8) << 8) |
+ ((r1b0g0r0 & 0xfc00) >> 5) |
+ ((r1b0g0r0 & 0xf80000) >> 19) |
+ (r1b0g0r0 & 0xf8000000) |
+ ((g2r2b1g1 & 0xfc) << 19) |
+ ((g2r2b1g1 & 0xf800) << 5);
+ ((unsigned int *)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++;
+ ((unsigned short *)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++;
+ ((unsigned short *)obptr)[0] = ((g & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ (g >> 3);
+ obptr += 2;
+ }
+ }
+ else
+ {
+ for (x = 0; x < width - 3; x += 4)
+ {
+ unsigned int g3g2g1g0;
+
+ g3g2g1g0 = ((unsigned int *)bp2)[0];
+ ((unsigned int *)obptr)[0] =
+ ((g3g2g1g0 & 0xf8) << 8) |
+ ((g3g2g1g0 & 0xfc) << 3) |
+ ((g3g2g1g0 & 0xf8) >> 3) |
+ (g3g2g1g0 & 0xf800) << 16 |
+ ((g3g2g1g0 & 0xfc00) << 11) |
+ ((g3g2g1g0 & 0xf800) << 5);
+ ((unsigned int *)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++;
+ ((unsigned short *)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++;
+ ((unsigned short *)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++)
+ {
+ unsigned int *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++)
+ {
+ int 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)
+ {
+ unsigned int r1b0g0r0;
+ unsigned int g2r2b1g1;
+ unsigned int b3g3r3b2;
+ unsigned int rgb02, rgb13;
+
+ r1b0g0r0 = ((unsigned int *)bp2)[0];
+ g2r2b1g1 = ((unsigned int *)bp2)[1];
+ b3g3r3b2 = ((unsigned int *)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);
+ ((unsigned int *)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);
+ ((unsigned int *)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++)
+ {
+ int 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++)
+ {
+ unsigned int *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT);
+ unsigned char *bp2 = bptr;
+
+ for (x = x_align; x < width; x++)
+ {
+ int 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 KSVG_BYTE_ORDER == KSVG_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)
+ {
+ unsigned int r1b0g0r0;
+ unsigned int g2r2b1g1;
+ unsigned int b3g3r3b2;
+
+ r1b0g0r0 = ((unsigned int *)bp2)[0];
+ g2r2b1g1 = ((unsigned int *)bp2)[1];
+ b3g3r3b2 = ((unsigned int *)bp2)[2];
+ ((unsigned int *)obptr)[0] =
+ (r1b0g0r0 & 0xff00) |
+ ((r1b0g0r0 & 0xff0000) >> 16) |
+ (((g2r2b1g1 & 0xff00) | (r1b0g0r0 & 0xff)) << 16);
+ ((unsigned int *)obptr)[1] =
+ (g2r2b1g1 & 0xff0000ff) |
+ ((r1b0g0r0 & 0xff000000) >> 16) |
+ ((b3g3r3b2 & 0xff) << 16);
+ ((unsigned int *)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];
+ ((unsigned int *)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];
+ ((unsigned int *)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];
+ ((unsigned int *)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;
+ unsigned int 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;
+ unsigned int 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;
+ unsigned int 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;
+ unsigned int 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 */
+ unsigned int 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 KSVG_BYTE_ORDER == KSVG_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 KSVG_BYTE_ORDER == KSVG_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)
+{
+ unsigned int 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 (unsigned int *colors, int n_colors)
+{
+ XlibRgbCmap *cmap;
+ int i, j;
+ unsigned int rgb;
+
+ if (n_colors < 0)
+ return NULL;
+ if (n_colors > 256)
+ return NULL;
+ cmap = malloc(sizeof(XlibRgbCmap));
+ memcpy (cmap->colors, colors, n_colors * sizeof(unsigned int));
+ 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/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.h b/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.h
new file mode 100644
index 00000000..d35c1c87
--- /dev/null
+++ b/karbon/render/xrgbrender/gdk-pixbuf-xlibrgb.h
@@ -0,0 +1,194 @@
+/* -*- 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>
+
+
+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 (unsigned int rgb);
+
+void
+xlib_rgb_gc_set_foreground (GC gc, unsigned int rgb);
+
+void
+xlib_rgb_gc_set_background (GC gc, unsigned int 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 (unsigned int *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__ */