summaryrefslogtreecommitdiffstats
path: root/ksvg/impl/libs
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /ksvg/impl/libs
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'ksvg/impl/libs')
-rw-r--r--ksvg/impl/libs/Makefile.am1
-rw-r--r--ksvg/impl/libs/art_support/Makefile.am4
-rw-r--r--ksvg/impl/libs/art_support/art_misc.c1841
-rw-r--r--ksvg/impl/libs/art_support/art_misc.h79
-rw-r--r--ksvg/impl/libs/art_support/art_render_misc.c774
-rw-r--r--ksvg/impl/libs/art_support/art_render_misc.h90
-rw-r--r--ksvg/impl/libs/art_support/art_rgba_svp.c659
-rw-r--r--ksvg/impl/libs/art_support/art_rgba_svp.h57
-rw-r--r--ksvg/impl/libs/libtext2path/AUTHORS1
-rw-r--r--ksvg/impl/libs/libtext2path/COPYING339
-rw-r--r--ksvg/impl/libs/libtext2path/ChangeLog2
-rw-r--r--ksvg/impl/libs/libtext2path/INSTALL181
-rw-r--r--ksvg/impl/libs/libtext2path/Makefile.am7
-rw-r--r--ksvg/impl/libs/libtext2path/NEWS1
-rw-r--r--ksvg/impl/libs/libtext2path/README4
-rw-r--r--ksvg/impl/libs/libtext2path/VERSION1
-rw-r--r--ksvg/impl/libs/libtext2path/configure.in.in41
-rw-r--r--ksvg/impl/libs/libtext2path/libtext2path.lsm16
-rw-r--r--ksvg/impl/libs/libtext2path/libtext2path.pc.in11
-rw-r--r--ksvg/impl/libs/libtext2path/libtext2path.spec41
-rw-r--r--ksvg/impl/libs/libtext2path/src/Affine.cpp174
-rw-r--r--ksvg/impl/libs/libtext2path/src/Affine.h67
-rw-r--r--ksvg/impl/libs/libtext2path/src/BezierPath.h56
-rw-r--r--ksvg/impl/libs/libtext2path/src/Cache.h156
-rw-r--r--ksvg/impl/libs/libtext2path/src/Converter.cpp505
-rw-r--r--ksvg/impl/libs/libtext2path/src/Converter.h94
-rw-r--r--ksvg/impl/libs/libtext2path/src/Font.cpp252
-rw-r--r--ksvg/impl/libs/libtext2path/src/Font.h91
-rw-r--r--ksvg/impl/libs/libtext2path/src/Glyph.cpp353
-rw-r--r--ksvg/impl/libs/libtext2path/src/Glyph.h198
-rw-r--r--ksvg/impl/libs/libtext2path/src/GlyphTracer.cpp76
-rw-r--r--ksvg/impl/libs/libtext2path/src/GlyphTracer.h65
-rw-r--r--ksvg/impl/libs/libtext2path/src/Makefile.am10
-rw-r--r--ksvg/impl/libs/libtext2path/src/Point.h65
-rw-r--r--ksvg/impl/libs/libtext2path/src/QtUnicode.cpp164
-rw-r--r--ksvg/impl/libs/libtext2path/src/QtUnicode.h149
-rw-r--r--ksvg/impl/libs/libtext2path/src/Rectangle.cpp102
-rw-r--r--ksvg/impl/libs/libtext2path/src/Rectangle.h55
-rw-r--r--ksvg/impl/libs/libtext2path/src/Tools.h85
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/assert.hpp24
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/checked_delete.hpp61
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/lightweight_mutex.hpp74
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp367
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/shared_ptr.hpp395
-rw-r--r--ksvg/impl/libs/libtext2path/src/myboost/throw_exception.hpp30
-rw-r--r--ksvg/impl/libs/xrgbrender/Makefile.am5
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-drawable.c1137
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-private.h30
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.c46
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.h78
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.c3425
-rw-r--r--ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.h145
52 files changed, 12684 insertions, 0 deletions
diff --git a/ksvg/impl/libs/Makefile.am b/ksvg/impl/libs/Makefile.am
new file mode 100644
index 00000000..76f41e24
--- /dev/null
+++ b/ksvg/impl/libs/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = xrgbrender art_support libtext2path
diff --git a/ksvg/impl/libs/art_support/Makefile.am b/ksvg/impl/libs/art_support/Makefile.am
new file mode 100644
index 00000000..4bf00dd7
--- /dev/null
+++ b/ksvg/impl/libs/art_support/Makefile.am
@@ -0,0 +1,4 @@
+noinst_LTLIBRARIES = libksvgart.la
+libksvgart_la_SOURCES = art_render_misc.c art_rgba_svp.c art_misc.c
+
+INCLUDES = $(LIBART_CFLAGS) $(all_includes)
diff --git a/ksvg/impl/libs/art_support/art_misc.c b/ksvg/impl/libs/art_support/art_misc.c
new file mode 100644
index 00000000..69b45306
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_misc.c
@@ -0,0 +1,1841 @@
+#include <libart_lgpl/art_vpath.h>
+#include <libart_lgpl/art_bpath.h>
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_affine.h>
+#include <libart_lgpl/art_svp_render_aa.h>
+
+#include "art_misc.h"
+
+extern double ceil(double x);
+extern double floor(double x);
+
+/**
+ * art_vpath_render_bez: Render a bezier segment into the vpath.
+ * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
+ * @pn_points: Pointer to the number of points in *@p_vpath.
+ * @pn_points_max: Pointer to the number of points allocated.
+ * @x0: X coordinate of starting bezier point.
+ * @y0: Y coordinate of starting bezier point.
+ * @x1: X coordinate of first bezier control point.
+ * @y1: Y coordinate of first bezier control point.
+ * @x2: X coordinate of second bezier control point.
+ * @y2: Y coordinate of second bezier control point.
+ * @x3: X coordinate of ending bezier point.
+ * @y3: Y coordinate of ending bezier point.
+ * @flatness: Flatness control.
+ *
+ * Renders a bezier segment into the vector path, reallocating and
+ * updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
+ * incremented by the number of vector points added.
+ *
+ * This step includes (@x0, @y0) but not (@x3, @y3).
+ *
+ * The @flatness argument guides the amount of subdivision. The Adobe
+ * PostScript reference manual defines flatness as the maximum
+ * deviation between the any point on the vpath approximation and the
+ * corresponding point on the "true" curve, and we follow this
+ * definition here. A value of 0.25 should ensure high quality for aa
+ * rendering.
+ **/
+ void
+ksvg_art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
+ double x0, double y0,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double flatness)
+{
+ double x3_0, y3_0;
+ double z3_0_dot;
+ double z1_dot, z2_dot;
+ double z1_perp, z2_perp;
+ double max_perp_sq;
+
+ double x_m, y_m;
+ double xa1, ya1;
+ double xa2, ya2;
+ double xb1, yb1;
+ double xb2, yb2;
+
+ /* It's possible to optimize this routine a fair amount.
+
+ First, once the _dot conditions are met, they will also be met in
+ all further subdivisions. So we might recurse to a different
+ routine that only checks the _perp conditions.
+
+ Second, the distance _should_ decrease according to fairly
+ predictable rules (a factor of 4 with each subdivision). So it might
+ be possible to note that the distance is within a factor of 4 of
+ acceptable, and subdivide once. But proving this might be hard.
+
+ Third, at the last subdivision, x_m and y_m can be computed more
+ expeditiously (as in the routine above).
+
+ Finally, if we were able to subdivide by, say 2 or 3, this would
+ allow considerably finer-grain control, i.e. fewer points for the
+ same flatness tolerance. This would speed things up downstream.
+
+ In any case, this routine is unlikely to be the bottleneck. It's
+ just that I have this undying quest for more speed...
+
+*/
+
+ x3_0 = x3 - x0;
+ y3_0 = y3 - y0;
+
+ /* z3_0_dot is dist z0-z3 squared */
+ z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
+
+ /* todo: this test is far from satisfactory. */
+ if (z3_0_dot < 0.001)
+ goto nosubdivide;
+
+ /* we can avoid subdivision if:
+
+ z1 has distance no more than flatness from the z0-z3 line
+
+ z1 is no more z0'ward than flatness past z0-z3
+
+ z1 is more z0'ward than z3'ward on the line traversing z0-z3
+
+ and correspondingly for z2 */
+
+ /* perp is distance from line, multiplied by dist z0-z3 */
+ max_perp_sq = flatness * flatness * z3_0_dot;
+ z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
+ if (z1_perp * z1_perp > max_perp_sq)
+ goto subdivide;
+
+ z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
+ if (z2_perp * z2_perp > max_perp_sq)
+ goto subdivide;
+
+ z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
+ if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
+ goto subdivide;
+
+ z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
+ if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
+ goto subdivide;
+
+ if (z1_dot + z1_dot > z3_0_dot)
+ goto subdivide;
+
+ if (z2_dot + z2_dot > z3_0_dot)
+ goto subdivide;
+
+nosubdivide:
+ /* don't subdivide */
+ art_vpath_add_point (p_vpath, pn, pn_max,
+ ART_LINETO, x3, y3);
+ return;
+
+subdivide:
+
+ xa1 = (x0 + x1) * 0.5;
+ ya1 = (y0 + y1) * 0.5;
+ xa2 = (x0 + 2 * x1 + x2) * 0.25;
+ ya2 = (y0 + 2 * y1 + y2) * 0.25;
+ xb1 = (x1 + 2 * x2 + x3) * 0.25;
+ yb1 = (y1 + 2 * y2 + y3) * 0.25;
+ xb2 = (x2 + x3) * 0.5;
+ yb2 = (y2 + y3) * 0.5;
+ x_m = (xa2 + xb1) * 0.5;
+ y_m = (ya2 + yb1) * 0.5;
+#ifdef VERBOSE
+ printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
+ xb1, yb1, xb2, yb2);
+#endif
+ ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
+ x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
+ ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
+ x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
+}
+
+#define RENDER_LEVEL 4
+#define RENDER_SIZE (1 << (RENDER_LEVEL))
+
+/**
+ * ksvg_art_bez_path_to_vec: Create vpath from bezier path.
+ * @bez: Bezier path.
+ * @flatness: Flatness control.
+ *
+ * Creates a vector path closely approximating the bezier path defined by
+ * @bez. The @flatness argument controls the amount of subdivision. In
+ * general, the resulting vpath deviates by at most @flatness pixels
+ * from the "ideal" path described by @bez.
+ *
+ * Return value: Newly allocated vpath.
+ **/
+ ArtVpath *
+ksvg_art_bez_path_to_vec(const ArtBpath *bez, double flatness)
+{
+ ArtVpath *vec;
+ int vec_n, vec_n_max;
+ int bez_index;
+ double x, y;
+
+ vec_n = 0;
+ vec_n_max = RENDER_SIZE;
+ vec = art_new (ArtVpath, vec_n_max);
+
+ /* Initialization is unnecessary because of the precondition that the
+ bezier path does not begin with LINETO or CURVETO, but is here
+ to make the code warning-free. */
+ x = 0;
+ y = 0;
+
+ bez_index = 0;
+ do
+ {
+#ifdef VERBOSE
+ printf ("%s %g %g\n",
+ bez[bez_index].code == ART_CURVETO ? "curveto" :
+ bez[bez_index].code == ART_LINETO ? "lineto" :
+ bez[bez_index].code == ART_MOVETO ? "moveto" :
+ bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
+ "end", bez[bez_index].x3, bez[bez_index].y3);
+#endif
+ /* make sure space for at least one more code */
+ if (vec_n >= vec_n_max)
+ art_expand (vec, ArtVpath, vec_n_max);
+ switch (bez[bez_index].code)
+ {
+ case ART_MOVETO_OPEN:
+ case ART_MOVETO:
+ case ART_LINETO:
+ x = bez[bez_index].x3;
+ y = bez[bez_index].y3;
+ vec[vec_n].code = bez[bez_index].code;
+ vec[vec_n].x = x;
+ vec[vec_n].y = y;
+ vec_n++;
+ break;
+ case ART_END:
+ vec[vec_n].code = ART_END;
+ vec[vec_n].x = 0;
+ vec[vec_n].y = 0;
+ vec_n++;
+ break;
+ case ART_END2:
+ vec[vec_n].code = (ArtPathcode)ART_END2;
+ vec[vec_n].x = bez[bez_index].x3;
+ vec[vec_n].y = bez[bez_index].y3;
+ vec_n++;
+ break;
+ case ART_CURVETO:
+#ifdef VERBOSE
+ printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
+ bez[bez_index].x1, bez[bez_index].y1,
+ bez[bez_index].x2, bez[bez_index].y2,
+ bez[bez_index].x3, bez[bez_index].y3);
+#endif
+ ksvg_art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
+ x, y,
+ bez[bez_index].x1, bez[bez_index].y1,
+ bez[bez_index].x2, bez[bez_index].y2,
+ bez[bez_index].x3, bez[bez_index].y3,
+ flatness);
+ x = bez[bez_index].x3;
+ y = bez[bez_index].y3;
+ break;
+ }
+ }
+ while (bez[bez_index++].code != ART_END);
+ return vec;
+}
+
+/* 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 ksvg_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;
+}
+
+/**
+ * ksvg_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.
+ * @alpha: Alpha, range 0..256.
+ *
+ * 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.
+ *
+ * KSVG additions : we have changed this function to support an alpha level as well.
+* also we made sure compositing an rgba image over an rgb buffer works.
+**/
+ void ksvg_art_rgb_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,
+ int alpha)
+{
+ /* 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);
+
+ if(alpha == 255)
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ 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] = dst_p[0] + (((src_p[2] - dst_p[0]) * src_p[3] + 0x80) >> 8);
+ dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * src_p[3] + 0x80) >> 8);
+ dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * src_p[3] + 0x80) >> 8);
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+ else
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ 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] = dst_p[0] + (((src_p[2] - dst_p[0]) * alpha + 0x80) >> 8);
+ dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * alpha + 0x80) >> 8);
+ dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * alpha + 0x80) >> 8);
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
+
+
+typedef struct _ksvgArtRgbAffineClipAlphaData ksvgArtRgbAffineClipAlphaData;
+
+struct _ksvgArtRgbAffineClipAlphaData
+{
+ int alphatab[256];
+ art_u8 alpha;
+ art_u8 *dst;
+ int dst_rowstride;
+ int x0, x1;
+ double inv[6];
+ const art_u8 *src;
+ int src_width;
+ int src_height;
+ int src_rowstride;
+ const art_u8 *mask;
+ int y0;
+};
+
+static
+void ksvg_art_rgb_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ pt.y = y;
+
+ for(x = x0; x < x1; x++)
+ {
+ pt.x = x;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)(src_pt.x);
+ src_y = (int)(src_pt.y);
+
+ if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
+ {
+ int s;
+ int d;
+ int tmp;
+ int srcAlpha;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ srcAlpha = alpha * src_p[3] + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ d = *dst_p;
+ s = src_p[2];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[1];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[0];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+ }
+ else
+ dst_p += 3;
+ }
+}
+
+static void
+ksvg_art_rgb_affine_clip_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgb_affine_clip_run(linebuf + (run_x0 - x0) * 3, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_run(linebuf + (run_x1 - x0) * 3, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgb_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ pt.y = y;
+
+ for(x = x0; x < x1; x++)
+ {
+ pt.x = x;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)(src_pt.x);
+ src_y = (int)(src_pt.y);
+
+ if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
+ {
+ int s;
+ int d;
+ int tmp;
+ int srcAlpha;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ srcAlpha = alpha * src_p[3] + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ srcAlpha = (srcAlpha * *mask++) + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ d = *dst_p;
+ s = src_p[2];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[1];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[0];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+ }
+ else
+ {
+ dst_p += 3;
+ mask++;
+ }
+ }
+}
+
+static void
+ksvg_art_rgb_affine_clip_mask_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+ const art_u8 *maskbuf;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+ maskbuf = data->mask + (y - data->y0) * (x1 - x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x0 - x0) * 3, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x1 - x0) * 3, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgba_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ pt.y = y;
+
+ for(x = x0; x < x1; x++)
+ {
+ pt.x = x;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)(src_pt.x);
+ src_y = (int)(src_pt.y);
+
+ if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
+ {
+ int s;
+ int d;
+ int tmp;
+ int srcAlpha;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ srcAlpha = alpha * src_p[3] + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ d = *dst_p;
+ s = src_p[2];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[1];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[0];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+
+ tmp = srcAlpha * (255 - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+ }
+ else
+ dst_p += 4;
+ }
+}
+
+static void
+ksvg_art_rgba_affine_clip_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgba_affine_clip_run(linebuf + (run_x0 - x0) * 4, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_run(linebuf + (run_x1 - x0) * 4, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgba_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ pt.y = y;
+
+ for(x = x0; x < x1; x++)
+ {
+ pt.x = x;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)(src_pt.x);
+ src_y = (int)(src_pt.y);
+
+ if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
+ {
+ int s;
+ int d;
+ int tmp;
+ int srcAlpha;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ srcAlpha = alpha * src_p[3] + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ srcAlpha = (srcAlpha * *mask++) + 0x80;
+ srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
+
+ d = *dst_p;
+ s = src_p[2];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[1];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+ s = src_p[0];
+
+ tmp = srcAlpha * (s - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+
+ d = *dst_p;
+
+ tmp = srcAlpha * (255 - d) + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ *dst_p++ = d + tmp;
+ }
+ else
+ {
+ dst_p += 4;
+ mask++;
+ }
+ }
+}
+
+static void
+ksvg_art_rgba_affine_clip_mask_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+ const art_u8 *maskbuf;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+ maskbuf = data->mask + (y - data->y0) * (x1 - x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x0 - x0) * 4, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x1 - x0) * 4, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+/**
+ * ksvg_art_rgb_affine_clip: Affine transform source RGB image and composite, with clipping path.
+ * @svp: Clipping path.
+ * @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.
+ * @alpha: Alpha, range 0..256.
+ *
+ * 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.
+ *
+ * KSVG additions : we have changed this function to support an alpha level as well.
+* also we made sure compositing an rgba image over an rgb buffer works.
+**/
+void ksvg_art_rgb_affine_clip(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, int dst_channels,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ int alpha, const art_u8 *mask)
+{
+ ksvgArtRgbAffineClipAlphaData data;
+ int i;
+ int a, da;
+
+ data.alpha = alpha;
+
+ 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.dst = dst;
+ data.dst_rowstride = dst_rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ data.y0 = y0;
+ data.mask = mask;
+
+ art_affine_invert(data.inv, affine);
+
+ data.src = src;
+ data.src_width = src_width;
+ data.src_height = src_height;
+ data.src_rowstride = src_rowstride;
+
+ if(dst_channels == 3)
+ {
+ if(mask)
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_mask_callback, &data);
+ else
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_callback, &data);
+ }
+ else
+ {
+ if(mask)
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_mask_callback, &data);
+ else
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_callback, &data);
+ }
+}
+
+
+static
+void ksvg_art_rgb_texture_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+ int srcAlpha;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ /* TODO: optimise and filter? */
+ pt.y = y + 0.5;
+
+ for(x = x0; x < x1; x++)
+ {
+ int s;
+ int d;
+ int tmp;
+ int tmp2;
+
+ pt.x = x + 0.5;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)floor(src_pt.x);
+ src_y = (int)floor(src_pt.y);
+
+ if(src_x < 0)
+ {
+ /* Can't assume % behaviour with negative values */
+ src_x += ((src_x / -src_width) + 1) * src_width;
+ }
+
+ if(src_y < 0)
+ {
+ src_y += ((src_y / -src_height) + 1) * src_height;
+ }
+
+ src_x %= src_width;
+ src_y %= src_height;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ /* Pattern source is in RGBA format, premultiplied.
+ * alpha represents fill/stroke/group opacity.
+ *
+ * Multiply source alpha by 'alpha' then composite over.
+ * For each channel, d = d + alpha * (s - srcAlpha * d).
+ */
+
+ srcAlpha = src_p[3];
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+ }
+}
+
+static void
+ksvg_art_rgb_texture_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgb_texture_run(linebuf + (run_x0 - x0) * 3, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_run(linebuf + (run_x1 - x0) * 3, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgb_texture_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+ int srcAlpha;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ /* TODO: optimise and filter? */
+ pt.y = y + 0.5;
+
+ for(x = x0; x < x1; x++)
+ {
+ int s;
+ int d;
+ int am;
+ int tmp;
+ int tmp2;
+
+ pt.x = x + 0.5;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)floor(src_pt.x);
+ src_y = (int)floor(src_pt.y);
+
+ if(src_x < 0)
+ {
+ /* Can't assume % behaviour with negative values */
+ src_x += ((src_x / -src_width) + 1) * src_width;
+ }
+
+ if(src_y < 0)
+ {
+ src_y += ((src_y / -src_height) + 1) * src_height;
+ }
+
+ src_x %= src_width;
+ src_y %= src_height;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ /* Pattern source is in RGBA format, premultiplied.
+ * alpha represents fill/stroke/group opacity.
+ *
+ * Multiply source alpha by 'alpha' and mask value then composite over.
+ * For each channel, d = d + alpha * mask * (s - srcAlpha * d).
+ */
+
+ am = (alpha * *mask++) + 0x80;
+ am = (am + (am >> 8)) >> 8;
+
+ srcAlpha = src_p[3];
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+ }
+}
+
+static void
+ksvg_art_rgb_texture_mask_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+ const art_u8 *maskbuf;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ maskbuf = data->mask + (y - data->y0) * (x1 - x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgb_texture_mask_run(linebuf + (run_x0 - x0) * 3, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_mask_run(linebuf + (run_x1 - x0) * 3, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgb_texture_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgba_texture_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+ int srcAlpha;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ /* TODO: optimise and filter? */
+ pt.y = y + 0.5;
+
+ for(x = x0; x < x1; x++)
+ {
+ int s;
+ int d;
+ int tmp;
+ int tmp2;
+
+ pt.x = x + 0.5;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)floor(src_pt.x);
+ src_y = (int)floor(src_pt.y);
+
+ if(src_x < 0)
+ {
+ /* Can't assume % behaviour with negative values */
+ src_x += ((src_x / -src_width) + 1) * src_width;
+ }
+
+ if(src_y < 0)
+ {
+ src_y += ((src_y / -src_height) + 1) * src_height;
+ }
+
+ src_x %= src_width;
+ src_y %= src_height;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ /* Pattern source is in RGBA format, premultiplied.
+ * alpha represents fill/stroke/group opacity.
+ *
+ * Multiply source alpha by 'alpha' then composite over.
+ * For each colour channel, d = d + alpha * (s - srcAlpha * d).
+ */
+
+ srcAlpha = src_p[3];
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = alpha * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ /* dstAlpha = dstAlpha + srcAlpha * alpha * (1 - dstAlpha) */
+ d = *dst_p;
+
+ tmp = srcAlpha * alpha + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = tmp * (255 - d) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+ src_p++;
+ }
+}
+
+static void
+ksvg_art_rgba_texture_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgba_texture_run(linebuf + (run_x0 - x0) * 4, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_run(linebuf + (run_x1 - x0) * 4, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+static
+void ksvg_art_rgba_texture_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
+ int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
+{
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int x;
+ int srcAlpha;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ /* TODO: optimise and filter? */
+ pt.y = y + 0.5;
+
+ for(x = x0; x < x1; x++)
+ {
+ int s;
+ int d;
+ int am;
+ int tmp;
+ int tmp2;
+
+ pt.x = x + 0.5;
+
+ art_affine_point(&src_pt, &pt, inv);
+
+ src_x = (int)floor(src_pt.x);
+ src_y = (int)floor(src_pt.y);
+
+ if(src_x < 0)
+ {
+ /* Can't assume % behaviour with negative values */
+ src_x += ((src_x / -src_width) + 1) * src_width;
+ }
+
+ if(src_y < 0)
+ {
+ src_y += ((src_y / -src_height) + 1) * src_height;
+ }
+
+ src_x %= src_width;
+ src_y %= src_height;
+
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+
+ /* Pattern source is in RGBA format, premultiplied.
+ * alpha represents fill/stroke/group opacity.
+ *
+ * Multiply source alpha by 'alpha' and mask value then composite over.
+ * For each channel, d = d + alpha * mask * (s - srcAlpha * d).
+ */
+
+ am = (alpha * *mask++) + 0x80;
+ am = (am + (am >> 8)) >> 8;
+
+ srcAlpha = src_p[3];
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ d = *dst_p;
+ s = *src_p++;
+
+ tmp = srcAlpha * d + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = am * (s - tmp) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+
+ /* dstAlpha = dstAlpha + srcAlpha * alpha * mask * (1 - dstAlpha) */
+ d = *dst_p;
+
+ tmp = srcAlpha * am + 0x80;
+ tmp = (tmp + (tmp >> 8)) >> 8;
+
+ tmp2 = tmp * (255 - d) + 0x80;
+ tmp2 = (tmp2 + (tmp2 >> 8)) >> 8;
+
+ *dst_p++ = d + tmp2;
+ src_p++;
+ }
+}
+
+static void
+ksvg_art_rgba_texture_mask_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ int *alphatab;
+ int alpha;
+ const art_u8 *maskbuf;
+
+ linebuf = data->dst;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ alphatab = data->alphatab;
+
+ maskbuf = data->mask + (y - data->y0) * (x1 - x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ 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)
+ ksvg_art_rgba_texture_mask_run(linebuf + (run_x0 - x0) * 4, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ running_sum += steps[k].delta;
+ if(x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_mask_run(linebuf + (run_x1 - x0) * 4, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ ksvg_art_rgba_texture_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
+ }
+
+ data->dst += data->dst_rowstride;
+}
+
+/**
+ * ksvg_art_rgb_texture: Affine transform source RGB image and composite, with clipping path.
+ * @svp: Clipping path.
+ * @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.
+ * @alpha: Alpha, range 0..256.
+ *
+ * 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.
+ *
+ * KSVG additions : we have changed this function to support an alpha level as well.
+* also we made sure compositing an rgba image over an rgb buffer works.
+**/
+void ksvg_art_rgb_texture(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ int dst_channels,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphaGamma,
+ int alpha,
+ const art_u8 *mask)
+{
+ ksvgArtRgbAffineClipAlphaData data;
+ int i;
+ int a, da;
+
+ data.alpha = alpha;
+
+ 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.dst = dst;
+ data.dst_rowstride = dst_rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+
+ data.inv[0] = affine[0];
+ data.inv[1] = affine[1];
+ data.inv[2] = affine[2];
+ data.inv[3] = affine[3];
+ data.inv[4] = affine[4];
+ data.inv[5] = affine[5];
+
+ data.src = src;
+ data.src_width = src_width;
+ data.src_height = src_height;
+ data.src_rowstride = src_rowstride;
+
+ data.mask = mask;
+ data.y0 = y0;
+
+ if(mask)
+ {
+ if(dst_channels == 3)
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_texture_mask_callback, &data);
+ else
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_texture_mask_callback, &data);
+ }
+ else
+ {
+ if(dst_channels == 3)
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_texture_callback, &data);
+ else
+ art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_texture_callback, &data);
+ }
+}
+
+/**
+ * ksvg_art_svp_move: moves an svp relatively to the current position.
+ * @svp: SVP to move.
+ * @dx: relative amount to move horizontally.
+ * @dy: relative amount to move vertically.
+ *
+ * Note : this function always moves the svp, not taking into account render buffer
+ * boundaries.
+ **/
+void ksvg_art_svp_move(ArtSVP *svp, int dx, int dy)
+{
+ int i, j;
+ ArtSVPSeg *seg;
+
+ if(dx == 0 && dy == 0) return;
+ for(i = 0;i < svp->n_segs;i++)
+ {
+ seg = &svp->segs[i];
+ for(j = 0;j < seg->n_points;j++)
+ {
+ seg->points[j].x += dx;
+ seg->points[j].y += dy;
+ }
+ seg->bbox.x0 += dx;
+ seg->bbox.y0 += dy;
+ seg->bbox.x1 += dx;
+ seg->bbox.y1 += dy;
+ }
+}
+
diff --git a/ksvg/impl/libs/art_support/art_misc.h b/ksvg/impl/libs/art_support/art_misc.h
new file mode 100644
index 00000000..52f09a63
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_misc.h
@@ -0,0 +1,79 @@
+/* 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 __KSVG_ART_H__
+#define __KSVG_ART_H__
+
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_bpath.h>
+#include <libart_lgpl/art_vpath.h>
+#include <libart_lgpl/art_alphagamma.h>
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_svp.h>
+
+#define ART_END2 10
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void ksvg_art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
+ double x0, double y0,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double flatness);
+
+ ArtVpath *ksvg_art_bez_path_to_vec(const ArtBpath *bez, double flatness);
+
+ void ksvg_art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+ int src_width, int src_height,
+ const double affine[6]);
+
+ void ksvg_art_rgb_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,
+ int alpha);
+
+ void ksvg_art_rgb_affine_clip(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, int dst_channels,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ int alpha, const art_u8 *mask);
+
+ void ksvg_art_rgb_texture(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ int dst_channels,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphaGamma,
+ int alpha,
+ const art_u8 *mask);
+
+ void ksvg_art_svp_move(ArtSVP *svp, int dx, int dy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ksvg/impl/libs/art_support/art_render_misc.c b/ksvg/impl/libs/art_support/art_render_misc.c
new file mode 100644
index 00000000..1603da1e
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_render_misc.c
@@ -0,0 +1,774 @@
+/* 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) 2001-2003 KSVG Team
+ *
+ * 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>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* These are in KSVGHelper.cpp */
+int linearRGBFromsRGB(int sRGB8bit);
+int sRGBFromLinearRGB(int linearRGB8bit);
+
+typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
+
+struct _ArtImageSourceGradRad {
+ ArtImageSource super;
+ const ArtKSVGGradientRadial *gradient;
+ double a;
+};
+
+#define EPSILON 1e-6
+
+/**
+ * art_ksvg_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_ksvg_render_gradient_setpix (ArtRender *render,
+ art_u8 *dst,
+ int n_stops, ArtGradientStop *stops,
+ double offset, ArtKSVGGradientInterpolation interpolation)
+{
+ 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);
+ if(interpolation == ART_KSVG_LINEARRGB_INTERPOLATION)
+ {
+ for (j = 0; j < n_ch; j++)
+ {
+ int z0, z1;
+ int z;
+ int z0_8bit, z0_linearRGB_8bit;
+ int z1_8bit, z1_linearRGB_8bit;
+ int z_8bit, z_sRGB_8bit;
+
+ /* Note: Using explicit variables for intermediate steps since */
+ /* the ART_PIX macros reference the argument more than once. */
+ z0 = stops[ix - 1].color[j];
+ z0_8bit = ART_PIX_8_FROM_MAX(z0);
+ z0_linearRGB_8bit = linearRGBFromsRGB(z0_8bit);
+ z0 = ART_PIX_MAX_FROM_8(z0_linearRGB_8bit);
+
+ z1 = stops[ix].color[j];
+ z1_8bit = ART_PIX_8_FROM_MAX(z1);
+ z1_linearRGB_8bit = linearRGBFromsRGB(z1_8bit);
+ z1 = ART_PIX_MAX_FROM_8(z1_linearRGB_8bit);
+
+ z = floor (z0 + (z1 - z0) * interp + 0.5);
+ z_8bit = ART_PIX_8_FROM_MAX(z);
+ z_sRGB_8bit = sRGBFromLinearRGB(z_8bit);
+
+ if (render->buf_depth == 8)
+ dst[j] = z_sRGB_8bit;
+ else /* (render->buf_depth == 16) */
+ ((art_u16 *)dst)[j] = ART_PIX_MAX_FROM_8(z_sRGB_8bit);
+ }
+ }
+ else
+ {
+ /* sRGB interpolation */
+ 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_ksvg_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_ksvg_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
+ const ArtKSVGGradientRadial *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_ksvg_render_gradient_setpix (render, bufp, n_stops, stops, z, gradient->interpolation);
+ bufp += pixstride;
+ b_a += db_a;
+ rad += drad;
+ drad += ddrad;
+ }
+}
+
+static void
+art_ksvg_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_ksvg_render_gradient_radial_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_SEPARATE;
+}
+
+/**
+ * art_ksvg_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_ksvg_render_gradient_radial (ArtRender *render,
+ const ArtKSVGGradientRadial *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_ksvg_render_gradient_radial_done;
+ image_source->super.negotiate = art_ksvg_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);
+}
+
+
+/* Hack to find out how to define alloca on different platforms.
+ * Modified version of glib/galloca.h.
+ */
+
+#ifdef __GNUC__
+/* GCC does the right thing */
+ #undef alloca
+ #define alloca(size) __builtin_alloca (size)
+#elif defined (HAVE_ALLOCA_H)
+/* a native and working alloca.h is there */
+ #include <alloca.h>
+#else /* !__GNUC__ && !HAVE_ALLOCA_H */
+ #ifdef _MSC_VER
+ #include <malloc.h>
+ #define alloca _alloca
+ #else /* !_MSC_VER */
+ #ifdef _AIX
+ #pragma alloca
+ #else /* !_AIX */
+ #ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+ #endif /* !alloca */
+ #endif /* !_AIX */
+ #endif /* !_MSC_VER */
+#endif /* !__GNUC__ && !HAVE_ALLOCA_H */
+
+#undef DEBUG_SPEW
+
+typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
+
+/* The stops will be copied right after this structure */
+struct _ArtImageSourceGradLin
+{
+ ArtImageSource super;
+ ArtKSVGGradientLinear gradient;
+ ArtGradientStop stops[1];
+};
+
+#ifndef MAX
+ #define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+static void
+art_ksvg_rgba_gradient_run (art_u8 *buf,
+ art_u8 *color1,
+ art_u8 *color2,
+ int len)
+{
+ int i;
+ int r, g, b, a;
+ int dr, dg, db, da;
+
+#ifdef DEBUG_SPEW
+ printf ("gradient run from %3d %3d %3d %3d to %3d %3d %3d %3d in %d pixels\n",
+ color1[0], color1[1], color1[2], color1[3],
+ color2[0], color2[1], color2[2], color2[3],
+ len);
+#endif
+
+ r = (color1[0] << 16) + 0x8000;
+ g = (color1[1] << 16) + 0x8000;
+ b = (color1[2] << 16) + 0x8000;
+ a = (color1[3] << 16) + 0x8000;
+ dr = ((color2[0] - color1[0]) << 16) / len;
+ dg = ((color2[1] - color1[1]) << 16) / len;
+ db = ((color2[2] - color1[2]) << 16) / len;
+ da = ((color2[3] - color1[3]) << 16) / len;
+
+ for(i = 0; i < len; i++)
+ {
+ *buf++ = (r>>16);
+ *buf++ = (g>>16);
+ *buf++ = (b>>16);
+ *buf++ = (a>>16);
+
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+}
+
+static void
+ksvg_calc_color_at (ArtGradientStop *stops,
+ int n_stops,
+ ArtGradientSpread spread,
+ double offset,
+ double offset_fraction,
+ int favor_start,
+ int ix,
+ art_u8 *color)
+{
+ double off0, off1;
+ int j;
+
+ if(spread == ART_GRADIENT_PAD)
+ {
+ if(offset < EPSILON)
+ {
+ color[0] = ART_PIX_8_FROM_MAX (stops[0].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[0].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[0].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[0].color[3]);
+ return;
+ }
+ if(offset >= 1.0 - EPSILON)
+ {
+ color[0] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[3]);
+ return;
+ }
+ }
+
+ if(ix > 0 && ix < n_stops)
+ {
+ off0 = stops[ix - 1].offset;
+ off1 = stops[ix].offset;
+ if(fabs (off1 - off0) > EPSILON)
+ {
+ double interp;
+ double o;
+ o = offset_fraction;
+
+ if((fabs (o) < EPSILON) && (!favor_start))
+ o = 1.0;
+ else if((fabs (o-1.0) < EPSILON) && (favor_start))
+ o = 0.0;
+
+ /*
+ if (offset_fraction == 0.0 && !favor_start)
+ offset_fraction = 1.0;
+ */
+
+ interp = (o - off0) / (off1 - off0);
+ for(j = 0; j < 4; 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);
+ color[j] = ART_PIX_8_FROM_MAX (z);
+ }
+ return;
+ }
+ /* If offsets are too close to safely do the division, just
+ pick the ix color. */
+ color[0] = ART_PIX_8_FROM_MAX (stops[ix].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[ix].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[ix].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[ix].color[3]);
+ return;
+ }
+
+ /*printf ("WARNING! bad ix %d in calc_color_at() [internal error]\n", ix);
+ assert (0);*/
+}
+
+static void
+art_ksvg_render_gradient_linear_render_8 (ArtRenderCallback *self,
+ ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+ const ArtKSVGGradientLinear *gradient = &(z->gradient);
+ int i;
+ int width = render->x1 - render->x0;
+ int len;
+ double offset, d_offset;
+ double offset_fraction;
+ int next_stop;
+ int ix;
+ art_u8 color1[4], color2[4];
+ int n_stops = gradient->n_stops;
+ int extra_stops;
+ ArtGradientStop *stops = gradient->stops;
+ ArtGradientStop *tmp_stops;
+ art_u8 *bufp = render->image_buf;
+ ArtGradientSpread spread = gradient->spread;
+
+#ifdef DEBUG_SPEW
+ printf ("x1: %d, x2: %d, y: %d\n", render->x0, render->x1, y);
+ printf ("spread: %d, stops:", gradient->spread);
+ for(i=0;i<n_stops;i++)
+ {
+ printf ("%f, ", gradient->stops[i].offset);
+ }
+ printf ("\n");
+ printf ("a: %f, b: %f, c: %f\n", gradient->a, gradient->b, gradient->c);
+#endif
+
+ offset = render->x0 * gradient->affine[0] + y * gradient->affine[2] + gradient->affine[4];
+ d_offset = gradient->affine[0];
+
+ /* We need to force the gradient to extend the whole 0..1 segment,
+ because the rest of the code doesn't handle partial gradients
+ correctly */
+ if((gradient->stops[0].offset > EPSILON /* == 0.0 */) ||
+ (gradient->stops[n_stops-1].offset < (1.0 - EPSILON)))
+ {
+ extra_stops = 0;
+ tmp_stops = stops = alloca (sizeof (ArtGradientStop) * (n_stops + 2));
+ if(gradient->stops[0].offset > EPSILON /* 0.0 */)
+ {
+ memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop));
+ tmp_stops[0].offset = 0.0;
+ tmp_stops += 1;
+ extra_stops++;
+ }
+ memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop) * n_stops);
+ if(gradient->stops[n_stops-1].offset < (1.0 - EPSILON))
+ {
+ tmp_stops += n_stops;
+ memcpy (tmp_stops, &gradient->stops[n_stops-1], sizeof (ArtGradientStop));
+ tmp_stops[0].offset = 1.0;
+ extra_stops++;
+ }
+ n_stops += extra_stops;
+
+
+#ifdef DEBUG_SPEW
+ printf ("start/stop modified stops:");
+ for(i=0;i<n_stops;i++)
+ {
+ printf ("%f, ", stops[i].offset);
+ }
+ printf ("\n");
+#endif
+
+ }
+
+ if(spread == ART_GRADIENT_REFLECT)
+ {
+ tmp_stops = stops;
+ stops = alloca (sizeof (ArtGradientStop) * n_stops * 2);
+ memcpy (stops, tmp_stops, sizeof (ArtGradientStop) * n_stops);
+
+ for(i = 0; i< n_stops; i++)
+ {
+ stops[n_stops * 2 - 1 - i].offset = (1.0 - stops[i].offset / 2.0);
+ memcpy (stops[n_stops * 2 - 1 - i].color, stops[i].color, sizeof (stops[i].color));
+ stops[i].offset = stops[i].offset / 2.0;
+ }
+
+ spread = ART_GRADIENT_REPEAT;
+ offset = offset / 2.0;
+ d_offset = d_offset / 2.0;
+
+ n_stops = 2 * n_stops;
+
+#ifdef DEBUG_SPEW
+ printf ("reflect modified stops:");
+ for(i=0;i<n_stops;i++)
+ {
+ printf ("%f, ", stops[i].offset);
+ }
+ printf ("\n");
+#endif
+ }
+
+ offset_fraction = offset - floor (offset);
+#ifdef DEBUG_SPEW
+ printf ("inital offset: %f, fraction: %f d_offset: %f\n", offset, offset_fraction, d_offset);
+#endif
+ /* ix is selected so that offset_fraction is
+ stops[ix-1] <= offset_fraction <= stops[ix]
+ If offset_fraction is equal to one of the edges, ix
+ is selected so the the section of the line extending
+ in the same direction as d_offset is between ix-1 and ix.
+ */
+ for(ix = 0; ix < n_stops; ix++)
+ if(stops[ix].offset > offset_fraction ||
+ (d_offset < 0.0 && fabs (stops[ix].offset - offset_fraction) < EPSILON))
+ break;
+ if(ix == 0)
+ ix = n_stops - 1;
+ else if(ix == n_stops)
+ ix = n_stops - 1;
+
+#ifdef DEBUG_SPEW
+ printf ("Initial ix: %d\n", ix);
+#endif
+#if 0
+ assert (ix > 0);
+ assert (ix < n_stops);
+ assert ((stops[ix-1].offset <= offset_fraction + EPSILON) ||
+ ((stops[ix].offset > (1.0 - EPSILON)) && (offset_fraction < EPSILON /* == 0.0*/)));
+ /*assert (offset_fraction <= stops[ix].offset);*/
+ /* FIXME: These asserts may be broken, it is for now
+ safer to not use them. Should be fixed!
+ See bug #121850
+ assert ((offset_fraction != stops[ix-1].offset) ||
+ (d_offset >= 0.0));
+ assert ((offset_fraction != stops[ix].offset) ||
+ (d_offset <= 0.0));
+ */
+#endif
+ while(width > 0)
+ {
+#ifdef DEBUG_SPEW
+ printf ("ix: %d\n", ix);
+ printf ("start offset: %f\n", offset);
+#endif
+ ksvg_calc_color_at (stops, n_stops,
+ spread,
+ offset,
+ offset_fraction,
+ (d_offset > -EPSILON),
+ ix,
+ color1);
+
+ if(d_offset > 0)
+ next_stop = ix;
+ else
+ next_stop = ix-1;
+
+#ifdef DEBUG_SPEW
+ printf ("next_stop: %d\n", next_stop);
+#endif
+ if(fabs (d_offset) > EPSILON)
+ {
+ double o;
+ o = offset_fraction;
+
+ if((fabs (o) <= EPSILON) && (ix == n_stops - 1))
+ o = 1.0;
+ else if((fabs (o-1.0) <= EPSILON) && (ix == 1))
+ o = 0.0;
+
+#ifdef DEBUG_SPEW
+ printf ("o: %f\n", o);
+#endif
+ len = (int)floor (fabs ((stops[next_stop].offset - o) / d_offset)) + 1;
+ len = MAX (len, 0);
+ len = MIN (len, width);
+ }
+ else
+ {
+ len = width;
+ }
+#ifdef DEBUG_SPEW
+ printf ("len: %d\n", len);
+#endif
+ if(len > 0)
+ {
+ offset = offset + (len-1) * d_offset;
+ offset_fraction = offset - floor (offset);
+#ifdef DEBUG_SPEW
+ printf ("end offset: %f, fraction: %f\n", offset, offset_fraction);
+#endif
+ ksvg_calc_color_at (stops, n_stops,
+ spread,
+ offset,
+ offset_fraction,
+ (d_offset < EPSILON),
+ ix,
+ color2);
+
+ art_ksvg_rgba_gradient_run (bufp,
+ color1,
+ color2,
+ len);
+ offset += d_offset;
+ offset_fraction = offset - floor (offset);
+ }
+
+ if(d_offset > 0)
+ {
+ do
+ {
+ ix++;
+ if(ix == n_stops)
+ ix = 1;
+ /* Note: offset_fraction can actually be one here on x86 machines that
+ does calculations with extended precision, but later rounds to 64bit.
+ This happens if the 80bit offset_fraction is larger than the
+ largest 64bit double that is less than one.
+ */
+ }
+ while(!((stops[ix-1].offset <= offset_fraction &&
+ offset_fraction < stops[ix].offset) ||
+ (ix == 1 && offset_fraction > (1.0 - EPSILON))));
+ }
+ else
+ {
+ do
+ {
+ ix--;
+ if(ix == 0)
+ ix = n_stops - 1;
+ }
+ while(!((stops[ix-1].offset < offset_fraction &&
+ offset_fraction <= stops[ix].offset) ||
+ (ix == n_stops - 1 && offset_fraction < EPSILON /* == 0.0*/)));
+ }
+
+ bufp += 4*len;
+ width -= len;
+ }
+}
+
+static void
+art_ksvg_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_ksvg_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+ const ArtKSVGGradientLinear *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->affine[0] + y * gradient->affine[2] + gradient->affine[4];
+ d_offset = gradient->affine[0];
+
+ 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_ksvg_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset, gradient->interpolation);
+ offset += d_offset;
+ bufp += pixstride;
+ }
+}
+
+static void
+art_ksvg_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
+ ArtImageSourceFlags *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+
+ if(render->depth == 8 &&
+ render->n_chan == 3 &&
+ z->gradient.interpolation == ART_KSVG_SRGB_INTERPOLATION)
+ {
+ /* The optimised renderer doesn't support linearRGB interpolation at the moment */
+ /* so we only use it for sRGB, which is more common anyway. */
+ self->super.render = art_ksvg_render_gradient_linear_render_8;
+ *p_flags = 0;
+ *p_buf_depth = 8;
+ *p_alpha = ART_ALPHA_SEPARATE;
+ return;
+ }
+
+ self->super.render = art_ksvg_render_gradient_linear_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_SEPARATE;
+}
+
+/**
+ * art_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_ksvg_render_gradient_linear (ArtRender *render,
+ const ArtKSVGGradientLinear *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradLin *image_source = art_alloc (sizeof (ArtImageSourceGradLin) +
+ sizeof (ArtGradientStop) * (gradient->n_stops - 1));
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_ksvg_render_gradient_linear_done;
+ image_source->super.negotiate = art_ksvg_render_gradient_linear_negotiate;
+
+ /* copy the gradient into the structure */
+ image_source->gradient = *gradient;
+ image_source->gradient.stops = image_source->stops;
+ memcpy (image_source->gradient.stops, gradient->stops, sizeof (ArtGradientStop) * gradient->n_stops);
+
+ art_render_add_image_source (render, &image_source->super);
+}
+
diff --git a/ksvg/impl/libs/art_support/art_render_misc.h b/ksvg/impl/libs/art_support/art_render_misc.h
new file mode 100644
index 00000000..d1f3690b
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_render_misc.h
@@ -0,0 +1,90 @@
+/* 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) 2001-2002 KSVG Team
+ *
+ * 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"
+#include "art_render_gradient.h"
+#else
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_render.h>
+#include <libart_lgpl/art_render_gradient.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum
+{
+ ART_KSVG_SRGB_INTERPOLATION,
+ ART_KSVG_LINEARRGB_INTERPOLATION
+} ArtKSVGGradientInterpolation;
+
+typedef struct _ArtKSVGGradientRadial ArtKSVGGradientRadial;
+
+struct _ArtKSVGGradientRadial {
+ 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;
+ ArtKSVGGradientInterpolation interpolation;
+};
+
+void
+art_ksvg_render_gradient_radial (ArtRender *render,
+ const ArtKSVGGradientRadial *gradient,
+ ArtFilterLevel level);
+
+typedef struct _ArtKSVGGradientLinear ArtKSVGGradientLinear;
+
+struct _ArtKSVGGradientLinear {
+ double affine[6]; /* transforms screen gradient vector to unit vector (1, 0) */
+ ArtGradientSpread spread;
+ int n_stops;
+ ArtGradientStop *stops;
+ ArtKSVGGradientInterpolation interpolation;
+};
+
+void
+art_ksvg_render_gradient_linear (ArtRender *render,
+ const ArtKSVGGradientLinear *gradient,
+ ArtFilterLevel level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_MISC_H__ */
diff --git a/ksvg/impl/libs/art_support/art_rgba_svp.c b/ksvg/impl/libs/art_support/art_rgba_svp.c
new file mode 100644
index 00000000..47c7d924
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_rgba_svp.c
@@ -0,0 +1,659 @@
+/* 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 <X11/Xos.h>
+
+#include "art_rgba_svp.h"
+
+#include <libart_lgpl/art_svp.h>
+#include <libart_lgpl/art_svp_render_aa.h>
+#include <libart_lgpl/art_rgba.h>
+#include <libart_lgpl/art_rgb.h>
+
+/* RGBA renderers */
+
+typedef struct _ArtKSVGRgbaSVPAlphaData ArtKSVGRgbaSVPAlphaData;
+
+struct _ArtKSVGRgbaSVPAlphaData {
+ int alphatab[256];
+ art_u8 r, g, b, alpha;
+ art_u32 rgba;
+ art_u8 *buf;
+ art_u8 *mask;
+ int rowstride;
+ int x0, x1;
+ int y0;
+};
+
+/**
+ * art_rgba_fill_run: fill an RGBA 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, solid
+ * alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
+ * (exclusive) are written.
+ **/
+static void
+art_ksvg_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+ int i;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ art_u32 src_rgba;
+#else
+ art_u32 src_abgr;
+#endif
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
+#else
+ src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
+#endif
+ for(i = 0; i < n; i++)
+ {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ ((art_u32 *)buf)[i] = src_rgba;
+#else
+ ((art_u32 *)buf)[i] = src_abgr;
+#endif
+ }
+}
+
+/**
+ * art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..255.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha. Note that the range of @alpha is 0..255, in contrast
+ * to art_rgb_run_alpha, which has a range of 0..256.
+ **/
+static void
+art_ksvg_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+ int v;
+ int tmp;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ for(i = 0; i < n; i++)
+ {
+ v = *buf;
+ tmp = (r - v) * alpha + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (g - v) * alpha + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (b - v) * alpha + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (255 - alpha) * v + 0x80;
+ *buf++ = alpha + ((tmp + (tmp >> 8)) >> 8);
+ }
+}
+
+static void
+art_ksvg_rgba_mask_run_alpha (art_u8 *buf, art_u8 *mask, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+ int v;
+ int am;
+ int tmp;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ for(i = 0; i < n; i++)
+ {
+ am = (alpha * *mask++) + 0x80;
+ am = (am + (am >> 8)) >> 8;
+
+ v = *buf;
+ tmp = (r - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (g - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (b - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (255 - am) * v + 0x80;
+ *buf++ = am + ((tmp + (tmp >> 8)) >> 8);
+ }
+}
+
+static void
+art_ksvg_rgba_svp_alpha_callback(void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtKSVGRgbaSVPAlphaData *data = (ArtKSVGRgbaSVPAlphaData *)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_ksvg_rgba_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_ksvg_rgba_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_ksvg_rgba_run_alpha (linebuf + (run_x1 - x0) * 4,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_ksvg_rgba_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+
+ data->buf += data->rowstride;
+}
+
+static void
+art_ksvg_rgba_svp_alpha_opaque_callback(void *callback_data, int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtKSVGRgbaSVPAlphaData *data = (ArtKSVGRgbaSVPAlphaData *)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 rgba;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ rgba = data->rgba;
+ 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_ksvg_rgba_fill_run (linebuf,
+ r, g, b,
+ run_x1 - x0);
+ else
+ art_ksvg_rgba_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_ksvg_rgba_fill_run (linebuf + (run_x0 - x0) * 4,
+ r, g, b,
+ run_x1 - run_x0);
+ else
+ art_ksvg_rgba_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_ksvg_rgba_fill_run (linebuf + (run_x1 - x0) * 4,
+ r, g, b,
+ x1 - run_x1);
+ else
+ art_ksvg_rgba_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_ksvg_rgba_fill_run (linebuf,
+ r, g, b,
+ x1 - x0);
+ else
+ art_ksvg_rgba_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+ }
+ data->buf += data->rowstride;
+}
+
+static void
+art_ksvg_rgba_svp_alpha_mask_callback(void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtKSVGRgbaSVPAlphaData *data = (ArtKSVGRgbaSVPAlphaData *)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;
+ art_u8 *maskbuf;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ alphatab = data->alphatab;
+
+ maskbuf = data->mask + (y - data->y0) * (data->x1 - data->x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ art_ksvg_rgba_mask_run_alpha (linebuf, maskbuf,
+ 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_ksvg_rgba_mask_run_alpha (linebuf + (run_x0 - x0) * 4, maskbuf + (run_x0 - x0),
+ 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_ksvg_rgba_mask_run_alpha (linebuf + (run_x1 - x0) * 4, maskbuf + (run_x1 - x0) ,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ art_ksvg_rgba_mask_run_alpha (linebuf, maskbuf,
+ 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_ksvg_rgba_svp_alpha(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma,
+ art_u8 *mask)
+{
+ ArtKSVGRgbaSVPAlphaData data;
+ int r, g, b;
+ int i;
+ int a, da;
+ int alpha;
+
+ r = (rgba >> 24) & 0xff;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+ alpha = rgba & 0xff;
+
+ data.r = r;
+ data.g = g;
+ data.b = b;
+ data.alpha = alpha;
+ data.rgba = rgba;
+ data.mask = mask;
+
+ 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;
+ data.y0 = y0;
+
+ if(mask)
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_ksvg_rgba_svp_alpha_mask_callback, &data);
+ else
+ {
+ if (alpha == 255)
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_ksvg_rgba_svp_alpha_opaque_callback, &data);
+ else
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_ksvg_rgba_svp_alpha_callback, &data);
+ }
+}
+
+/* RGB renderers */
+
+static void
+art_ksvg_rgb_mask_run_alpha(art_u8 *buf, art_u8 *mask, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+ int v;
+ int am;
+ int tmp;
+
+ if(alpha > 255)
+ alpha = 255;
+
+ for(i = 0; i < n; i++)
+ {
+ am = (alpha * *mask++) + 0x80;
+ am = (am + (am >> 8)) >> 8;
+
+ v = *buf;
+ tmp = (r - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (g - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+
+ v = *buf;
+ tmp = (b - v) * am + 0x80;
+ *buf++ = v + ((tmp + (tmp >> 8)) >> 8);
+ }
+}
+
+static void
+art_ksvg_rgb_svp_alpha_mask_callback(void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtKSVGRgbaSVPAlphaData *data = (ArtKSVGRgbaSVPAlphaData *)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;
+ art_u8 *maskbuf;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ alphatab = data->alphatab;
+
+ maskbuf = data->mask + (y - data->y0) * (data->x1 - data->x0);
+
+ if(n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if(run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ art_ksvg_rgb_mask_run_alpha (linebuf, maskbuf,
+ 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_ksvg_rgb_mask_run_alpha (linebuf + (run_x0 - x0) * 3, maskbuf + (run_x0 - x0),
+ 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_ksvg_rgb_mask_run_alpha (linebuf + (run_x1 - x0) * 3, maskbuf + (run_x1 - x0) ,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if(alpha)
+ art_ksvg_rgb_mask_run_alpha (linebuf, maskbuf,
+ 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_ksvg_rgb_svp_alpha_mask(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma,
+ art_u8 *mask)
+{
+ ArtKSVGRgbaSVPAlphaData data;
+ int r, g, b, alpha;
+ int i;
+ int a, da;
+
+ r = rgba >> 24;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+ alpha = rgba & 0xff;
+
+ data.r = r;
+ data.g = g;
+ data.b = b;
+ data.alpha = alpha;
+ data.mask = mask;
+
+ 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;
+ data.y0 = y0;
+
+ art_svp_render_aa(svp, x0, y0, x1, y1, art_ksvg_rgb_svp_alpha_mask_callback, &data);
+}
+
diff --git a/ksvg/impl/libs/art_support/art_rgba_svp.h b/ksvg/impl/libs/art_support/art_rgba_svp.h
new file mode 100644
index 00000000..b59096d4
--- /dev/null
+++ b/ksvg/impl/libs/art_support/art_rgba_svp.h
@@ -0,0 +1,57 @@
+/* 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_RGBA_SVP_H__
+#define __ART_RGBA_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_ksvg_rgba_svp_alpha(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma,
+ art_u8 *mask);
+
+void
+art_ksvg_rgb_svp_alpha_mask(const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma,
+ art_u8 *mask);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RGB_SVP_H__ */
diff --git a/ksvg/impl/libs/libtext2path/AUTHORS b/ksvg/impl/libs/libtext2path/AUTHORS
new file mode 100644
index 00000000..efa499dd
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/AUTHORS
@@ -0,0 +1 @@
+Nikolas Zimmermann <wildfox@kde.org>
diff --git a/ksvg/impl/libs/libtext2path/COPYING b/ksvg/impl/libs/libtext2path/COPYING
new file mode 100644
index 00000000..0b84a43f
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ksvg/impl/libs/libtext2path/ChangeLog b/ksvg/impl/libs/libtext2path/ChangeLog
new file mode 100644
index 00000000..fad2a19b
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/ChangeLog
@@ -0,0 +1,2 @@
+Fri Jul 25 08:30:43 CEST 2003 - Nikolas Zimmermann <wildfox@kde.org>
+ o Initial Creation
diff --git a/ksvg/impl/libs/libtext2path/INSTALL b/ksvg/impl/libs/libtext2path/INSTALL
new file mode 100644
index 00000000..28fadaa7
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/INSTALL
@@ -0,0 +1,181 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/ksvg/impl/libs/libtext2path/Makefile.am b/ksvg/impl/libs/libtext2path/Makefile.am
new file mode 100644
index 00000000..c7f2f390
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/Makefile.am
@@ -0,0 +1,7 @@
+SUBDIRS = src
+DIST_SUBDIRS = src
+
+#pkgconfigdir = $(libdir)/pkgconfig
+#kgconfig_DATA = libtext2path-0.1.pc
+
+#EXTRA_DIST = autogen.sh
diff --git a/ksvg/impl/libs/libtext2path/NEWS b/ksvg/impl/libs/libtext2path/NEWS
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/NEWS
@@ -0,0 +1 @@
+
diff --git a/ksvg/impl/libs/libtext2path/README b/ksvg/impl/libs/libtext2path/README
new file mode 100644
index 00000000..b9493b88
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/README
@@ -0,0 +1,4 @@
+libtext2path v0.1
+Nikolas Zimmermann <wildfox@kde.org>
+----------------------------------------------------------------------
+TODO: Write documentation! :)
diff --git a/ksvg/impl/libs/libtext2path/VERSION b/ksvg/impl/libs/libtext2path/VERSION
new file mode 100644
index 00000000..6c2cb464
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/VERSION
@@ -0,0 +1 @@
+libtext2path-0.1
diff --git a/ksvg/impl/libs/libtext2path/configure.in.in b/ksvg/impl/libs/libtext2path/configure.in.in
new file mode 100644
index 00000000..2198ab52
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/configure.in.in
@@ -0,0 +1,41 @@
+#AC_INIT(src/Converter.h)
+#AM_CONFIG_HEADER(config.h)
+
+dnl -----------------------------------------------
+dnl Package name and version number (user defined)
+dnl -----------------------------------------------
+GENERIC_LIBRARY_NAME=libtext2path-0.1
+
+# release versioning
+GENERIC_MAJOR_VERSION=0
+GENERIC_MINOR_VERSION=1
+GENERIC_MICRO_VERSION=0
+
+# API version (often = GENERIC_MAJOR_VERSION.GENERIC_MINOR_VERSION)
+GENERIC_API_VERSION=0.1
+AC_SUBST(GENERIC_API_VERSION)
+
+#shared library versioning
+GENERIC_LIBRARY_VERSION=0:1:0
+
+dnl --------------------------------
+dnl Package name and version number
+dnl --------------------------------
+AC_SUBST(GENERIC_LIBRARY_VERSION)
+
+AC_SUBST(GENERIC_LIBRARY_NAME)
+
+GENERIC_VERSION=$GENERIC_MAJOR_VERSION.$GENERIC_MINOR_VERSION.$GENERIC_MICRO_VERSION
+GENERIC_RELEASE=$GENERIC_MAJOR_VERSION.$GENERIC_MINOR_VERSION
+AC_SUBST(GENERIC_RELEASE)
+AC_SUBST(GENERIC_VERSION)
+
+
+dnl -----------------------------------------------
+dnl Checks for programs.
+dnl -----------------------------------------------
+
+dnl Check for fontconfig
+# PKG_CHECK_MODULES(DEPS, fontconfig >= 2.2.0)
+#AC_SUBST(DEPS_CFLAGS)
+#AC_SUBST(DEPS_LIBS)
diff --git a/ksvg/impl/libs/libtext2path/libtext2path.lsm b/ksvg/impl/libs/libtext2path/libtext2path.lsm
new file mode 100644
index 00000000..7407a0ff
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/libtext2path.lsm
@@ -0,0 +1,16 @@
+Begin4
+Title: libtext2path -- Some description
+Version: 0.1
+Entered-date: YYYY-MM-DD
+Description:
+Keywords: KDE3 Qt
+Author: Nikolas Zimmermann <wildfox@kde.org>
+Maintained-by: Nikolas Zimmermann <wildfox@kde.org>
+Home-page:
+Alternate-site:
+Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils
+ xxxxxx libtext2path-0.1.tar.gz
+ xxx libtext2path-0.1.lsm
+Platform: Linux. Needs KDE 2.x
+Copying-policy: GPL
+End
diff --git a/ksvg/impl/libs/libtext2path/libtext2path.pc.in b/ksvg/impl/libs/libtext2path/libtext2path.pc.in
new file mode 100644
index 00000000..1d4b4210
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/libtext2path.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libtext2path
+Description: Converts FreeType glyphs to bezier paths
+Version: @VERSION@
+Libs: -L${libdir} -ltext2path
+Cflags: -I${includedir}/@GENERIC_LIBRARY_NAME@ -I${libdir}/@GENERIC_LIBRARY_NAME@/include
+
diff --git a/ksvg/impl/libs/libtext2path/libtext2path.spec b/ksvg/impl/libs/libtext2path/libtext2path.spec
new file mode 100644
index 00000000..e0c217bd
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/libtext2path.spec
@@ -0,0 +1,41 @@
+%define distversion %( perl -e 'Creating /home/nikoz/Projects/libtext2path/libtext2path.spec...=\<\>;/(\d+)\.(\d)\.?(\d)?/; print "".(||0)' /etc/*-release)
+Name: libtext2path
+Summary: libtext2path -- Some description
+Version: 0.1
+Release: %{_vendor}_%{distversion}
+Copyright: GPL
+Group: X11/KDE/Utilities
+Source: ftp://ftp.kde.org/pub/kde/unstable/apps/utils/%{name}-%{version}.tar.gz
+Packager: Nikolas Zimmermann <wildfox@kde.org>
+BuildRoot: /tmp/%{name}-%{version}
+Prefix: /usr/kde/cvs
+
+%description
+A long description
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+%setup -n %{name}-%{version}
+CFLAGS="" CXXFLAGS="" ./configure --disable-debug --enable-final --prefix=%{prefix}
+
+%build
+# Setup for parallel builds
+numprocs=1
+if [ "" = "0" ]; then
+ numprocs=1
+fi
+
+make -j
+
+%install
+make install-strip DESTDIR=$RPM_BUILD_ROOT
+
+cd
+find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > /%{name}-master.list
+find . -type f -o -type l | sed 's|^\.||' >> $RPM_BUILD_DIR/%{name}-master.list
+
+%clean
+rm -rf $RPM_BUILD_DIR/%{name}-%{version}
+rm -rf $RPM_BUILD_DIR/-master.list
+
+%files -f $RPM_BUILD_DIR/%{name}-master.list
diff --git a/ksvg/impl/libs/libtext2path/src/Affine.cpp b/ksvg/impl/libs/libtext2path/src/Affine.cpp
new file mode 100644
index 00000000..d06b53bc
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Affine.cpp
@@ -0,0 +1,174 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include <math.h>
+
+#include "Point.h"
+#include "Affine.h"
+
+using namespace T2P;
+
+Affine::Affine()
+{
+ m_affine[0] = 1.0;
+ m_affine[1] = 0.0;
+ m_affine[2] = 0.0;
+ m_affine[3] = 1.0;
+ m_affine[4] = 0.0;
+ m_affine[5] = 0.0;
+}
+
+Affine::Affine(double affine[6])
+{
+ for(int i = 0; i < 6; i++)
+ m_affine[i] = affine[i];
+}
+
+Affine::Affine(const Affine &other)
+{
+ (*this) = other;
+}
+
+Affine::Affine(double m11, double m12, double m21, double m22, double dx, double dy)
+{
+ m_affine[0] = m11; m_affine[1] = m12; m_affine[2] = m21;
+ m_affine[3] = m22; m_affine[4] = dx; m_affine[5] = dy;
+}
+
+Affine::~Affine()
+{
+}
+
+Affine &Affine::operator*=(Affine &other)
+{
+ double d0 = m11() * other.m11() + m12() * other.m21();
+ double d1 = m11() * other.m12() + m12() * other.m22();
+ double d2 = m21() * other.m11() + m22() * other.m21();
+ double d3 = m21() * other.m12() + m22() * other.m22();
+ double d4 = dx() * other.m11() + dy() * other.m21() + other.dx();
+ double d5 = dx() * other.m12() + dy() * other.m22() + other.dy();
+
+ m_affine[0] = d0; m_affine[1] = d1; m_affine[2] = d2;
+ m_affine[3] = d3; m_affine[4] = d4; m_affine[5] = d5;
+
+ return *this;
+}
+
+Affine &Affine::operator=(const Affine &other)
+{
+ for(int i = 0; i < 6; i++)
+ m_affine[i] = other.m_affine[i];
+
+ return *this;
+}
+
+double &Affine::m11()
+{
+ return m_affine[0];
+}
+
+double &Affine::m12()
+{
+ return m_affine[1];
+}
+
+double &Affine::m21()
+{
+ return m_affine[2];
+}
+
+double &Affine::m22()
+{
+ return m_affine[3];
+}
+
+double &Affine::dx()
+{
+ return m_affine[4];
+}
+
+double &Affine::dy()
+{
+ return m_affine[5];
+}
+
+void Affine::scale(double s)
+{
+ scale(s, s);
+}
+
+void Affine::scale(double sx, double sy)
+{
+ m_affine[0] = sx;
+ m_affine[3] = sy;
+}
+
+void Affine::translate(const Point &point)
+{
+ m_affine[4] += point.x();
+ m_affine[5] += point.y();
+}
+
+void Affine::translate(double tx, double ty)
+{
+ m_affine[4] += tx * m_affine[0] + ty * m_affine[2];
+ m_affine[5] += tx * m_affine[1] + ty * m_affine[3];
+}
+
+void Affine::rotate(double angle)
+{
+ double sina = sin(angle);
+ double cosa = cos(angle);
+
+ double tm11 = cosa * m_affine[0] + sina * m_affine[2];
+ double tm12 = cosa * m_affine[1] + sina * m_affine[3];
+ double tm21 = -sina * m_affine[0] + cosa * m_affine[2];
+ double tm22 = -sina * m_affine[1] + cosa * m_affine[3];
+
+ m_affine[0] = tm11; m_affine[1] = tm12;
+ m_affine[2] = tm21; m_affine[3] = tm22;
+}
+
+void Affine::rotateAround(double angle, const Point &point)
+{
+ translate(point);
+ rotate(angle);
+ translate(point.invert());
+}
+
+void Affine::rotateAround(double angle, double cx, double cy)
+{
+ translate(-cx, -cy);
+ rotate(angle);
+ translate(cx, cy);
+}
+
+Point Affine::mapPoint(const Point &p) const
+{
+ return Point(p.x() * m_affine[0] + p.y() * m_affine[2] + m_affine[4],
+ p.x() * m_affine[1] + p.y() * m_affine[3] + m_affine[5]);
+}
+
+double *Affine::data()
+{
+ return m_affine;
+}
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Affine.h b/ksvg/impl/libs/libtext2path/src/Affine.h
new file mode 100644
index 00000000..c0f11e9b
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Affine.h
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_AFFINE_H
+#define T2P_AFFINE_H
+
+namespace T2P
+{
+ class Point;
+ class Affine
+ {
+ public:
+ Affine();
+ Affine(double affine[6]);
+ Affine(const Affine &other);
+ Affine(double m11, double m12, double m21, double m22, double dx, double dy);
+ ~Affine();
+
+ Affine &operator*=(Affine &other);
+ Affine &operator=(const Affine &other);
+
+ double &m11();
+ double &m12();
+ double &m21();
+ double &m22();
+ double &dx();
+ double &dy();
+
+ void scale(double s);
+ void scale(double sx, double sy);
+ void translate(const Point &point); // Assumes point is already transformed
+ void translate(double tx, double ty);
+
+ void rotate(double angle);
+ void rotateAround(double angle, const Point &point); // Assumes point is already transformed
+ void rotateAround(double angle, double cx, double cy);
+
+ Point mapPoint(const Point &p) const;
+
+ // Internal
+ double *data();
+
+ private:
+ double m_affine[6];
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/BezierPath.h b/ksvg/impl/libs/libtext2path/src/BezierPath.h
new file mode 100644
index 00000000..1c357abd
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/BezierPath.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_BEZIERPATH_H
+#define T2P_BEZIERPATH_H
+
+#include <list>
+
+namespace T2P
+{
+ class Point;
+ class BezierPath
+ {
+ public:
+ BezierPath() { }
+ virtual ~BezierPath() { }
+
+ /**
+ * Calculates the arclength from p0 to the point parametrized by 0 <= t <= 1.
+ */
+ virtual double length(double t = 1.0) = 0;
+
+ /**
+ * Calculates the point, the tangent vector and the normal vector for
+ * 0 <= t <= 1. The tangent vector and the normal vector are
+ * normalized (length=1).
+ */
+ virtual void pointTangentNormalAt(double t, Point *p = 0, Point *tn = 0, Point *n = 0) = 0;
+
+ /**
+ * Calculates the axis-aligned bounding box.
+ */
+ virtual void boundingBox(Point *topLeft, Point *bottomRight) = 0;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Cache.h b/ksvg/impl/libs/libtext2path/src/Cache.h
new file mode 100644
index 00000000..a85fdf92
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Cache.h
@@ -0,0 +1,156 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_CACHE_H
+#define T2P_CACHE_H
+
+#include <map>
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "myboost/shared_ptr.hpp"
+
+namespace T2P
+{
+ class CacheElement
+ {
+ public:
+ CacheElement(std::string key) : m_key(key), m_usage(0) { }
+ ~CacheElement() { }
+
+ std::string key() const { return m_key; }
+ int usage() const { return m_usage; }
+
+ void incUsage() { m_usage++; }
+
+ private:
+ std::string m_key;
+ int m_usage;
+ };
+
+ template<typename T>
+ class Cache
+ {
+ public:
+ typedef myboost::shared_ptr<T> SharedT;
+
+ Cache(int maxSize = 10) : m_size(0), m_maxSize(maxSize) { }
+ ~Cache() { clear(); }
+
+ // Number of elements in cache
+ int size() const { return m_size; }
+
+ // Maximum number of elements in cache
+ int maxSize() const { return m_maxSize; }
+
+ // Add new entry
+ void insert(const std::string &key, SharedT &value)
+ {
+ // TODO: Add real LRU logic, now i will just delete the less
+ // used item when inserting a new item would exceed maxSize
+ if(m_size == m_maxSize)
+ {
+ // Find less used item
+ typename std::map<SharedT, CacheElement *>::const_iterator it = m_cacheMap.begin();
+ int usage = (*it).second->usage(); std::string keyUsage = (*it).second->key();
+ for(it++; it != m_cacheMap.end(); ++it)
+ {
+ int curUsage = (*it).second->usage();
+ if(curUsage < usage)
+ {
+ usage = curUsage;
+ keyUsage = (*it).second->key();
+ }
+ }
+
+// std::cout << "[CACHE] Removing less used element with key: " << keyUsage << " (Used " << usage << " times!)" << std::endl;
+ remove(keyUsage);
+ }
+
+ m_size++;
+ m_entries.push_back(value);
+ m_cacheMap[value] = new CacheElement(key);
+ }
+
+ // Remove single entry
+ void remove(const std::string &key)
+ {
+ for(typename std::vector<SharedT>::iterator it = m_entries.begin(); it != m_entries.end(); ++it)
+ {
+ SharedT cur = *it;
+ if(m_cacheMap[cur]->key() == key)
+ {
+ m_size--;
+
+ typename std::map<SharedT, CacheElement *>::iterator cacheElement = m_cacheMap.find(cur);
+ m_cacheMap.erase(cacheElement);
+ delete cacheElement->second;
+ m_entries.erase(it); // Only valid to write because we don't go on here!
+ break; // Otherwhise the iterators _may_ be invalid!
+ }
+ }
+ }
+
+ // Remove all entries
+ void clear()
+ {
+ m_size = 0;
+ m_entries.clear();
+ m_cacheMap.clear();
+ }
+
+ // Lookup entry
+ SharedT find(const std::string &key)
+ {
+ for(typename std::vector<SharedT>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it)
+ {
+ SharedT cur = *it;
+ if(m_cacheMap[cur]->key() == key)
+ {
+ m_cacheMap[cur]->incUsage();
+ return cur;
+ }
+ }
+
+ return SharedT();
+ }
+
+ void dump()
+ {
+ std::cout << "[CACHE] " << size() << " of " << maxSize() << " Objects in the cache." << std::endl;
+
+ for(typename std::vector<SharedT>::iterator it = m_entries.begin(); it != m_entries.end(); ++it)
+ {
+ SharedT cur = *it;
+ std::cout << "[CACHE] - " << m_cacheMap[cur]->key() << " -> " << cur << " (Usage: " << m_cacheMap[cur]->usage() << ")" << std::endl;
+ }
+ }
+
+ private:
+ std::vector<SharedT> m_entries;
+ std::map<SharedT, CacheElement *> m_cacheMap;
+ int m_size, m_maxSize;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Converter.cpp b/ksvg/impl/libs/libtext2path/src/Converter.cpp
new file mode 100644
index 00000000..7810b417
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Converter.cpp
@@ -0,0 +1,505 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include <math.h>
+
+#include "myboost/shared_ptr.hpp"
+#include <fontconfig/fontconfig.h>
+#include <fribidi/fribidi.h>
+#include <fribidi/fribidi_types.h>
+
+#include "Font.h"
+#include "Glyph.h"
+#include "Tools.h"
+#include "Rectangle.h"
+#include "Converter.h"
+#include "QtUnicode.h"
+#include "GlyphTracer.h"
+
+// Macros
+#define FT_TRUNC(x) ((x) >> 6)
+#define FT_TOFLOAT(x) ((x) * (1.0 / 64.0))
+#define FT_FROMFLOAT(x) ((int) floor ((x) * 64.0 + 0.5))
+
+const double deg2rad = 0.017453292519943295769; // pi/180
+
+using namespace T2P;
+
+// Font engine. The core component.
+Converter::Converter(GlyphTracer *tracer) : m_glyphTracer(tracer)
+{
+ m_init = false;
+ m_kerning = true;
+ m_library = 0;
+}
+
+Converter::~Converter()
+{
+ if(m_glyphTracer)
+ delete m_glyphTracer;
+
+ m_fontCache.clear();
+ m_glyphCache.clear();
+
+ // Close FreeType2 library
+ if(m_library)
+ FT_Done_FreeType(m_library);
+}
+
+void Converter::init()
+{
+ // Initialize FreeType2
+ m_init = (FT_Init_FreeType(&m_library) == 0);
+}
+
+bool Converter::ready()
+{
+ return m_init;
+}
+
+void Converter::setKerning(bool mode)
+{
+ m_kerning = mode;
+}
+
+// Lookup font in cache or create new font
+SharedFont Converter::requestFont(const FontVisualParams *params)
+{
+ std::string cacheKey = cacheFontKey(params);
+ SharedFont cached = m_fontCache.find(cacheKey);
+
+ // If not available in cache, create new one and cache it :)
+ if(cached)
+ {
+ delete params;
+ return cached;
+ }
+ else
+ {
+ // Create a new Font
+ SharedFont newFont(new Font(this));
+
+ // Load the font
+ if(!newFont->load(params))
+ {
+ delete params;
+ return SharedFont();
+ }
+
+ // Append to cache
+ m_fontCache.insert(cacheKey, newFont);
+ return newFont;
+ }
+}
+
+GlyphAffinePair *Converter::requestGlyph(GlyphRenderParams *params, Rectangle &bbox, Affine &affine, bool onlyLatin)
+{
+ // 1. Select glyph to have glyphIndex information,
+ // needed to generate the cache lookup key
+ selectGlyph(params);
+
+ SharedGlyph cached = m_glyphCache.find(cacheGlyphKey(params));
+
+ // If not available in cache, render new one and cache it :)
+ // If we're mixing ie. japanese and latin characters (TTB layout),
+ // then we also have to re-calculate the glyph again with the appropriate rotation matrix (Niko)
+ if(!cached || !onlyLatin)
+ cached = calcGlyph(params, affine, onlyLatin);
+
+ // Correct bezier path by setting up the correct scaling matrix
+ // and multiplying with the current glyph affine
+ double fontSize = params->font()->fontParams()->size();
+
+ T2P::Affine correctAffine;
+ correctAffine.scale(0.001 * fontSize, -0.001 * fontSize);
+ correctAffine *= affine;
+
+ // Get bbox information
+ Point p1(FT_TRUNC(cached->ftBbox()->xMin), FT_TRUNC(cached->ftBbox()->yMin));
+ Point p2(FT_TRUNC(cached->ftBbox()->xMax), FT_TRUNC(cached->ftBbox()->yMax));
+
+ bbox.setA(affine.mapPoint(p1));
+ bbox.setB(affine.mapPoint(p2));
+
+ return new GlyphAffinePair(cached.get(), correctAffine);
+}
+
+void Converter::selectGlyph(GlyphRenderParams *params)
+{
+ // 1. Select glyph + test if it exists
+ // |
+ // |-> if it doesn't exist, replace by a '?' and check if exists
+ // |-> if it does exist, use it!
+ params->setGlyphIndex(FT_Get_Char_Index(params->font()->fontFace(), (FT_ULong) params->character()));
+
+ if(params->glyphIndex() == 0)
+ params->setGlyphIndex(FT_Get_Char_Index(params->font()->fontFace(), '?'));
+
+ // 2. Load glyph into font's glyphSlot, according to the GlyphLayoutParams
+ int flags = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
+
+ // 3. Don't pass FT_LOAD_VERTICAL_LAYOUT on TTB layouts when rendering
+ // a latin glyph because it needs to be rotated...
+ if(params->layout()->tb())
+ {
+ Script script;
+ SCRIPT_FOR_CHAR(script, params->character())
+ if(script != Latin || params->layout()->glyphOrientationVertical() == 0)
+ flags |= FT_LOAD_VERTICAL_LAYOUT;
+ }
+
+ FT_Error error = FT_Load_Glyph(params->font()->fontFace(), params->glyphIndex(), flags);
+ if(error)
+ params->setGlyphIndex(0);
+}
+
+SharedGlyph Converter::calcGlyph(const GlyphRenderParams *params, Affine &affine, bool onlyLatin)
+{
+ // 2. Apply kerning if needed
+ if(m_kerning && params->lastGlyph() != 0 && params->glyphIndex() != 0)
+ {
+ FT_Vector kerningVector;
+ double kx, ky;
+
+ FT_Get_Kerning(params->font()->fontFace(), params->lastGlyph(), params->glyphIndex(), ft_kerning_default, &kerningVector);
+
+ kx = FT_TRUNC(kerningVector.x);
+ ky = FT_TRUNC(kerningVector.y);
+
+ affine.dx() += kx + affine.m21() * ky;
+
+ // Only apply y kerning in TB mode
+ if(params->layout()->tb())
+ affine.dy() += kx + affine.m22() * ky;
+ }
+
+ // 3. Prepare path tracing
+ FT_OutlineGlyph ftGlyph;
+ FT_Get_Glyph(params->font()->fontFace()->glyph, reinterpret_cast<FT_Glyph *>(&ftGlyph));
+
+ // 3a. Prepare tracing matrix
+ Affine traceAffine;
+ traceAffine.scale(1000.0 / params->font()->fontFace()->units_per_EM);
+
+ // 3b. Enable character rotation, if needed
+ if(params->layout()->tb())
+ {
+ Script script;
+ SCRIPT_FOR_CHAR(script, params->character())
+ if(!onlyLatin && script == Latin)
+ {
+ FT_Matrix matrix;
+
+ double angle = deg2rad * params->layout()->glyphOrientationVertical();
+ matrix.xx = (FT_Fixed)( cos(angle) * 0x10000L);
+ matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
+ matrix.yx = (FT_Fixed)( sin(angle) * 0x10000L);
+ matrix.yy = (FT_Fixed)( cos(angle) * 0x10000L);
+
+ FT_Glyph_Transform(reinterpret_cast<FT_Glyph>(ftGlyph), &matrix, 0);
+ }
+ }
+
+ // 4. Begin path tracing
+ // - Setup glyphOutlineing glyph
+ // - Start tracing
+ // - Close path
+ FT_Outline *ftOut = &ftGlyph->outline;
+
+ SharedGlyph glyphOutline(new Glyph());
+ glyphOutline->setBezierPath(m_glyphTracer->allocBezierPath(ftOut->n_points * 2 + ftOut->n_contours + 1));
+ glyphOutline->setAffine(traceAffine);
+
+ FT_Outline_Decompose(ftOut, m_glyphTracer->outlineFuncs(), glyphOutline.get());
+
+ m_glyphTracer->closePath(glyphOutline.get());
+
+ // 5. Determine bounding box (aka "cbox")
+ FT_Glyph_Get_CBox(reinterpret_cast<FT_Glyph>(ftGlyph), ft_glyph_bbox_unscaled, glyphOutline->ftBbox());
+
+ // 6. Cache glyph!
+ m_glyphCache.insert(cacheGlyphKey(params), glyphOutline);
+
+ FT_Done_Glyph(reinterpret_cast<FT_Glyph>(ftGlyph));
+
+ return glyphOutline;
+}
+
+GlyphSet *Converter::calcString(Font *font, const unsigned short *text, unsigned int length, Affine &affine, const GlyphLayoutParams *params, BezierPath *bpath)
+{
+ unsigned short *bidi = 0;
+
+ // 0. Apply BiDi Rules
+ if(params->useBidi())
+ {
+ FriBidiCharType baseDir = FRIBIDI_TYPE_N;
+ FriBidiChar *unicodeIn = new FriBidiChar[length + 1];
+ FriBidiChar *unicodeOut = new FriBidiChar[length + 1];
+ bidi = new unsigned short[length + 1];
+
+ for(unsigned int i = 0; i < length; i++)
+ unicodeIn[i] = text[i];
+
+ fribidi_log2vis(unicodeIn, length, &baseDir, unicodeOut, 0, 0, 0);
+
+ for(unsigned int i = 0; i < length; i++)
+ bidi[i] = unicodeOut[i];
+
+ bidi[length] = 0;
+ delete []unicodeIn;
+ delete []unicodeOut;
+ }
+ else
+ bidi = const_cast<unsigned short *>(text);
+
+ // Detect character rotation if needed,
+ // probably working in 0.1% of the cases :/
+ Script script;
+ bool onlyLatin = true;
+ for(unsigned int i = 0; i < length; i++)
+ {
+ SCRIPT_FOR_CHAR(script, bidi[i])
+ if(script != Latin)
+ {
+ onlyLatin = false;
+ break;
+ }
+ }
+
+ // 1. Set initial font size
+ double fontSize = font->fontParams()->size();
+ FT_Set_Char_Size(font->fontFace(), FT_FROMFLOAT(fontSize), FT_FROMFLOAT(fontSize), 0, 0);
+
+ // 2. Compute positioning metrics
+ // - See http://www.freetype.org/freetype2/docs/tutorial/stepX.html (X = 1 or 2)
+ int pixelHeight = (int) (FT_TOFLOAT(font->fontFace()->size->metrics.ascender - font->fontFace()->size->metrics.descender) * affine.m22());
+ int pixelBaseline = (int) (FT_TOFLOAT(font->fontFace()->size->metrics.ascender) * affine.m22());
+ int pixelUnderlinePosition = (int) (((font->fontFace()->ascender - font->fontFace()->underline_position - font->fontFace()->underline_thickness / 2) * fontSize / font->fontFace()->units_per_EM) * affine.m22());
+ int pixelUnderlineThickness = T2PMAX(1, (int) ((font->fontFace()->underline_thickness * fontSize / font->fontFace()->units_per_EM) * affine.m22()));
+
+ // 3. Prepare needed variables for the rendering loop
+ // - rendering params (layout, font...)
+ // - bounding box (per glyph, overall)
+ // - glyph matrix (overall)
+ // - resulting glyph sets
+ GlyphRenderParams *renderParams = new GlyphRenderParams();
+ renderParams->setFont(font);
+ renderParams->setLayout(params);
+ renderParams->setLastGlyph(0);
+ renderParams->setGlyphIndex(0);
+
+ Affine glyphAffine(affine);
+ Rectangle bbox, currentBbox;
+ GlyphSet *result = new GlyphSet();
+
+ // Align to path start, if bpath != 0
+ Point pathPoint, pathTangent, pathNormal;
+ double pathLength = 0, pathAdvance = 0;
+ double startOffset = params->textPathStartOffset();
+
+ if(bpath)
+ {
+ pathLength = bpath->length();
+ bpath->pointTangentNormalAt(startOffset, &pathPoint, &pathTangent);
+
+ glyphAffine.dx() = pathPoint.x();
+ glyphAffine.dy() = pathPoint.y();
+ glyphAffine.rotate(atan2(pathTangent.y(), pathTangent.x()));
+
+ std::cout << "[T2P] Starting textPath at: " << pathPoint.x() << ", " << pathPoint.y() << std::endl;
+ }
+
+ // <tspan> elements can have different baseline-shift's
+ // baseline-shift support (Niko)
+ double baseline = 0;
+ if(!params->baselineShift().empty())
+ {
+ if(params->baselineShift() == "sub")
+ baseline += fontSize / 5 + 1;
+ else if(params->baselineShift() == "super")
+ baseline -= fontSize / 3 + 1;
+ else
+ {
+ std::string temp = params->baselineShift();
+ if(temp.find("%") > 0)
+ baseline -= (atof(temp.c_str()) / 100.0) * fontSize;
+ else
+ baseline -= atoi(temp.c_str());
+ }
+
+ if(!params->tb())
+ glyphAffine.translate(0, baseline);
+ else
+ glyphAffine.translate(-baseline, 0);
+ }
+
+ // 4. Enter main rendering loop
+ for(unsigned int i = 0; i < length; i++)
+ {
+ // 4a. Modify character to render
+ renderParams->setCharacter(bidi[i]);
+
+ // 4c. Get glyph outline
+ GlyphAffinePair *glyphOutline = requestGlyph(renderParams, currentBbox, glyphAffine, onlyLatin);
+ m_glyphTracer->correctGlyph(glyphOutline);
+
+ // 4d. Save advance values
+ result->m_glyphXAdvance.push_back((font->fontFace()->glyph->advance.x * fontSize / font->fontFace()->units_per_EM) * affine.m11());
+ result->m_glyphYAdvance.push_back((font->fontFace()->glyph->advance.y * fontSize / font->fontFace()->units_per_EM) * affine.m22());
+
+ // 4e. Misc
+ // - union current + overall bounding box
+ // - add glyph to list of glyphs
+ // - apply letter & word spacing
+ if(renderParams->glyphIndex() != 0)
+ {
+ // Remember last glyph for kerning
+ renderParams->setLastGlyph(renderParams->glyphIndex());
+
+ // Union current + overall bounding box
+ bbox.bboxUnion(bbox, currentBbox);
+
+ // Move glyph locations for the next glyph to be
+ // rendered apply letter & word spacing
+ bool addGlyph = true;
+ if(!params->tb())
+ {
+ if(bpath)
+ {
+ double advance = startOffset + (pathAdvance / pathLength);
+ if(advance < 0.0 || advance > 1.0) // dont render off-path glyphs
+ addGlyph = false;
+
+ pathAdvance += (result->m_glyphXAdvance.back() + params->letterSpacing() * affine.m11()) + ((bidi[(i + 1)] == ' ') ? params->wordSpacing() * affine.m11() : 0);
+
+ std::cout << "[T2P] Adjusting textPath advance: " << pathAdvance << " Path Length: " << pathLength << " StartOffset: " << startOffset << " Position in Path (relative 0-1): " << pathAdvance/pathLength << " Adjusted by offset: " << startOffset + (pathAdvance / pathLength) << std::endl;
+
+ bpath->pointTangentNormalAt(startOffset + (pathAdvance / pathLength), &pathPoint, &pathTangent, &pathNormal);
+
+ glyphAffine.m11() = affine.m11();
+ glyphAffine.m12() = affine.m12();
+ glyphAffine.m21() = affine.m21();
+ glyphAffine.m22() = affine.m22();
+ glyphAffine.dx() = pathPoint.x();
+ glyphAffine.dy() = pathPoint.y();
+
+ glyphAffine.rotateAround(atan2(pathTangent.y(), pathTangent.x()), Point(result->m_glyphXAdvance.back() / 2, result->m_glyphYAdvance.back() / 2));
+
+ std::cout << "[T2P] Aligning textPath to: " << pathPoint.x() << ", " << pathPoint.y() << std::endl;
+ if(!params->tb())
+ glyphAffine.translate(0, baseline);
+ else
+ glyphAffine.translate(-baseline, 0);
+ }
+ else
+ glyphAffine.dx() += (result->m_glyphXAdvance.back() + params->letterSpacing() * affine.m11()) + ((bidi[(i + 1)] == ' ') ? params->wordSpacing() * affine.m11() : 0);
+ }
+ else
+ {
+ double advy = result->m_glyphYAdvance.back();
+
+ Script script;
+ SCRIPT_FOR_CHAR(script, bidi[i])
+ if(!onlyLatin && script == Latin && params->glyphOrientationVertical() != 0)
+ advy = result->m_glyphXAdvance.back();
+
+ glyphAffine.dy() += (advy + params->letterSpacing() * affine.m22()) + ((bidi[(i + 1)] == ' ') ? params->wordSpacing() * affine.m22() : 0);
+ }
+
+ // Copy bezier path/affine pair
+ if(addGlyph)
+ {
+ result->m_set.push_back(glyphOutline);
+ result->m_glyphCount++;
+ }
+ else
+ delete glyphOutline;
+ }
+ }
+
+ // 5. Fill out resulting data structures
+ result->m_underlinePosition = pixelUnderlinePosition;
+ result->m_overlinePosition = pixelHeight - pixelUnderlinePosition;
+ result->m_strikeThroughPosition = (result->m_underlinePosition + result->m_overlinePosition) / 2;
+ result->m_pixelBaseline = pixelBaseline;
+ result->m_underlineThickness = pixelUnderlineThickness;
+
+ result->m_xpen = glyphAffine.dx() - affine.dx();
+ result->m_ypen = glyphAffine.dy() - affine.dy();
+
+ result->m_bboxX = T2PMAX(1, int(bbox.a().x()));
+ result->m_bboxY = T2PMAX(1, int(bbox.a().y() - int(pixelHeight / 2)));
+ result->m_height = T2PMAX(1, int(bbox.b().y() - bbox.a().y()));
+
+ // Correct bounding box information also on
+ // vertical layouts! (Niko)
+ if(!params->tb())
+ {
+ if(bpath)
+ result->m_width = int(pathAdvance);
+ else
+ result->m_width = T2PMAX(1, int(bbox.b().x() - bbox.a().x()));
+ }
+ else
+ result->m_width = T2PMAX(1, pixelHeight);
+
+ // 6. Cleanup memory
+ if(text != bidi)
+ delete []bidi;
+
+ delete renderParams;
+
+ // 7. Eventually, dump cache statistics
+ // m_glyphCache.dump();
+ // m_fontCache.dump();
+
+ return result;
+}
+
+std::string Converter::cacheFontKey(const FontVisualParams *params) const
+{
+ // TODO: Tune the key
+ std::string key;
+
+ key += Tools::joinList('|', const_cast<FontVisualParams *>(params)->fontList());
+ key += Tools::a2str(params->weight());
+ key += Tools::a2str(params->slant());
+ key += Tools::a2str(params->size());
+
+ // std::cout << "Font cache key: " << key << std::endl;
+ return key;
+}
+
+std::string Converter::cacheGlyphKey(const GlyphRenderParams *params) const
+{
+ // TODO: Tune the key
+ std::string key;
+
+ key += params->font()->fontFile();
+ key += Tools::a2str(params->character());
+ key += Tools::a2str(params->glyphIndex());
+ key += Tools::a2str(params->font()->fontParams()->size());
+ key += Tools::a2str(params->font()->fontParams()->weight());
+ key += Tools::a2str(params->font()->fontParams()->slant());
+
+ // std::cout << "Glyph cache key: " << key << std::endl;
+ return key;
+}
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Converter.h b/ksvg/impl/libs/libtext2path/src/Converter.h
new file mode 100644
index 00000000..d6e19521
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Converter.h
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_CONVERTER_H
+#define T2P_CONVERTER_H
+
+#include "Cache.h"
+
+// FreeType 2 includes
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_GLYPH_H
+
+namespace T2P
+{
+ class BezierPath;
+
+ class Font;
+ class Glyph;
+ class Affine;
+ class GlyphSet;
+ class Rectangle;
+ class GlyphTracer;
+ class GlyphAffinePair;
+ class FontVisualParams;
+ class GlyphLayoutParams;
+ class GlyphRenderParams;
+
+ typedef myboost::shared_ptr<Font> SharedFont;
+ typedef myboost::shared_ptr<Glyph> SharedGlyph;
+
+ class Converter
+ {
+ public:
+ Converter(GlyphTracer *tracer);
+ ~Converter();
+
+ // Is initialized?
+ void init();
+ bool ready();
+
+ // Kerning control
+ void setKerning(bool mode);
+
+ SharedFont requestFont(const FontVisualParams *params);
+ GlyphAffinePair *requestGlyph(GlyphRenderParams *params, Rectangle &bbox, Affine &affine, bool onlyLatin);
+
+ GlyphSet *calcString(Font *font, const unsigned short *text, unsigned int length, Affine &affine, const GlyphLayoutParams *params, BezierPath *bpath = 0);
+ SharedGlyph calcGlyph(const GlyphRenderParams *params, Affine &affine, bool onlyLatin);
+
+ void selectGlyph(GlyphRenderParams *params);
+
+ protected:
+ friend class Font;
+
+ // Internal
+ FT_Library library() { return m_library; }
+
+ private:
+ std::string cacheFontKey(const FontVisualParams *params) const;
+ std::string cacheGlyphKey(const GlyphRenderParams *params) const;
+
+ FT_Library m_library;
+
+ GlyphTracer *m_glyphTracer;
+
+ Cache<Glyph> m_glyphCache;
+ Cache<Font> m_fontCache;
+
+ bool m_init, m_kerning;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Font.cpp b/ksvg/impl/libs/libtext2path/src/Font.cpp
new file mode 100644
index 00000000..1d6f7005
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Font.cpp
@@ -0,0 +1,252 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include <math.h>
+#include <iostream>
+#include <fontconfig/fontconfig.h>
+
+#include "Font.h"
+#include "Tools.h"
+#include "Converter.h"
+
+// Macros
+#define FT_TRUNC(x) ((x) >> 6)
+#define FT_TOFLOAT(x) ((x) * (1.0 / 64.0))
+#define FT_FROMFLOAT(x) ((int) floor ((x) * 64.0 + 0.5))
+
+using namespace T2P;
+
+FontVisualParams::FontVisualParams()
+{
+ m_size = 0.0;
+ m_slant = 0;
+ m_weight = 0;
+}
+
+FontVisualParams::FontVisualParams(const FontVisualParams &other)
+{
+ (*this) = other;
+}
+
+FontVisualParams::~FontVisualParams()
+{
+}
+
+FontVisualParams &FontVisualParams::operator=(const FontVisualParams &other)
+{
+ m_size = other.m_size;
+ m_slant = other.m_slant;
+ m_weight = other.m_weight;
+ m_fontList = other.m_fontList;
+
+ return *this;
+}
+
+void FontVisualParams::setWeight(int weight)
+{
+ m_weight = weight;
+}
+
+int FontVisualParams::weight() const
+{
+ return m_weight;
+}
+
+void FontVisualParams::setSlant(int slant)
+{
+ m_slant = slant;
+}
+
+int FontVisualParams::slant() const
+{
+ return m_slant;
+}
+
+void FontVisualParams::setSize(double size)
+{
+ m_size = size;
+}
+
+double FontVisualParams::size() const
+{
+ return m_size;
+}
+
+std::list<std::string> &FontVisualParams::fontList()
+{
+ return m_fontList;
+}
+
+// #####
+
+Font::Font(Converter *context) : m_context(context)
+{
+ m_ready = false;
+
+ m_fontFace = 0;
+ m_fontParams = 0;
+}
+
+Font::~Font()
+{
+ // Release font face
+ if(m_ready && m_fontFace)
+ {
+ // FIXME: Debug that!
+ //std::cout << "CALLING DONE FACE " << m_fontFace << std::endl;
+ FT_Done_Face(m_fontFace);
+ }
+
+ delete m_fontParams;
+}
+
+std::string Font::buildRequest(const FontVisualParams *fontParams, int &id)
+{
+ // Use FontConfig to locate & select fonts and use
+ // FreeType2 to open them
+ FcPattern *pattern;
+ std::string fileName;
+
+ pattern = FcPatternBuild(0,
+ FC_WEIGHT, FcTypeInteger, fontParams->weight(),
+ FC_SLANT, FcTypeInteger, fontParams->slant(),
+ FC_SIZE, FcTypeDouble, fontParams->size(),
+ NULL);
+
+ // Add multiple font names
+ std::list<std::string> &fontList = const_cast<FontVisualParams *>(fontParams)->fontList();
+
+ for(std::list<std::string>::const_iterator it = fontList.begin(); it != fontList.end(); ++it)
+ {
+ std::string string = *it;
+
+ if(!string.empty())
+ FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(string.c_str()));
+ }
+
+ // Always load vertical layout
+ FcPatternAddBool(pattern, FC_VERTICAL_LAYOUT, true);
+
+ // Disable hinting
+ FcPatternAddBool(pattern, FC_HINTING, false);
+
+ // Perform the default font pattern modification operations.
+ FcDefaultSubstitute(pattern);
+ FcConfigSubstitute(FcConfigGetCurrent(), pattern, FcMatchPattern);
+
+ // Match the pattern!
+ FcResult result;
+ FcPattern *match = FcFontMatch(0, pattern, &result);
+
+ // Destroy pattern
+ FcPatternDestroy(pattern);
+
+ // Get index & filename
+ FcChar8 *temp;
+
+ if(match)
+ {
+ FcPattern *pattern = FcPatternDuplicate(match);
+
+ // Get index & filename
+ if(FcPatternGetString(pattern, FC_FILE, 0, &temp) != FcResultMatch ||
+ FcPatternGetInteger(pattern, FC_INDEX, 0, &id) != FcResultMatch)
+ {
+ std::cout << "Font::buildRequest(), could not load font file for requested font \"" << Tools::joinList('|', fontList) << "\"" << std::endl;
+ return fileName;
+ }
+
+ fileName = reinterpret_cast<const char *>(temp);
+
+ // Kill pattern
+ FcPatternDestroy(pattern);
+ }
+
+ // Kill pattern
+ FcPatternDestroy(match);
+
+ return fileName;
+}
+
+bool Font::load(const FontVisualParams *fontParams)
+{
+ // Build FontConfig request pattern
+ int id = -1;
+ std::string filename = Font::buildRequest(fontParams, id);
+
+ // Load font directly using FreeType2
+ std::cout << "Font::load(), loading " << filename << " for requested font \"" << Tools::joinList('|', const_cast<FontVisualParams *>(fontParams)->fontList()) << "\"" << std::endl;
+
+ FT_Error error = FT_New_Face(m_context->library(), filename.c_str(), id, &m_fontFace);
+ if(error)
+ {
+ std::cout << "Font::load(), could not load font. Aborting!" << std::endl;
+ return false;
+ }
+ if(!FT_IS_SCALABLE(m_fontFace))
+ {
+ std::cout << "Font::load(), font does not contain outlines. Aborting!" << std::endl;
+ FT_Done_Face(m_fontFace);
+ m_fontFace = 0;
+ return false;
+ }
+
+ // Choose unicode charmap
+ for(int charmap = 0; charmap < m_fontFace->num_charmaps; charmap++)
+ {
+ if(m_fontFace->charmaps[charmap]->encoding == ft_encoding_unicode)
+ {
+ FT_Error error = FT_Set_Charmap(m_fontFace, m_fontFace->charmaps[charmap]);
+
+ if(error)
+ {
+ std::cout << "Font::load(), unable to select unicode charmap. Aborting!" << std::endl;
+
+ FT_Done_Face(m_fontFace);
+ m_fontFace = 0;
+
+ return false;
+ }
+ }
+ }
+
+ m_fontParams = fontParams;
+ m_fontFile = filename;
+ m_ready = true;
+
+ return true;
+}
+
+FT_Face &Font::fontFace()
+{
+ return m_fontFace;
+}
+
+std::string Font::fontFile() const
+{
+ return m_fontFile;
+}
+
+const FontVisualParams *Font::fontParams() const
+{
+ return m_fontParams;
+}
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Font.h b/ksvg/impl/libs/libtext2path/src/Font.h
new file mode 100644
index 00000000..72844285
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Font.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_FONT_H
+#define T2P_FONT_H
+
+#include <list>
+#include <string>
+
+// FreeType 2 includes
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace T2P
+{
+ class Converter;
+
+ class FontVisualParams
+ {
+ public:
+ FontVisualParams();
+ FontVisualParams(const FontVisualParams &other);
+ ~FontVisualParams();
+
+ FontVisualParams &operator=(const FontVisualParams &other);
+
+ void setWeight(int weight);
+ int weight() const;
+
+ void setSlant(int slant);
+ int slant() const;
+
+ void setSize(double size);
+ double size() const;
+
+ std::list<std::string> &fontList();
+
+ private:
+ int m_weight, m_slant;
+ double m_size;
+
+ std::list<std::string> m_fontList;
+ };
+
+ class Font
+ {
+ public:
+ Font(Converter *context);
+ ~Font();
+
+ // Build font loading request for FontConfig
+ static std::string buildRequest(const FontVisualParams *fontParams, int &id);
+
+ // Load it! :)
+ bool load(const FontVisualParams *fontParams);
+
+ FT_Face &fontFace();
+ std::string fontFile() const;
+ const FontVisualParams *fontParams() const;
+
+ private:
+ FT_Face m_fontFace;
+ std::string m_fontFile;
+
+ Converter *m_context;
+ const FontVisualParams *m_fontParams;
+
+ bool m_ready;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Glyph.cpp b/ksvg/impl/libs/libtext2path/src/Glyph.cpp
new file mode 100644
index 00000000..5d172018
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Glyph.cpp
@@ -0,0 +1,353 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include <iostream>
+#include "Glyph.h"
+
+using namespace T2P;
+
+Glyph::Glyph()
+{
+ m_bezierPath = 0;
+}
+
+Glyph::~Glyph()
+{
+ delete m_bezierPath;
+ m_bezierPath = 0;
+}
+
+Affine &Glyph::affine()
+{
+ return m_affine;
+}
+
+void Glyph::setAffine(const Affine &affine)
+{
+ m_affine = affine;
+}
+
+const BezierPath *Glyph::bezierPath() const
+{
+ return const_cast<const BezierPath *>(m_bezierPath);
+}
+
+BezierPath *Glyph::modifiableBezierPath()
+{
+ return m_bezierPath;
+}
+
+void Glyph::setBezierPath(const BezierPath *bpath)
+{
+ m_bezierPath = const_cast<BezierPath *>(bpath);
+}
+
+FT_BBox *Glyph::ftBbox()
+{
+ return m_ftBbox;
+}
+
+// #####
+
+GlyphAffinePair::GlyphAffinePair(const Glyph *glyph, const Affine &affine)
+{
+ m_glyph = glyph;
+ m_affine = affine;
+ m_transformatedPath = 0;
+}
+
+GlyphAffinePair::~GlyphAffinePair()
+{
+ // The glyphs are shared and thus not deleted (Niko)
+ delete m_transformatedPath;
+}
+
+void GlyphAffinePair::setTransformatedPath(const BezierPath *path)
+{
+ m_transformatedPath = path;
+}
+
+const BezierPath *GlyphAffinePair::transformatedPath() const
+{
+ return m_transformatedPath;
+}
+
+const Glyph *GlyphAffinePair::glyph() const
+{
+ return m_glyph;
+}
+
+Affine &GlyphAffinePair::affine()
+{
+ return m_affine;
+}
+
+// #####
+
+GlyphSet::GlyphSet()
+{
+ m_glyphCount = 0;
+
+ m_bboxX = 0;
+ m_bboxY = 0;
+ m_width = 0;
+ m_height = 0;
+
+ m_xpen = 0;
+ m_ypen = 0;
+
+ m_underlinePosition = 0;
+ m_underlineThickness = 0;
+ m_overlinePosition = 0;
+ m_strikeThroughPosition = 0;
+ m_pixelBaseline = 0;
+}
+
+GlyphSet::~GlyphSet()
+{
+ m_set.clear();
+}
+
+std::vector<GlyphAffinePair *> &GlyphSet::set()
+{
+ return m_set;
+}
+
+std::list<float> GlyphSet::glyphXAdvance()
+{
+ return m_glyphXAdvance;
+}
+
+std::list<float> GlyphSet::glyphYAdvance()
+{
+ return m_glyphYAdvance;
+}
+
+unsigned int GlyphSet::glyphCount() const
+{
+ return m_glyphCount;
+}
+
+int GlyphSet::width() const
+{
+ return m_width;
+}
+
+int GlyphSet::height() const
+{
+ return m_height;
+}
+
+int GlyphSet::bboxX() const
+{
+ return m_bboxX;
+}
+
+int GlyphSet::bboxY() const
+{
+ return m_bboxY;
+}
+
+double GlyphSet::xpen() const
+{
+ return m_xpen;
+}
+
+double GlyphSet::ypen() const
+{
+ return m_ypen;
+}
+
+int GlyphSet::underlinePosition() const
+{
+ return m_underlinePosition;
+}
+
+int GlyphSet::underlineThickness() const
+{
+ return m_underlineThickness;
+}
+
+int GlyphSet::overlinePosition() const
+{
+ return m_overlinePosition;
+}
+
+int GlyphSet::strikeThroughPosition() const
+{
+ return m_strikeThroughPosition;
+}
+
+int GlyphSet::pixelBaseline() const
+{
+ return m_pixelBaseline;
+}
+
+// #####
+
+GlyphLayoutParams::GlyphLayoutParams()
+{
+}
+
+GlyphLayoutParams::~GlyphLayoutParams()
+{
+}
+
+bool GlyphLayoutParams::tb() const
+{
+ return m_tb;
+}
+
+void GlyphLayoutParams::setTb(bool tb)
+{
+ m_tb = tb;
+}
+
+bool GlyphLayoutParams::useBidi() const
+{
+ return m_useBidi;
+}
+
+void GlyphLayoutParams::setUseBidi(bool bidi)
+{
+ m_useBidi = bidi;
+}
+
+double GlyphLayoutParams::wordSpacing() const
+{
+ return m_wordSpacing;
+}
+
+void GlyphLayoutParams::setWordSpacing(double wordSpacing)
+{
+ m_wordSpacing = wordSpacing;
+}
+
+double GlyphLayoutParams::letterSpacing() const
+{
+ return m_letterSpacing;
+}
+
+void GlyphLayoutParams::setLetterSpacing(double letterSpacing)
+{
+ m_letterSpacing = letterSpacing;
+}
+
+std::string GlyphLayoutParams::baselineShift() const
+{
+ return m_baseline;
+}
+
+void GlyphLayoutParams::setBaselineShift(const std::string &baseline)
+{
+ m_baseline = baseline;
+}
+
+int GlyphLayoutParams::glyphOrientationVertical() const
+{
+ return m_glyphOrientationVertical;
+}
+
+void GlyphLayoutParams::setGlyphOrientationVertical(int orient)
+{
+ m_glyphOrientationVertical = orient;
+}
+
+int GlyphLayoutParams::glyphOrientationHorizontal() const
+{
+ return m_glyphOrientationHorizontal;
+}
+
+void GlyphLayoutParams::setGlyphOrientationHorizontal(int orient)
+{
+ m_glyphOrientationHorizontal = orient;
+}
+
+double GlyphLayoutParams::textPathStartOffset() const
+{
+ return m_textPathStartOffset;
+}
+
+void GlyphLayoutParams::setTextPathStartOffset(double offset)
+{
+ m_textPathStartOffset = offset;
+}
+
+// #####
+
+GlyphRenderParams::GlyphRenderParams()
+{
+}
+
+GlyphRenderParams::~GlyphRenderParams()
+{
+}
+
+Font *GlyphRenderParams::font() const
+{
+ return m_font;
+}
+
+void GlyphRenderParams::setFont(Font *font)
+{
+ m_font = font;
+}
+
+const GlyphLayoutParams *GlyphRenderParams::layout() const
+{
+ return m_layout;
+}
+
+void GlyphRenderParams::setLayout(const GlyphLayoutParams *layout)
+{
+ m_layout = layout;
+}
+
+unsigned int GlyphRenderParams::glyphIndex() const
+{
+ return m_glyphIndex;
+}
+
+void GlyphRenderParams::setGlyphIndex(unsigned int glyphIndex)
+{
+ m_glyphIndex = glyphIndex;
+}
+
+unsigned int GlyphRenderParams::lastGlyph() const
+{
+ return m_lastGlyph;
+}
+
+void GlyphRenderParams::setLastGlyph(unsigned int lastGlyph)
+{
+ m_lastGlyph = lastGlyph;
+}
+
+unsigned short GlyphRenderParams::character() const
+{
+ return m_character;
+}
+
+void GlyphRenderParams::setCharacter(unsigned short character)
+{
+ m_character = character;
+}
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Glyph.h b/ksvg/impl/libs/libtext2path/src/Glyph.h
new file mode 100644
index 00000000..b3bd3fb5
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Glyph.h
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_GLYPH_H
+#define T2P_GLYPH_H
+
+#include <list>
+#include <vector>
+#include <string>
+
+#include "Affine.h"
+#include "BezierPath.h"
+
+// FreeType 2 includes
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace T2P
+{
+ class Font;
+
+ // Represent one single glyph in cache
+ class Glyph
+ {
+ public:
+ Glyph();
+ ~Glyph();
+
+ Affine &affine(); // Initial tracing affine
+ void setAffine(const Affine &affine);
+
+ const BezierPath *bezierPath() const; // Non-modifyable bezierPath belonging to this glyph
+ BezierPath *modifiableBezierPath(); // ONLY USED BY GLYPHTRACER, DO NOT USE SOMEWHERE ELSE!
+ void setBezierPath(const BezierPath *bpath);
+
+ FT_BBox *ftBbox();
+
+ private:
+ Affine m_affine;
+ FT_BBox m_ftBbox[4];
+ BezierPath *m_bezierPath;
+ };
+
+ // Is created for every character which needs to
+ // be rendered and has to be deleted by the "client"
+ class GlyphAffinePair
+ {
+ public:
+ GlyphAffinePair(const Glyph *glyph, const Affine &affine);
+ ~GlyphAffinePair();
+
+ void setTransformatedPath(const BezierPath *path);
+ const BezierPath *transformatedPath() const;
+
+ const Glyph *glyph() const;
+ Affine &affine();
+
+ private:
+ const Glyph *m_glyph;
+ const BezierPath *m_transformatedPath;
+ Affine m_affine;
+ };
+
+ class GlyphSet
+ {
+ public:
+ GlyphSet();
+ ~GlyphSet();
+
+ std::vector<GlyphAffinePair *> &set();
+ std::list<float> glyphXAdvance();
+ std::list<float> glyphYAdvance();
+
+ unsigned int glyphCount() const;
+
+ int width() const;
+ int height() const;
+
+ int bboxX() const;
+ int bboxY() const;
+
+ double xpen() const;
+ double ypen() const;
+
+ int underlinePosition() const;
+ int underlineThickness() const;
+ int overlinePosition() const;
+ int strikeThroughPosition() const;
+ int pixelBaseline() const;
+
+ private:
+ friend class Converter;
+ unsigned int m_glyphCount; // Number of glyphs in the set
+
+ int m_bboxX, m_bboxY; // Bounding box locations (x,y) + (x + width, y + width)
+ int m_width, m_height;
+
+ double m_xpen, m_ypen; // relative pen locations
+
+ int m_underlinePosition, m_underlineThickness, m_overlinePosition, m_strikeThroughPosition, m_pixelBaseline;
+
+ std::vector<GlyphAffinePair *> m_set; // Bezier paths in the set
+
+ std::list<float> m_glyphXAdvance; // List of advance values needed ie. for text paths
+ std::list<float> m_glyphYAdvance;
+ };
+
+ class GlyphLayoutParams
+ {
+ public:
+ GlyphLayoutParams();
+ ~GlyphLayoutParams();
+
+ bool tb() const;
+ void setTb(bool tb);
+
+ bool useBidi() const;
+ void setUseBidi(bool bidi);
+
+ double wordSpacing() const;
+ void setWordSpacing(double wordSpacing);
+
+ double letterSpacing() const;
+ void setLetterSpacing(double letterSpacing);
+
+ std::string baselineShift() const;
+ void setBaselineShift(const std::string &baseline);
+
+ int glyphOrientationVertical() const;
+ void setGlyphOrientationVertical(int orient);
+
+ int glyphOrientationHorizontal() const;
+ void setGlyphOrientationHorizontal(int orient);
+
+ // textOnPath specific stuff
+ double textPathStartOffset() const;
+ void setTextPathStartOffset(double offset);
+
+ private:
+ bool m_tb; // Top-To-Bottom or Bottom-To-Top ?
+ bool m_useBidi; // Use Bidi ?
+ double m_wordSpacing, m_letterSpacing; // word/character spacing
+ double m_textPathStartOffset; // range: 0.0 - 1.0; start offset in the path
+ int m_glyphOrientationVertical, m_glyphOrientationHorizontal; // Degrees...
+ std::string m_baseline; // baseline description, using same system as svg
+ };
+
+ class GlyphRenderParams
+ {
+ public:
+ GlyphRenderParams();
+ ~GlyphRenderParams();
+
+ Font *font() const;
+ void setFont(Font *font);
+
+ const GlyphLayoutParams *layout() const;
+ void setLayout(const GlyphLayoutParams *layout);
+
+ unsigned int glyphIndex() const;
+ void setGlyphIndex(unsigned int glyphIndex);
+
+ unsigned int lastGlyph() const;
+ void setLastGlyph(unsigned int lastGlyph);
+
+ unsigned short character() const;
+ void setCharacter(unsigned short character);
+
+ private:
+ Font *m_font;
+ const GlyphLayoutParams *m_layout; // Glyph layouting params
+
+ unsigned int m_glyphIndex; // 'character' index in font
+ unsigned int m_lastGlyph; // Kerning
+ unsigned short m_character; // Unicode glyph to process
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/GlyphTracer.cpp b/ksvg/impl/libs/libtext2path/src/GlyphTracer.cpp
new file mode 100644
index 00000000..42457553
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/GlyphTracer.cpp
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include "GlyphTracer.h"
+
+using namespace T2P;
+
+GlyphTracer::GlyphTracer()
+{
+ m_moveTo = 0;
+ m_lineTo = 0;
+ m_conicBezier = 0;
+ m_cubicBezier = 0;
+ m_outlineMethods = 0;
+}
+
+GlyphTracer::~GlyphTracer()
+{
+ delete m_outlineMethods;
+}
+
+void GlyphTracer::setMoveto(FT_Outline_MoveToFunc funcPtr)
+{
+ m_moveTo = funcPtr;
+}
+
+void GlyphTracer::setLineto(FT_Outline_LineToFunc funcPtr)
+{
+ m_lineTo = funcPtr;
+}
+
+void GlyphTracer::setConicBezier(FT_Outline_ConicToFunc funcPtr)
+{
+ m_conicBezier = funcPtr;
+}
+
+void GlyphTracer::setCubicBezier(FT_Outline_CubicToFunc funcPtr)
+{
+ m_cubicBezier = funcPtr;
+}
+
+FT_Outline_Funcs *GlyphTracer::outlineFuncs()
+{
+ if(m_outlineMethods)
+ return m_outlineMethods;
+
+ FT_Outline_Funcs *ret = new FT_Outline_Funcs();
+ ret->move_to = m_moveTo;
+ ret->line_to = m_lineTo;
+ ret->conic_to = m_conicBezier;
+ ret->cubic_to = m_cubicBezier;
+ ret->shift = 0;
+ ret->delta = 0;
+
+ m_outlineMethods = ret;
+ return m_outlineMethods;
+}
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/GlyphTracer.h b/ksvg/impl/libs/libtext2path/src/GlyphTracer.h
new file mode 100644
index 00000000..7607ecad
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/GlyphTracer.h
@@ -0,0 +1,65 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_GLYPHTRACER_H
+#define T2P_GLYPHTRACER_H
+
+// FreeType 2 includes
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace T2P
+{
+ class Glyph;
+ class BezierPath;
+ class GlyphAffinePair;
+
+ class GlyphTracer
+ {
+ public:
+ GlyphTracer();
+ virtual ~GlyphTracer();
+
+ // Needs to be implemented
+ virtual void correctGlyph(GlyphAffinePair *glyphAffine) = 0;
+ virtual BezierPath *allocBezierPath(int size) = 0;
+ virtual void closePath(Glyph *glyph) = 0;
+
+ // FreeType glyph tracing functions
+ void setMoveto(FT_Outline_MoveToFunc funcPtr);
+ void setLineto(FT_Outline_LineToFunc funcPtr);
+ void setConicBezier(FT_Outline_ConicToFunc funcPtr);
+ void setCubicBezier(FT_Outline_CubicToFunc funcPtr);
+
+ FT_Outline_Funcs *outlineFuncs();
+
+ private:
+ FT_Outline_Funcs *m_outlineMethods;
+
+ FT_Outline_MoveToFunc m_moveTo;
+ FT_Outline_LineToFunc m_lineTo;
+ FT_Outline_ConicToFunc m_conicBezier;
+ FT_Outline_CubicToFunc m_cubicBezier;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Makefile.am b/ksvg/impl/libs/libtext2path/src/Makefile.am
new file mode 100644
index 00000000..175e1a91
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Makefile.am
@@ -0,0 +1,10 @@
+lib_LTLIBRARIES = libtext2path.la
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+INCLUDES = $(FRIBIDI_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) $(all_includes)
+
+libtext2path_includedir=$(includedir)/libtext2path-0.1
+libtext2path_include_HEADERS = BezierPath.h Glyph.h GlyphTracer.h
+
+libtext2path_la_SOURCES = Affine.cpp Rectangle.cpp Font.cpp Glyph.cpp GlyphTracer.cpp Converter.cpp QtUnicode.cpp
+libtext2path_la_LDFLAGS = $(FRIBIDI_LIBS) $(FONTCONFIG_LIBS)
diff --git a/ksvg/impl/libs/libtext2path/src/Point.h b/ksvg/impl/libs/libtext2path/src/Point.h
new file mode 100644
index 00000000..d95742a2
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Point.h
@@ -0,0 +1,65 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_POINT_H
+#define T2P_POINT_H
+
+namespace T2P
+{
+ class Point
+ {
+ public:
+ Point() { m_x = 0.0; m_y = 0.0; }
+ Point(double x, double y) { m_x = x; m_y = y; }
+ Point &operator=(const Point &other) { m_x = other.x(); m_y = other.y(); return *this; }
+
+ friend inline Point operator+(const Point &, const Point &);
+ friend inline Point operator-(const Point &, const Point &);
+ friend inline Point operator*(const double &, const Point &);
+ friend inline Point operator*(const Point &, const double &);
+
+ double x() const { return m_x; }
+ double y() const { return m_y; }
+
+ void setX(double x) { m_x = x; }
+ void setY(double y) { m_y = y; }
+
+ const Point invert() const
+ {
+ Point temp;
+ temp.setX(-x());
+ temp.setY(-y());
+ return temp;
+ }
+
+ private:
+ double m_x;
+ double m_y;
+ };
+
+ inline Point operator+(const Point &p1, const Point &p2) { return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y); }
+ inline Point operator-(const Point &p1, const Point &p2) { return Point(p1.m_x - p2.m_x, p1.m_y - p2.m_y); }
+ inline Point operator*(const double &c, const Point &p) { return Point(p.m_x * c, p.m_y * c); }
+ inline Point operator*(const Point &p, const double &c) { return Point(p.m_x * c, p.m_y * c); }
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/QtUnicode.cpp b/ksvg/impl/libs/libtext2path/src/QtUnicode.cpp
new file mode 100644
index 00000000..694ed5c7
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/QtUnicode.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+**
+** ???
+**
+** Copyright (C) 2002-2003 Trolltech AS. All rights reserved.
+**
+** This file is part of the kernel module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "QtUnicode.h"
+
+using namespace T2P;
+// START OF GENERATED DATA
+
+// copied form qfont.h, as we can't include it in tools. Do not modify without
+// changing the script enum in qfont.h aswell.
+const unsigned char QtUnicode::otherScripts [120] = {
+#define SCRIPTS_02 0
+ 0xaf, Latin, 0xff, SpacingModifiers, // row 0x02, index 0
+#define SCRIPTS_03 4
+ 0x6f, CombiningMarks, 0xff, Greek, // row 0x03, index 4
+#define SCRIPTS_05 8
+ 0x2f, Cyrillic, 0x8f, Armenian, 0xff, Hebrew, // row 0x05, index 8
+#define SCRIPTS_07 14
+ 0x4f, Syriac, 0x7f, Unicode, 0xbf, Thaana,
+ 0xff, Unicode, // row 0x07, index 14
+#define SCRIPTS_10 22
+ 0x9f, Myanmar, 0xff, Georgian, // row 0x10, index 20
+#define SCRIPTS_13 26
+ 0x7f, Ethiopic, 0x9f, Unicode, 0xff, Cherokee, // row 0x13, index 24
+#define SCRIPTS_16 32
+ 0x7f, CanadianAboriginal, 0x9f, Ogham,
+ 0xff, Runic, // row 0x16 index 30
+#define SCRIPTS_17 38
+ 0x1f, Tagalog, 0x3f, Hanunoo, 0x5f, Buhid,
+ 0x7f, Tagbanwa, 0xff, Khmer, // row 0x17, index 36
+#define SCRIPTS_18 48
+ 0xaf, Mongolian, 0xff, Unicode, // row 0x18, index 46
+#define SCRIPTS_20 52
+ 0x0b, Unicode, 0x0d, UnknownScript, 0x6f, Unicode, 0x9f, NumberForms,
+ 0xab, CurrencySymbols, 0xac, Latin,
+ 0xcf, CurrencySymbols, 0xff, CombiningMarks, // row 0x20, index 50
+#define SCRIPTS_21 68
+ 0x4f, LetterlikeSymbols, 0x8f, NumberForms,
+ 0xff, MathematicalOperators, // row 0x21, index 62
+#define SCRIPTS_24 74
+ 0x5f, TechnicalSymbols, 0xff, EnclosedAndSquare, // row 0x24, index 68
+#define SCRIPTS_2e 78
+ 0x7f, Unicode, 0xff, Han, // row 0x2e, index 72
+#define SCRIPTS_30 82
+ 0x3f, Han, 0x9f, Hiragana, 0xff, Katakana, // row 0x30, index 76
+#define SCRIPTS_31 88
+ 0x2f, Bopomofo, 0x8f, Hangul, 0x9f, Han,
+ 0xff, Unicode, // row 0x31, index 82
+#define SCRIPTS_fb 96
+ 0x06, Latin, 0x1c, Unicode, 0x4f, Hebrew,
+ 0xff, Arabic, // row 0xfb, index 90
+#define SCRIPTS_fe 104
+ 0x1f, Unicode, 0x2f, CombiningMarks, 0x6f, Unicode,
+ 0xff, Arabic, // row 0xfe, index 98
+#define SCRIPTS_ff 112
+ 0x5e, Katakana, 0x60, Unicode, // row 0xff, index 106
+ 0x9f, KatakanaHalfWidth, 0xff, Unicode
+};
+
+// (uc-0x0900)>>7
+const unsigned char QtUnicode::indicScripts [] =
+{
+ Devanagari, Bengali,
+ Gurmukhi, Gujarati,
+ Oriya, Tamil,
+ Telugu, Kannada,
+ Malayalam, Sinhala,
+ Thai, Lao
+};
+
+
+// 0x80 + x: x is the offset into the otherScripts table
+const unsigned char QtUnicode::scriptTable[256] =
+{
+ Latin, Latin, 0x80+SCRIPTS_02, 0x80+SCRIPTS_03,
+ Cyrillic, 0x80+SCRIPTS_05, Arabic, 0x80+SCRIPTS_07,
+ Unicode, SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC,
+ SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC, Tibetan,
+
+ 0x80+SCRIPTS_10, Hangul, Ethiopic, 0x80+SCRIPTS_13,
+ CanadianAboriginal, CanadianAboriginal, 0x80+SCRIPTS_16, 0x80+SCRIPTS_17,
+ 0x80+SCRIPTS_18, Unicode, Unicode, Unicode,
+ Unicode, Unicode, Latin, Greek,
+
+ 0x80+SCRIPTS_20, 0x80+SCRIPTS_21, MathematicalOperators, TechnicalSymbols,
+ 0x80+SCRIPTS_24, GeometricSymbols, MiscellaneousSymbols, MiscellaneousSymbols,
+ Braille, Unicode, Unicode, Unicode,
+ Unicode, Unicode, 0x80+SCRIPTS_2e, Han,
+
+ 0x80+SCRIPTS_30, 0x80+SCRIPTS_31, EnclosedAndSquare, EnclosedAndSquare,
+ Han, Han, Han, Han,
+ Han, Han, Han, Han,
+ Han, Han, Han, Han,
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+ Han, Han, Han, Han, Han, Han, Han, Han,
+ Han, Han, Han, Han, Han, Han, Han, Han,
+
+ Yi, Yi, Yi, Yi, Yi, Unicode, Unicode, Unicode,
+ Unicode, Unicode, Unicode, Unicode, Hangul, Hangul, Hangul, Hangul,
+
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+
+ Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul,
+ Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode,
+
+ Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode,
+ Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode,
+
+ Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode,
+ Unicode, Han, Han, 0x80+SCRIPTS_fb, Arabic, Arabic, 0x80+SCRIPTS_fe, 0x80+SCRIPTS_ff
+};
+
diff --git a/ksvg/impl/libs/libtext2path/src/QtUnicode.h b/ksvg/impl/libs/libtext2path/src/QtUnicode.h
new file mode 100644
index 00000000..41008500
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/QtUnicode.h
@@ -0,0 +1,149 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_QT_UNICODE_H
+#define T2P_QT_UNICODE_H
+
+namespace T2P
+{
+ enum Script
+ {
+ // European Alphabetic Scripts
+ Latin,
+ Greek,
+ Cyrillic,
+ Armenian,
+ Georgian,
+ Runic,
+ Ogham,
+ SpacingModifiers,
+ CombiningMarks,
+
+ // Middle Eastern Scripts
+ Hebrew,
+ Arabic,
+ Syriac,
+ Thaana,
+
+ // South and Southeast Asian Scripts
+ Devanagari,
+ Bengali,
+ Gurmukhi,
+ Gujarati,
+ Oriya,
+ Tamil,
+ Telugu,
+ Kannada,
+ Malayalam,
+ Sinhala,
+ Thai,
+ Lao,
+ Tibetan,
+ Myanmar,
+ Khmer,
+
+ // East Asian Scripts
+ Han,
+ Hiragana,
+ Katakana,
+ Hangul,
+ Bopomofo,
+ Yi,
+
+ // Additional Scripts
+ Ethiopic,
+ Cherokee,
+ CanadianAboriginal,
+ Mongolian,
+
+ // Symbols
+ CurrencySymbols,
+ LetterlikeSymbols,
+ NumberForms,
+ MathematicalOperators,
+ TechnicalSymbols,
+ GeometricSymbols,
+ MiscellaneousSymbols,
+ EnclosedAndSquare,
+ Braille,
+
+ Unicode,
+
+ // some scripts added in Unicode 3.2
+ Tagalog,
+ Hanunoo,
+ Buhid,
+ Tagbanwa,
+
+ KatakanaHalfWidth,
+
+ // End
+ NScripts,
+ UnknownScript = NScripts
+ };
+
+ class QtUnicode
+ {
+ public:
+ QtUnicode() { }
+ ~QtUnicode() { }
+
+ static int scriptForChar(unsigned short uc)
+ {
+ unsigned char script = QtUnicode::scriptTable[(uc >> 8)];
+ if(script >= QtUnicode::SCRIPTS_INDIC)
+ {
+ if(script == QtUnicode::SCRIPTS_INDIC)
+ script = QtUnicode::indicScripts[(uc - 0x0900) >> 7];
+ else
+ {
+ // 0x80 + SCRIPTS_xx
+ unsigned char index = script - 0x80;
+ unsigned char cell = uc & 0xff;
+ while(QtUnicode::otherScripts[index++] < cell)
+ index++;
+ script = QtUnicode::otherScripts[index];
+ }
+ }
+
+ return script;
+ }
+
+ private:
+ enum
+ {
+ SCRIPTS_INDIC = 0x7e
+ };
+
+ static const unsigned char otherScripts[];
+ static const unsigned char indicScripts[];
+ static const unsigned char scriptTable[];
+ };
+}
+
+#define SCRIPT_FOR_CHAR(script, c) \
+if(c < 0x100) \
+ script = T2P::Latin; \
+else \
+ script = (T2P::Script) QtUnicode::scriptForChar(c);
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Rectangle.cpp b/ksvg/impl/libs/libtext2path/src/Rectangle.cpp
new file mode 100644
index 00000000..ef59d6be
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Rectangle.cpp
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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.
+*/
+
+#include "Tools.h"
+#include "Rectangle.h"
+
+using namespace T2P;
+
+Rectangle::Rectangle()
+{
+}
+
+Rectangle::Rectangle(const Rectangle &other)
+{
+ (*this) = other;
+}
+
+Rectangle::Rectangle(const Point &a, const Point &b) : m_a(a), m_b(b)
+{
+}
+
+Rectangle::Rectangle(double x, double y, double width, double height)
+{
+ m_a = Point(x, y);
+ m_b = Point(x + width, y + height);
+}
+
+Rectangle::~Rectangle()
+{
+}
+
+Rectangle &Rectangle::operator=(const Rectangle &other)
+{
+ m_a = other.m_a;
+ m_b = other.m_b;
+
+ return *this;
+}
+
+Point Rectangle::a() const
+{
+ return m_a;
+}
+
+void Rectangle::setA(const Point &a)
+{
+ m_a = a;
+}
+
+Point Rectangle::b() const
+{
+ return m_b;
+}
+
+void Rectangle::setB(const Point &b)
+{
+ m_b = b;
+}
+
+void Rectangle::bboxUnion(const Rectangle &src1, const Rectangle &src2)
+{
+ double src1x0 = src1.a().x(), src1x1 = src1.b().x();
+ double src1y0 = src1.a().y(), src1y1 = src1.b().y();
+
+ double src2x0 = src2.a().x(), src2x1 = src2.b().x();
+ double src2y0 = src2.a().y(), src2y1 = src2.b().y();
+
+ if(src1x1 <= src1x0 || src1y1 <= src1y0) // Is src1 empty?
+ { // Copy src2 to dst
+ setA(Point(src2x0, src2y0));
+ setB(Point(src2x1, src2y1));
+ }
+ else if(src2x1 <= src2x0 || src2y1 <= src2y0) // Is src2 empty?
+ { // Copy src1 to dest
+ setA(Point(src1x0, src1y0));
+ setB(Point(src1x1, src1y1));
+ }
+ else
+ {
+ setA(Point(T2PMIN(src1x0, src2x0), T2PMIN(src1y0, src2y0)));
+ setB(Point(T2PMAX(src1x1, src2x1), T2PMAX(src1y1, src2y1)));
+ }
+}
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Rectangle.h b/ksvg/impl/libs/libtext2path/src/Rectangle.h
new file mode 100644
index 00000000..1a5eeeb1
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Rectangle.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_RECTANGLE_H
+#define T2P_RECTANGLE_H
+
+#include "Point.h"
+
+namespace T2P
+{
+ class Rectangle
+ {
+ public:
+ Rectangle();
+ Rectangle(const Rectangle &other);
+ Rectangle(const Point &a, const Point &b);
+ Rectangle(double x, double y, double width, double height);
+ ~Rectangle();
+
+ Rectangle &operator=(const Rectangle &other);
+
+ Point a() const;
+ void setA(const Point &a);
+
+ Point b() const;
+ void setB(const Point &b);
+
+ // Finds the smallest rectangle that includes src1 and src2.
+ void bboxUnion(const Rectangle &src1, const Rectangle &src2);
+
+ private:
+ Point m_a, m_b;
+ };
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/Tools.h b/ksvg/impl/libs/libtext2path/src/Tools.h
new file mode 100644
index 00000000..c7753365
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/Tools.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2003 Nikolas Zimmermann <wildfox@kde.org>
+ This file is part of the KDE project
+
+ 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
+ aint 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 T2P_TOOLS_H
+#define T2P_TOOLS_H
+
+#include <list>
+#include <string>
+#include <config.h>
+#ifdef HAVE_SSTREAM
+# include <sstream>
+#else
+# include <strstream>
+# define ostringstream ostrstream
+#endif
+
+#define T2PMAX(a, b) ((b) < (a) ? (a) : (b))
+#define T2PMIN(a, b) ((a) < (b) ? (a) : (b))
+
+namespace T2P
+{
+ class Tools
+ {
+ public:
+ static std::string joinList(char seperator, std::list<std::string> &list)
+ {
+ std::string result;
+
+ if(list.empty())
+ return result;
+
+ bool first = true;
+ for(std::list<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ std::string string = *it;
+
+ if(!string.empty())
+ {
+ if(!first)
+ result += seperator + string;
+ else
+ {
+ result += string;
+ first = false;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ template<typename T>
+ static std::string a2str(T arg)
+ {
+ std::ostringstream buffer;
+ buffer << arg;
+ return buffer.str();
+ }
+ };
+}
+
+#ifdef ostringstream
+# undef ostringstream
+#endif
+
+#endif
+
+// vim:ts=4:noet
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/assert.hpp b/ksvg/impl/libs/libtext2path/src/myboost/assert.hpp
new file mode 100644
index 00000000..3f3c61c2
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/assert.hpp
@@ -0,0 +1,24 @@
+//
+// boost/assert.hpp - BOOST_ASSERT(expr)
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// Note: There are no include guards. This is intentional.
+//
+// See http://www.boost.org/libs/utility/assert.html for documentation.
+//
+
+#ifndef ASSERT_HPP
+#define ASSERT_HPP
+
+#undef BOOST_ASSERT
+
+# include <assert.h>
+# define BOOST_ASSERT(expr) assert(expr)
+
+#endif
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/checked_delete.hpp b/ksvg/impl/libs/libtext2path/src/myboost/checked_delete.hpp
new file mode 100644
index 00000000..73afd5f5
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/checked_delete.hpp
@@ -0,0 +1,61 @@
+#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
+#define BOOST_CHECKED_DELETE_HPP_INCLUDED
+
+//
+// boost/checked_delete.hpp
+//
+// Copyright (c) 1999, 2000, 2001, 2002 boost.org
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
+//
+
+namespace myboost
+{
+
+// verify that types are complete for increased safety
+
+template<class T> inline void checked_delete(T * x)
+{
+ // Intel 7 accepts sizeof(incomplete) as 0 in system headers
+ typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
+ delete x;
+}
+
+template<class T> inline void checked_array_delete(T * x)
+{
+ typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
+ delete [] x;
+}
+
+template<class T> struct checked_deleter
+{
+ typedef void result_type;
+ typedef T * argument_type;
+
+ void operator()(T * x) const
+ {
+ // boost:: disables ADL
+ myboost::checked_delete(x);
+ }
+};
+
+template<class T> struct checked_array_deleter
+{
+ typedef void result_type;
+ typedef T * argument_type;
+
+ void operator()(T * x) const
+ {
+ myboost::checked_array_delete(x);
+ }
+};
+
+} // namespace myboost
+
+#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/lightweight_mutex.hpp b/ksvg/impl/libs/libtext2path/src/myboost/lightweight_mutex.hpp
new file mode 100644
index 00000000..10db127c
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/lightweight_mutex.hpp
@@ -0,0 +1,74 @@
+#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
+#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
+
+//
+// boost/detail/lwm_pthreads.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+#include <pthread.h>
+
+namespace myboost
+{
+
+namespace detail
+{
+
+class lightweight_mutex
+{
+private:
+
+ pthread_mutex_t m_;
+
+ lightweight_mutex(lightweight_mutex const &);
+ lightweight_mutex & operator=(lightweight_mutex const &);
+
+public:
+
+ lightweight_mutex()
+ {
+ pthread_mutex_init(&m_, 0);
+ }
+
+ ~lightweight_mutex()
+ {
+ pthread_mutex_destroy(&m_);
+ }
+
+ class scoped_lock;
+ friend class scoped_lock;
+
+ class scoped_lock
+ {
+ private:
+
+ pthread_mutex_t & m_;
+
+ scoped_lock(scoped_lock const &);
+ scoped_lock & operator=(scoped_lock const &);
+
+ public:
+
+ scoped_lock(lightweight_mutex & m): m_(m.m_)
+ {
+ pthread_mutex_lock(&m_);
+ }
+
+ ~scoped_lock()
+ {
+ pthread_mutex_unlock(&m_);
+ }
+ };
+};
+
+} // namespace detail
+
+} // namespace myboost
+
+#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp b/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp
new file mode 100644
index 00000000..e8ec19a8
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp
@@ -0,0 +1,367 @@
+#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
+#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
+
+//
+// detail/shared_count.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+#include "myboost/checked_delete.hpp"
+#include "myboost/throw_exception.hpp"
+#include "myboost/lightweight_mutex.hpp"
+
+#include <memory> // std::auto_ptr, std::allocator
+#include <functional> // std::less
+#include <exception> // std::exception
+#include <new> // std::bad_alloc
+#include <typeinfo> // std::type_info in get_deleter
+#include <cstddef> // std::size_t
+
+namespace myboost
+{
+
+class bad_weak_ptr: public std::exception
+{
+public:
+
+ virtual char const * what() const throw()
+ {
+ return "myboost::bad_weak_ptr";
+ }
+};
+
+namespace detail
+{
+
+class sp_counted_base
+{
+private:
+
+ typedef detail::lightweight_mutex mutex_type;
+
+public:
+
+ sp_counted_base(): use_count_(1), weak_count_(1)
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destruct() is called when weak_count_ drops to zero.
+
+ virtual void destruct() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter(std::type_info const & ti) = 0;
+
+ void add_ref_copy()
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ ++use_count_;
+ }
+
+ void add_ref_lock()
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ if(use_count_ == 0) myboost::throw_exception(myboost::bad_weak_ptr());
+ ++use_count_;
+ }
+
+ void release() // nothrow
+ {
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ long new_use_count = --use_count_;
+
+ if(new_use_count != 0) return;
+ }
+
+ dispose();
+ weak_release();
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ ++weak_count_;
+ }
+
+ void weak_release() // nothrow
+ {
+ long new_weak_count;
+
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ new_weak_count = --weak_count_;
+ }
+
+ if(new_weak_count == 0)
+ {
+ destruct();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ mutex_type::scoped_lock lock(mtx_);
+ return use_count_;
+ }
+
+private:
+
+ sp_counted_base(sp_counted_base const &);
+ sp_counted_base & operator= (sp_counted_base const &);
+
+ long use_count_; // #shared
+ long weak_count_; // #weak + (#shared != 0)
+
+ mutable mutex_type mtx_;
+};
+
+template<class P, class D> class sp_counted_base_impl: public sp_counted_base
+{
+private:
+
+ P ptr; // copy constructor must not throw
+ D del; // copy constructor must not throw
+
+ sp_counted_base_impl(sp_counted_base_impl const &);
+ sp_counted_base_impl & operator= (sp_counted_base_impl const &);
+
+ typedef sp_counted_base_impl<P, D> this_type;
+
+public:
+
+ // pre: initial_use_count <= initial_weak_count, d(p) must not throw
+
+ sp_counted_base_impl(P p, D d): ptr(p), del(d)
+ {
+ }
+
+ virtual void dispose() // nothrow
+ {
+ del(ptr);
+ }
+
+ virtual void * get_deleter(std::type_info const & ti)
+ {
+ return ti == typeid(D)? &del: 0;
+ }
+
+ void * operator new(std::size_t)
+ {
+ return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
+ }
+
+ void operator delete(void * p)
+ {
+ std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
+ }
+};
+
+class weak_count;
+
+class shared_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+ friend class weak_count;
+
+public:
+
+ shared_count(): pi_(0) // nothrow
+ {
+ }
+
+ template<class P, class D> shared_count(P p, D d): pi_(0)
+ {
+
+ try
+ {
+ pi_ = new sp_counted_base_impl<P, D>(p, d);
+ }
+ catch(...)
+ {
+ d(p); // delete p
+ throw;
+ }
+
+
+ pi_ = new sp_counted_base_impl<P, D>(p, d);
+
+ if(pi_ == 0)
+ {
+ d(p); // delete p
+ myboost::throw_exception(std::bad_alloc());
+ }
+ }
+
+ // auto_ptr<Y> is special cased to provide the strong guarantee
+
+ template<class Y>
+ explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>()))
+ {
+ r.release();
+ }
+
+ ~shared_count() // nothrow
+ {
+ if(pi_ != 0) pi_->release();
+ }
+
+ shared_count(shared_count const & r): pi_(r.pi_) // nothrow
+ {
+ if(pi_ != 0) pi_->add_ref_copy();
+ }
+
+ explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
+
+ shared_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ if(tmp != 0) tmp->add_ref_copy();
+ if(pi_ != 0) pi_->release();
+ pi_ = tmp;
+
+ return *this;
+ }
+
+ void swap(shared_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ bool unique() const // nothrow
+ {
+ return use_count() == 1;
+ }
+
+ friend inline bool operator==(shared_count const & a, shared_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(shared_count const & a, shared_count const & b)
+ {
+ return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+ }
+
+ void * get_deleter(std::type_info const & ti) const
+ {
+ return pi_? pi_->get_deleter(ti): 0;
+ }
+};
+
+class weak_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+ friend class shared_count;
+
+public:
+
+ weak_count(): pi_(0) // nothrow
+ {
+ }
+
+ weak_count(shared_count const & r): pi_(r.pi_) // nothrow
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+ weak_count(weak_count const & r): pi_(r.pi_) // nothrow
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+ ~weak_count() // nothrow
+ {
+ if(pi_ != 0) pi_->weak_release();
+ }
+
+ weak_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+
+ return *this;
+ }
+
+ weak_count & operator= (weak_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+
+ return *this;
+ }
+
+ void swap(weak_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ friend inline bool operator==(weak_count const & a, weak_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(weak_count const & a, weak_count const & b)
+ {
+ return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+ }
+};
+
+inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
+{
+ if(pi_ != 0)
+ {
+ pi_->add_ref_lock();
+ }
+ else
+ {
+ myboost::throw_exception(myboost::bad_weak_ptr());
+ }
+}
+
+} // namespace detail
+
+} // namespace myboost
+
+#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/shared_ptr.hpp b/ksvg/impl/libs/libtext2path/src/myboost/shared_ptr.hpp
new file mode 100644
index 00000000..3f2fe30d
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/shared_ptr.hpp
@@ -0,0 +1,395 @@
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SHARED_PTR_HPP_INCLUDED
+
+// shared_ptr.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include "myboost/assert.hpp"
+#include "myboost/checked_delete.hpp"
+#include "myboost/throw_exception.hpp"
+#include "myboost/shared_count.hpp"
+
+#include <memory> // for std::auto_ptr
+#include <algorithm> // for std::swap
+#include <functional> // for std::less
+#include <typeinfo> // for std::bad_cast
+#include <iosfwd> // for std::basic_ostream
+
+namespace myboost
+{
+
+template<class T> class weak_ptr;
+template<class T> class enable_shared_from_this;
+
+namespace detail
+{
+
+struct static_cast_tag {};
+struct const_cast_tag {};
+struct dynamic_cast_tag {};
+struct polymorphic_cast_tag {};
+
+template<class T> struct shared_ptr_traits
+{
+ typedef T & reference;
+};
+
+template<> struct shared_ptr_traits<void>
+{
+ typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void const>
+{
+ typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void volatile>
+{
+ typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void const volatile>
+{
+ typedef void reference;
+};
+
+// enable_shared_from_this support
+
+template<class T, class Y> void sp_enable_shared_from_this(myboost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn)
+{
+ if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn);
+}
+
+inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &)
+{
+}
+
+} // namespace detail
+
+
+//
+// shared_ptr
+//
+// An enhanced relative of scoped_ptr with reference counted copy semantics.
+// The object pointed to is deleted when the last shared_ptr pointing to it
+// is destroyed or reset.
+//
+
+template<class T> class shared_ptr
+{
+private:
+
+ // Borland 5.5.1 specific workaround
+ typedef shared_ptr<T> this_type;
+
+public:
+
+ typedef T element_type;
+ typedef T value_type;
+ typedef T * pointer;
+ typedef typename detail::shared_ptr_traits<T>::reference reference;
+
+ shared_ptr(): px(0), pn() // never throws in 1.30+
+ {
+ }
+
+ template<class Y>
+ explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
+ {
+ detail::sp_enable_shared_from_this(p, p, pn);
+ }
+
+ //
+ // Requirements: D's copy constructor must not throw
+ //
+ // shared_ptr will release p by calling d(p)
+ //
+
+ template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
+ {
+ detail::sp_enable_shared_from_this(p, p, pn);
+ }
+
+// generated copy constructor, assignment, destructor are fine...
+// except that Borland C++ has a bug, and g++ with -Wsynth warns
+ shared_ptr & operator=(shared_ptr const & r) // never throws
+ {
+ px = r.px;
+ pn = r.pn; // shared_count::op= doesn't throw
+ return *this;
+ }
+
+ template<class Y>
+ explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
+ {
+ // it is now safe to copy r.px, as pn(r.pn) did not throw
+ px = r.px;
+ }
+
+ template<class Y>
+ shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+ {
+ }
+
+ template<class Y>
+ shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
+ {
+ }
+
+ template<class Y>
+ shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
+ {
+ }
+
+ template<class Y>
+ shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+ {
+ if(px == 0) // need to allocate new counter -- the cast failed
+ {
+ pn = detail::shared_count();
+ }
+ }
+
+ template<class Y>
+ shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+ {
+ if(px == 0)
+ {
+ myboost::throw_exception(std::bad_cast());
+ }
+ }
+
+ template<class Y>
+ explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
+ {
+ Y * tmp = r.get();
+ pn = detail::shared_count(r);
+ detail::sp_enable_shared_from_this(tmp, tmp, pn);
+ }
+
+ template<class Y>
+ shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
+ {
+ px = r.px;
+ pn = r.pn; // shared_count::op= doesn't throw
+ return *this;
+ }
+
+ template<class Y>
+ shared_ptr & operator=(std::auto_ptr<Y> & r)
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+ void reset() // never throws in 1.30+
+ {
+ this_type().swap(*this);
+ }
+
+ template<class Y> void reset(Y * p) // Y must be complete
+ {
+ BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
+ this_type(p).swap(*this);
+ }
+
+ template<class Y, class D> void reset(Y * p, D d)
+ {
+ this_type(p, d).swap(*this);
+ }
+
+ reference operator* () const // never throws
+ {
+ BOOST_ASSERT(px != 0);
+ return *px;
+ }
+
+ T * operator-> () const // never throws
+ {
+ BOOST_ASSERT(px != 0);
+ return px;
+ }
+
+ T * get() const // never throws
+ {
+ return px;
+ }
+
+ typedef T * (this_type::*unspecified_bool_type)() const;
+
+ operator unspecified_bool_type() const // never throws
+ {
+ return px == 0? 0: &this_type::get;
+ }
+
+ // operator! is redundant, but some compilers need it
+
+ bool operator! () const // never throws
+ {
+ return px == 0;
+ }
+
+ bool unique() const // never throws
+ {
+ return pn.unique();
+ }
+
+ long use_count() const // never throws
+ {
+ return pn.use_count();
+ }
+
+ void swap(shared_ptr<T> & other) // never throws
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
+ {
+ return pn < rhs.pn;
+ }
+
+ void * _internal_get_deleter(std::type_info const & ti) const
+ {
+ return pn.get_deleter(ti);
+ }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+# if __GNUC__ >= 2 && __GNUC_MINOR__ >= 97
+private:
+
+ template<class Y> friend class shared_ptr;
+ template<class Y> friend class weak_ptr;
+#endif
+
+ T * px; // contained pointer
+ detail::shared_count pn; // reference counter
+
+}; // shared_ptr
+
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+ return a.get() != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
+{
+ return a.get() != b.get();
+}
+
+#endif
+
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+ return a._internal_less(b);
+}
+
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
+{
+ a.swap(b);
+}
+
+template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::const_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::dynamic_cast_tag());
+}
+
+// shared_*_cast names are deprecated. Use *_pointer_cast instead.
+
+template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::dynamic_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
+{
+ return shared_ptr<T>(r, detail::polymorphic_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
+{
+ BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
+ return shared_static_cast<T>(r);
+}
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline T * get_pointer(shared_ptr<T> const & p)
+{
+ return p.get();
+}
+
+// operator<<
+
+
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
+{
+ os << p.get();
+ return os;
+}
+
+
+// get_deleter (experimental)
+
+#if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
+
+// g++ 2.9x doesn't allow static_cast<X const *>(void *)
+// apparently EDG 2.38 also doesn't accept it
+
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
+{
+ void const * q = p._internal_get_deleter(typeid(D));
+ return const_cast<D *>(static_cast<D const *>(q));
+}
+
+#else
+
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
+{
+ return static_cast<D *>(p._internal_get_deleter(typeid(D)));
+}
+
+#endif
+
+} // namespace boost
+
+
+#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/throw_exception.hpp b/ksvg/impl/libs/libtext2path/src/myboost/throw_exception.hpp
new file mode 100644
index 00000000..dd32ec43
--- /dev/null
+++ b/ksvg/impl/libs/libtext2path/src/myboost/throw_exception.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
+#define BOOST_THROW_EXCEPTION_HPP_INCLUDED
+
+
+//
+// boost/throw_exception.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+// http://www.boost.org/libs/utility/throw_exception.html
+//
+
+# include <exception>
+
+namespace myboost
+{
+
+template<class E> void throw_exception(E const & e)
+{
+ throw e;
+}
+
+} // namespace myboost
+
+#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
diff --git a/ksvg/impl/libs/xrgbrender/Makefile.am b/ksvg/impl/libs/xrgbrender/Makefile.am
new file mode 100644
index 00000000..1e9ebcc1
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libksvgxrgbrender.la
+
+libksvgxrgbrender_la_SOURCES = gdk-pixbuf-xlib.c gdk-pixbuf-xlib-drawable.c gdk-pixbuf-xlibrgb.c
diff --git a/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-drawable.c b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-drawable.c
new file mode 100644
index 00000000..01f60976
--- /dev/null
+++ b/ksvg/impl/libs/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 (X_BYTE_ORDER == X_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/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-private.h b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-private.h
new file mode 100644
index 00000000..f1113339
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib-private.h
@@ -0,0 +1,30 @@
+/* GdkPixbuf library - Xlib header file
+ *
+ * Authors: John Harper <john@dcs.warwick.ac.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GDK_PIXBUF_XLIB_PRIVATE_H
+#define GDK_PIXBUF_XLIB_PRIVATE_H
+
+#include "gdk-pixbuf-xlib.h"
+#include <X11/Xlib.h>
+
+extern Display *gdk_pixbuf_dpy;
+extern int gdk_pixbuf_screen;
+
+#endif
diff --git a/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.c b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.c
new file mode 100644
index 00000000..8383246b
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.c
@@ -0,0 +1,46 @@
+/* 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_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/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.h b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.h
new file mode 100644
index 00000000..aa94c7c6
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlib.h
@@ -0,0 +1,78 @@
+/* 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_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/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.c b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.c
new file mode 100644
index 00000000..eb7e4cdf
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.c
@@ -0,0 +1,3425 @@
+/* -*- 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_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 X_BYTE_ORDER == X_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);
+ }
+}
+
+
+
+#if X_BYTE_ORDER == X_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 X_BYTE_ORDER == X_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 X_BYTE_ORDER == X_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 X_BYTE_ORDER == X_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 X_BYTE_ORDER == X_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_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/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.h b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.h
new file mode 100644
index 00000000..afde174e
--- /dev/null
+++ b/ksvg/impl/libs/xrgbrender/gdk-pixbuf-xlibrgb.h
@@ -0,0 +1,145 @@
+/* -*- 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_with_depth (Display *display, Screen *screen, int prefDepth);
+
+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_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__ */