summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile14
-rw-r--r--test/x11pdf.c367
-rw-r--r--test/ximage.c640
3 files changed, 1020 insertions, 1 deletions
diff --git a/Jamfile b/Jamfile
index 2ac988bb..6e2f2c2a 100644
--- a/Jamfile
+++ b/Jamfile
@@ -127,11 +127,23 @@ LINKLIBS =
-lm
;
+LINKLIBS on x11pdf = -lX11 -lXext $(LINKLIBS) ;
+
Main pdfclean : test/pdfclean.c ;
Main pdfdebug : test/pdfdebug.c ;
Main pdfmerge : test/pdfmerge.c ;
Main pdfrip : test/pdfrip.c ;
Main pdffunction : test/pdffunction.c ;
-LinkLibraries pdfclean pdfdebug pdfmerge pdfrip pdffunction : libmupdf libfitz ;
+Main x11pdf : test/x11pdf.c test/ximage.c ;
+
+LinkLibraries
+ pdfclean
+ pdfdebug
+ pdfmerge
+ pdfrip
+ pdffunction
+ x11pdf
+ : libmupdf libfitz ;
+
diff --git a/test/x11pdf.c b/test/x11pdf.c
new file mode 100644
index 00000000..a1c3372f
--- /dev/null
+++ b/test/x11pdf.c
@@ -0,0 +1,367 @@
+#include <fitz.h>
+#include <mupdf.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+
+extern int ximage_init(Display *display, int screen, Visual *visual);
+extern int ximage_get_depth(void);
+extern Visual *ximage_get_visual(void);
+extern Colormap ximage_get_colormap(void);
+extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty,
+ unsigned char *srcdata,
+ int srcx, int srcy, int srcw, int srch, int srcstride);
+
+static Display *xdpy;
+static int xscr;
+static Window xwin;
+static GC xgc;
+static XEvent xevt;
+static int mapped = 0;
+static Cursor xcarrow, xchand, xcwait;
+
+static float zoom = 1.0;
+static int rotate = 0;
+static int pageno = 1;
+static int count = 0;
+
+static int hist[256];
+static int histlen = 0;
+
+/* for 123G commands */
+static unsigned char pagebuf[256];
+static int pagebufidx = 0;
+
+static pdf_xref *xref;
+static pdf_pagetree *pages;
+static fz_renderer *rast;
+static fz_pixmap *image;
+
+void usage()
+{
+ fprintf(stderr, "usage: x11pdf [-u password] file.pdf\n");
+ exit(1);
+}
+
+/*
+ * X11 magic
+ */
+
+static void xopen(void)
+{
+ xdpy = XOpenDisplay(nil);
+ assert(xdpy != nil);
+
+ xscr = DefaultScreen(xdpy);
+
+ ximage_init(xdpy, xscr, DefaultVisual(xdpy, xscr));
+
+ xcarrow = XCreateFontCursor(xdpy, XC_left_ptr);
+ xchand = XCreateFontCursor(xdpy, XC_hand2);
+ xcwait = XCreateFontCursor(xdpy, XC_watch);
+
+ xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy),
+ 10, 10, 200, 100, 1,
+ ximage_get_depth(),
+ InputOutput,
+ ximage_get_visual(),
+ 0,
+ nil);
+
+ XSetWindowColormap(xdpy, xwin, ximage_get_colormap());
+ XSelectInput(xdpy, xwin,
+ StructureNotifyMask | ExposureMask | KeyPressMask |
+ PointerMotionMask | ButtonPressMask);
+
+ mapped = 0;
+
+ xgc = XCreateGC(xdpy, xwin, 0, nil);
+}
+
+static void xresize(void)
+{
+ XWindowChanges values;
+ int mask;
+
+ mask = CWWidth | CWHeight;
+ values.width = image->w;
+ values.height = image->h;
+ XConfigureWindow(xdpy, xwin, mask, &values);
+
+ if (!mapped)
+ {
+ XMapWindow(xdpy, xwin);
+ XFlush(xdpy);
+
+ while (1)
+ {
+ XNextEvent(xdpy, &xevt);
+ if (xevt.type == MapNotify)
+ break;
+ }
+
+ XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr));
+ XFillRectangle(xdpy, xwin, xgc, 0, 0, image->w, image->h);
+ XFlush(xdpy);
+
+ mapped = 1;
+ }
+}
+
+static void xblit(void)
+{
+ ximage_blit(xwin, xgc, 0, 0, image->samples, 0, 0,
+ image->w, image->h, image->w * image->n);
+}
+
+static void xtitle(char *s)
+{
+ XmbSetWMProperties(xdpy, xwin, s, s, 0, 0, 0, 0, 0);
+}
+
+static void showpage(void)
+{
+ fz_error *error;
+ pdf_page *page;
+ fz_matrix ctm;
+ fz_rect bbox;
+ char s[256];
+ fz_obj *pageobj;
+
+ assert(pageno > 0 && pageno <= pdf_getpagecount(pages));
+
+ pageobj = pdf_getpageobject(pages, pageno - 1);
+
+ XDefineCursor(xdpy, xwin, xcwait);
+ XFlush(xdpy);
+
+ if (image)
+ fz_freepixmap(image);
+ image = nil;
+
+ sprintf(s, "Loading page %d", pageno);
+ XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr));
+ XDrawString(xdpy, xwin, xgc, 10, 20, s, strlen(s));
+ XFlush(xdpy);
+
+ error = pdf_loadpage(&page, xref, pageobj);
+ if (error)
+ fz_abort(error);
+
+ sprintf(s, "Rendering...");
+ XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr));
+ XDrawString(xdpy, xwin, xgc, 10, 30, s, strlen(s));
+ XFlush(xdpy);
+
+ ctm = fz_concat(fz_translate(0, -page->mediabox.max.y),
+ fz_scale(zoom, -zoom));
+
+ bbox = page->mediabox;
+ bbox.min.x = bbox.min.x * zoom;
+ bbox.min.y = bbox.min.y * zoom;
+ bbox.max.x = bbox.max.x * zoom;
+ bbox.max.y = bbox.max.y * zoom;
+
+ error = fz_rendertree(&image, rast, page->tree, ctm, bbox);
+ if (error)
+ fz_abort(error);
+
+ pdf_freepage(page);
+
+ XDefineCursor(xdpy, xwin, xcarrow);
+ XFlush(xdpy);
+
+ xresize();
+ xblit();
+}
+
+static void pdfopen(char *filename, char *password)
+{
+ fz_error *error;
+
+ error = pdf_openpdf(&xref, filename);
+ if (error)
+ fz_abort(error);
+
+ error = pdf_decryptpdf(xref);
+ if (error)
+ fz_abort(error);
+
+ if (xref->crypt)
+ {
+ error = pdf_setpassword(xref->crypt, password);
+ if (error) fz_abort(error);
+ }
+
+ error = pdf_loadpagetree(&pages, xref);
+ if (error) fz_abort(error);
+
+ count = pdf_getpagecount(pages);
+
+ error = fz_newrenderer(&rast, pdf_devicergb);
+ if (error) fz_abort(error);
+
+ image = nil;
+}
+
+static void handlekey(int c)
+{
+ int oldpage = pageno;
+ float oldzoom = zoom;
+ int oldrotate = rotate;
+
+ if (c >= '0' && c <= '9')
+ pagebuf[pagebufidx++] = c;
+ else
+ if (c != 'g' && c != 'G')
+ pagebufidx = 0;
+
+ switch (c)
+ {
+ case 'b':
+ pageno--;
+ if (pageno < 1)
+ pageno = 1;
+ break;
+ case 'B':
+ pageno -= 10;
+ if (pageno < 1)
+ pageno = 1;
+ break;
+ case ' ':
+ case 'f':
+ pageno++;
+ if (pageno > count)
+ pageno = count;
+ break;
+ case 'F':
+ pageno += 10;
+ if (pageno > count)
+ pageno = count;
+ break;
+ case 't':
+ case 'T':
+ if (histlen > 0)
+ pageno = hist[--histlen];
+ break;
+ case '-':
+ zoom -= 0.1;
+ if (zoom < 0.1)
+ zoom = 0.1;
+ break;
+ case '+':
+ zoom += 0.1;
+ if (zoom > 3.0)
+ zoom = 3.0;
+ break;
+ case '<':
+ rotate -= 90;
+ break;
+ case '>':
+ rotate += 90;
+ break;
+ case 'q':
+ exit(0);
+ case 'g':
+ case 'G':
+ if (pagebufidx > 0)
+ {
+ pagebuf[pagebufidx] = '\0';
+ pageno = atoi(pagebuf);
+ pagebufidx = 0;
+ if (pageno < 1)
+ pageno = 1;
+ if (pageno > count)
+ pageno = count;
+ }
+ else
+ {
+ if (c == 'G')
+ {
+ pageno = count;
+ }
+ }
+ break;
+ }
+
+ if (pageno != oldpage || zoom != oldzoom || rotate != oldrotate)
+ showpage();
+}
+
+int main(int argc, char **argv)
+{
+ char *filename;
+ fz_obj *obj;
+ char buf[256];
+ int c;
+
+ char *password = "";
+
+ while ((c = getopt(argc, argv, "z:r:p:u:")) != -1)
+ {
+ switch (c)
+ {
+ case 'u': password = optarg; break;
+ case 'p': pageno = atoi(optarg); break;
+ case 'z': zoom = atof(optarg); break;
+ case 'r': rotate = atoi(optarg); break;
+ default: usage();
+ }
+ }
+
+ if (argc - optind == 0)
+ usage();
+
+ filename = argv[optind++];
+
+ xopen();
+ pdfopen(filename, password);
+ showpage();
+
+ strlcpy(buf, filename, sizeof buf);
+ obj = fz_dictgets(xref->trailer, "Info");
+ if (fz_isindirect(obj))
+ {
+ pdf_resolve(&obj, xref);
+ obj = fz_dictgets(obj, "Title");
+ if (obj)
+ {
+ int n = MIN(fz_tostringlen(obj) + 1, sizeof buf);
+ if (obj)
+ strlcpy(buf, fz_tostringbuf(obj), n);
+ printf("Title: %s\n", buf);
+ }
+ }
+ xtitle(buf);
+
+ while (1)
+ {
+ int len;
+ unsigned char buf[128];
+ KeySym keysym;
+
+ XNextEvent(xdpy, &xevt);
+ switch (xevt.type)
+ {
+ case Expose:
+ if (xevt.xexpose.count == 0)
+ xblit();
+ break;
+
+ case KeyPress:
+ len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, 0);
+ if (len)
+ handlekey(buf[0]);
+ break;
+ }
+ }
+
+ pdf_closepdf(xref);
+
+ return 0;
+}
+
diff --git a/test/ximage.c b/test/ximage.c
new file mode 100644
index 00000000..bcf8834b
--- /dev/null
+++ b/test/ximage.c
@@ -0,0 +1,640 @@
+/*
+ * Blit ARGB images to X with X(Shm)Images
+ */
+
+#include <fitz.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+
+typedef void (*ximage_convert_func_t)
+ (
+ const unsigned char *src,
+ int srcstride,
+ unsigned char *dst,
+ int dststride,
+ int w,
+ int h
+ );
+
+#define POOLSIZE 6
+#define WIDTH 256
+#define HEIGHT 64
+
+enum {
+ ARGB8888,
+ BGRA8888,
+ RGBA8888,
+ ABGR8888,
+ RGB888,
+ BGR888,
+ RGB565,
+ RGB565_BR,
+ RGB555,
+ RGB555_BR,
+ BGR233,
+ UNKNOWN
+};
+
+static char *modename[] = {
+ "ARGB8888",
+ "BGRA8888",
+ "RGBA8888",
+ "ABGR8888",
+ "RGB888",
+ "BGR888",
+ "RGB565",
+ "RGB565_BR",
+ "RGB555",
+ "RGB555_BR",
+ "BGR233",
+ "UNKNOWN"
+};
+
+extern ximage_convert_func_t ximage_convert_funcs[];
+
+static struct
+{
+ Display *display;
+ int screen;
+ XVisualInfo visual;
+ Colormap colormap;
+
+ int bitsperpixel;
+ int mode;
+
+ XColor rgbcube[256];
+
+ ximage_convert_func_t convert_func;
+
+ int useshm;
+ XImage *pool[POOLSIZE];
+ int lastused;
+} info;
+
+static XImage *
+createximage(Display *dpy, Visual *vis, int depth, int w, int h)
+{
+ XImage *img;
+ XShmSegmentInfo xsi;
+ Status status;
+
+// XXX
+goto fallback;
+
+ img = XShmCreateImage(dpy, vis, depth, ZPixmap, 0, &xsi, w, h);
+ if (!img)
+ {
+ fprintf(stderr, "warn: could not XShmCreateImage\n");
+ goto fallback;
+ }
+
+ xsi.shmid = shmget(IPC_PRIVATE,
+ img->bytes_per_line * img->height,
+ IPC_CREAT | 0777);
+ if (xsi.shmid < 0)
+ {
+ fprintf(stderr, "warn: could not shmget\n");
+ goto fallback;
+ }
+
+ img->data = xsi.shmaddr = shmat(xsi.shmid, 0, 0);
+ if (img->data == (char*)-1)
+ {
+ fprintf(stderr, "warn: could not shmat\n");
+ goto fallback;
+ }
+
+ xsi.readOnly = False;
+ status = XShmAttach(dpy, &xsi);
+ if (!status)
+ {
+ fprintf(stderr, "warn: could not XShmAttach\n");
+ goto fallback;
+ }
+
+ XSync(dpy, False);
+
+ shmctl(xsi.shmid, IPC_RMID, 0);
+
+printf("make xshm w=%d h=%d id=%d data=%p\n",
+ w, h, xsi.shmid, xsi.shmaddr);
+
+ return img;
+
+fallback:
+ info.useshm = 0;
+
+ img = XCreateImage(dpy, vis, depth, ZPixmap, 0, 0, w, h, 32, 0);
+ if (!img)
+ {
+ fprintf(stderr, "fail: could not XCreateImage");
+ abort();
+ }
+
+ img->data = malloc(h * img->bytes_per_line);
+ if (!img->data)
+ {
+ fprintf(stderr, "fail: could not malloc");
+ abort();
+ }
+
+ return img;
+}
+
+static void
+make_colormap(void)
+{
+ if (info.visual.class == PseudoColor && info.visual.depth == 8)
+ {
+ int i, r, g, b;
+ i = 0;
+ for (b = 0; b < 4; b++) {
+ for (g = 0; g < 8; g++) {
+ for (r = 0; r < 8; r++) {
+ info.rgbcube[i].pixel = i;
+ info.rgbcube[i].red = (r * 36) << 8;
+ info.rgbcube[i].green = (g * 36) << 8;
+ info.rgbcube[i].blue = (b * 85) << 8;
+ info.rgbcube[i].flags =
+ DoRed | DoGreen | DoBlue;
+ i++;
+ }
+ }
+ }
+ info.colormap = XCreateColormap(info.display,
+ RootWindow(info.display, info.screen),
+ info.visual.visual,
+ AllocAll);
+ XStoreColors(info.display, info.colormap, info.rgbcube, 256);
+ return;
+ }
+ else if (info.visual.class == TrueColor)
+ {
+ info.colormap = 0;
+ return;
+ }
+ fprintf(stderr, "Cannot handle visual class %d with depth: %d\n",
+ info.visual.class, info.visual.depth);
+ return;
+}
+
+static void
+select_mode(void)
+{
+
+ int byteorder;
+ int byterev;
+ unsigned long rm, gm, bm;
+ unsigned long rs, gs, bs;
+
+ byteorder = ImageByteOrder(info.display);
+#if BYTE_ORDER == BIG_ENDIAN
+ byterev = byteorder != MSBFirst;
+#else
+ byterev = byteorder != LSBFirst;
+#endif
+
+ rm = info.visual.red_mask;
+ gm = info.visual.green_mask;
+ bm = info.visual.blue_mask;
+
+ rs = ffs(rm) - 1;
+ gs = ffs(gm) - 1;
+ bs = ffs(bm) - 1;
+
+ printf("mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n",
+ info.visual.depth,
+ info.bitsperpixel,
+ rm, gm, bm, rs, gs, bs,
+ byteorder == MSBFirst ? "msb" : "lsb",
+ byterev ? " <swap>":"");
+
+ info.mode = UNKNOWN;
+ if (info.bitsperpixel == 8) {
+ /* Either PseudoColor with BGR233 colormap, or TrueColor */
+ info.mode = BGR233;
+ }
+ else if (info.bitsperpixel == 16) {
+ if (rm == 0xF800 && gm == 0x07E0 && bm == 0x001F)
+ info.mode = !byterev ? RGB565 : RGB565_BR;
+ if (rm == 0x7C00 && gm == 0x03E0 && bm == 0x001F)
+ info.mode = !byterev ? RGB555 : RGB555_BR;
+ }
+ else if (info.bitsperpixel == 24) {
+ if (rs == 0 && gs == 8 && bs == 16)
+ info.mode = byteorder == MSBFirst ? RGB888 : BGR888;
+ if (rs == 16 && gs == 8 && bs == 0)
+ info.mode = byteorder == MSBFirst ? BGR888 : RGB888;
+ }
+ else if (info.bitsperpixel == 32) {
+ if (rs == 0 && gs == 8 && bs == 16)
+ info.mode = byteorder == MSBFirst ? ABGR8888 : RGBA8888;
+ if (rs == 8 && gs == 16 && bs == 24)
+ info.mode = byteorder == MSBFirst ? BGRA8888 : ARGB8888;
+ if (rs == 16 && gs == 8 && bs == 0)
+ info.mode = byteorder == MSBFirst ? ARGB8888 : BGRA8888;
+ if (rs == 24 && gs == 16 && bs == 8)
+ info.mode = byteorder == MSBFirst ? RGBA8888 : ABGR8888;
+ }
+
+ printf("rgba:8888 -> %s\n", modename[info.mode]);
+
+ /* select conversion function */
+ info.convert_func = ximage_convert_funcs[info.mode];
+}
+
+static int
+create_pool(void)
+{
+ int i;
+
+ info.lastused = 0;
+
+ for (i = 0; i < POOLSIZE; i++) {
+ info.pool[i] = nil;
+ }
+
+ for (i = 0; i < POOLSIZE; i++) {
+ info.pool[i] = createximage(info.display,
+ info.visual.visual, info.visual.depth,
+ WIDTH, HEIGHT);
+ if (info.pool[i] == nil) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static XImage *
+next_pool_image(void)
+{
+ if (info.lastused + 1 >= POOLSIZE) {
+ if (info.useshm)
+ XSync(info.display, False);
+ else
+ XFlush(info.display);
+ info.lastused = 0;
+ }
+ return info.pool[info.lastused ++];
+}
+
+int
+ximage_init(Display *display, int screen, Visual *visual)
+{
+ XVisualInfo template;
+ XVisualInfo *visuals;
+ int nvisuals;
+ XPixmapFormatValues *formats;
+ int nformats;
+ int ok;
+ int i;
+
+ info.display = display;
+ info.screen = screen;
+ info.colormap = 0;
+
+ /* Get XVisualInfo for this visual */
+ template.visualid = XVisualIDFromVisual(visual);
+ visuals = XGetVisualInfo(display, VisualIDMask, &template, &nvisuals);
+ if (nvisuals != 1) {
+ fprintf(stderr, "Visual not found!\n");
+ XFree(visuals);
+ return 0;
+ }
+ memcpy(&info.visual, visuals, sizeof (XVisualInfo));
+ XFree(visuals);
+
+ /* Get appropriate PixmapFormat for this visual */
+ formats = XListPixmapFormats(info.display, &nformats);
+ for (i = 0; i < nformats; i++) {
+ if (formats[i].depth == info.visual.depth) {
+ info.bitsperpixel = formats[i].bits_per_pixel;
+ break;
+ }
+ }
+ XFree(formats);
+ if (i == nformats) {
+ fprintf(stderr, "PixmapFormat not found!\n");
+ return 0;
+ }
+
+ /* extract mode */
+ select_mode();
+
+ /* prepare colormap */
+ make_colormap();
+
+ /* prepare pool of XImages */
+ info.useshm = 1;
+ ok = create_pool();
+ if (!ok)
+ return 0;
+
+ printf("Using %sPutImage\n", info.useshm ? "XShm" : "X");
+
+ return 1;
+}
+
+int
+ximage_get_depth(void)
+{
+ return info.visual.depth;
+}
+
+Visual *
+ximage_get_visual(void)
+{
+ return info.visual.visual;
+}
+
+Colormap
+ximage_get_colormap(void)
+{
+ return info.colormap;
+}
+
+void
+ximage_blit(Drawable d, GC gc,
+ int dstx, int dsty,
+ unsigned char *srcdata,
+ int srcx, int srcy,
+ int srcw, int srch,
+ int srcstride)
+{
+ XImage *image;
+ int ax, ay;
+ int w, h;
+ unsigned char *srcptr;
+
+ for (ay = 0; ay < srch; ay += HEIGHT)
+ {
+ h = MIN(srch - ay, HEIGHT);
+ for (ax = 0; ax < srcw; ax += WIDTH)
+ {
+ w = MIN(srcw - ax, WIDTH);
+
+ image = next_pool_image();
+
+ srcptr = srcdata +
+ (ay + srcy) * srcstride +
+ (ax + srcx) * 4;
+
+ info.convert_func(srcptr, srcstride,
+ image->data,
+ image->bytes_per_line, w, h);
+
+ if (info.useshm)
+ {
+ XShmPutImage(info.display, d, gc, image,
+ 0, 0, dstx + ax, dsty + ay,
+ w, h, False);
+ }
+ else
+ {
+ XPutImage(info.display, d, gc, image,
+ 0, 0,
+ dstx + ax,
+ dsty + ay,
+ w, h);
+ }
+ }
+ }
+}
+
+/*
+ *
+ */
+
+#define PARAMS \
+ const unsigned char * src, \
+ int srcstride, \
+ unsigned char * dst, \
+ int dststride, \
+ int w, \
+ int h
+
+/*
+ * Convert byte:ARGB8888 to various formats
+ */
+
+static void
+ximage_convert_argb8888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[x * 4 + 0] = src[x * 4 + 0];
+ dst[x * 4 + 1] = src[x * 4 + 1];
+ dst[x * 4 + 2] = src[x * 4 + 2];
+ dst[x * 4 + 3] = src[x * 4 + 3];
+ }
+ dst += dststride;
+ src += srcstride;
+ }
+}
+
+static void
+ximage_convert_bgra8888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[x * 4 + 0] = src[x * 4 + 3];
+ dst[x * 4 + 1] = src[x * 4 + 2];
+ dst[x * 4 + 2] = src[x * 4 + 1];
+ dst[x * 4 + 3] = src[x * 4 + 0];
+ }
+ dst += dststride;
+ src += srcstride;
+ }
+}
+
+static void
+ximage_convert_abgr8888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[x * 4 + 0] = src[x * 4 + 0];
+ dst[x * 4 + 1] = src[x * 4 + 3];
+ dst[x * 4 + 2] = src[x * 4 + 2];
+ dst[x * 4 + 3] = src[x * 4 + 1];
+ }
+ dst += dststride;
+ src += srcstride;
+ }
+}
+
+static void
+ximage_convert_rgba8888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[x * 4 + 0] = src[x * 4 + 1];
+ dst[x * 4 + 1] = src[x * 4 + 2];
+ dst[x * 4 + 2] = src[x * 4 + 3];
+ dst[x * 4 + 3] = src[x * 4 + 0];
+ }
+ dst += dststride;
+ src += srcstride;
+ }
+}
+
+/* bgr/rgb have yet to recieve some MMX love ;-) */
+
+static void
+ximage_convert_bgr888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[3*x + 0] = src[4*x + 3];
+ dst[3*x + 1] = src[4*x + 2];
+ dst[3*x + 2] = src[4*x + 1];
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_rgb888(PARAMS)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ dst[3*x + 0] = src[4*x + 1];
+ dst[3*x + 1] = src[4*x + 2];
+ dst[3*x + 2] = src[4*x + 3];
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_rgb565(PARAMS)
+{
+ unsigned char r, g, b;
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ r = src[4*x + 1];
+ g = src[4*x + 2];
+ b = src[4*x + 3];
+ ((unsigned short *)dst)[x] =
+ ((r & 0xF8) << 8) |
+ ((g & 0xFC) << 3) |
+ (b >> 3);
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_rgb565_br(PARAMS)
+{
+ unsigned char r, g, b;
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ r = src[4*x + 1];
+ g = src[4*x + 2];
+ b = src[4*x + 3];
+ /* final word is:
+ g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5
+ */
+ ((unsigned short *)dst)[x] =
+ (r & 0xF8) |
+ ((g & 0xE0) >> 5) |
+ ((g & 0x1C) << 11) |
+ ((b & 0xF8) << 5);
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_rgb555(PARAMS)
+{
+ unsigned char r, g, b;
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ r = src[4*x + 1];
+ g = src[4*x + 2];
+ b = src[4*x + 3];
+ ((unsigned short *)dst)[x] =
+ ((r & 0xF8) << 7) |
+ ((g & 0xF8) << 2) |
+ (b >> 3);
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_rgb555_br(PARAMS)
+{
+ unsigned char r, g, b;
+ int x, y;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ r = src[4*x + 1];
+ g = src[4*x + 2];
+ b = src[4*x + 3];
+ /* final word is:
+ g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6
+ */
+ ((unsigned short *)dst)[x] =
+ ((r & 0xF8) >> 1) |
+ ((g & 0xC0) >> 6) |
+ ((g & 0x38) << 10) |
+ ((b & 0xF8) << 5);
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+static void
+ximage_convert_bgr233(PARAMS)
+{
+ unsigned char r, g, b;
+ int x,y;
+ for(y = 0; y < h; y++) {
+ for(x = 0; x < w; x++) {
+ r = src[4*x + 1];
+ g = src[4*x + 2];
+ b = src[4*x + 3];
+ /* format: b7 b6 g7 g6 g5 r7 r6 r5 */
+ dst[x] = (b&0xC0) | ((g>>2)&0x38) | ((r>>5)&0x7);
+ }
+ src += srcstride;
+ dst += dststride;
+ }
+}
+
+ximage_convert_func_t ximage_convert_funcs[] = {
+ ximage_convert_argb8888,
+ ximage_convert_bgra8888,
+ ximage_convert_rgba8888,
+ ximage_convert_abgr8888,
+ ximage_convert_rgb888,
+ ximage_convert_bgr888,
+ ximage_convert_rgb565,
+ ximage_convert_rgb565_br,
+ ximage_convert_rgb555,
+ ximage_convert_rgb555_br,
+ ximage_convert_bgr233,
+};
+