summaryrefslogtreecommitdiffstats
path: root/zbar/window/x.c
diff options
context:
space:
mode:
Diffstat (limited to 'zbar/window/x.c')
-rw-r--r--zbar/window/x.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/zbar/window/x.c b/zbar/window/x.c
new file mode 100644
index 0000000..f4284be
--- /dev/null
+++ b/zbar/window/x.c
@@ -0,0 +1,338 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "x.h"
+#include <ctype.h>
+#include "image.h"
+#include "window.h"
+
+#ifndef ZBAR_OVERLAY_FONT
+#define ZBAR_OVERLAY_FONT "-*-fixed-medium-r-*-*-*-120-75-75-*-*-ISO8859-1"
+#endif
+
+static inline unsigned long window_alloc_color(zbar_window_t *w, Colormap cmap,
+ unsigned short r,
+ unsigned short g,
+ unsigned short b)
+{
+ XColor color;
+ color.red = r;
+ color.green = g;
+ color.blue = b;
+ color.flags = 0;
+ XAllocColor(w->display, cmap, &color);
+ return (color.pixel);
+}
+
+static inline int window_alloc_colors(zbar_window_t *w)
+{
+ window_state_t *x = w->state;
+ Colormap cmap = DefaultColormap(w->display, DefaultScreen(w->display));
+ int i;
+ for (i = 0; i < 8; i++)
+ x->colors[i] = window_alloc_color(w, cmap, (i & 4) ? (0xcc * 0x101) : 0,
+ (i & 2) ? (0xcc * 0x101) : 0,
+ (i & 1) ? (0xcc * 0x101) : 0);
+
+ x->logo_colors[0] = window_alloc_color(w, cmap, 0xd709, 0x3333, 0x3333);
+ x->logo_colors[1] = window_alloc_color(w, cmap, 0xa3d6, 0x0000, 0x0000);
+ return (0);
+}
+
+static inline int window_hide_cursor(zbar_window_t *w)
+{
+ /* FIXME this seems lame...there must be a better way */
+ Pixmap empty = XCreatePixmap(w->display, w->xwin, 1, 1, 1);
+ GC gc = XCreateGC(w->display, empty, 0, NULL);
+ XDrawPoint(w->display, empty, gc, 0, 0);
+ XColor black;
+ memset(&black, 0, sizeof(black));
+ int screen = DefaultScreen(w->display);
+ black.pixel = BlackPixel(w->display, screen);
+ Cursor cursor =
+ XCreatePixmapCursor(w->display, empty, empty, &black, &black, 0, 0);
+ XDefineCursor(w->display, w->xwin, cursor);
+ XFreeCursor(w->display, cursor);
+ XFreeGC(w->display, gc);
+ XFreePixmap(w->display, empty);
+ return (0);
+}
+
+int _zbar_window_resize(zbar_window_t *w)
+{
+ window_state_t *x = w->state;
+ if (!x)
+ return (0);
+
+ int lbw;
+ if (w->height * 8 / 10 <= w->width)
+ lbw = w->height / 36;
+ else
+ lbw = w->width * 5 / 144;
+ if (lbw < 1)
+ lbw = 1;
+ x->logo_scale = lbw;
+ if (x->logo_zbars)
+ XDestroyRegion(x->logo_zbars);
+ x->logo_zbars = XCreateRegion();
+
+ int x0 = w->width / 2;
+ int y0 = w->height / 2;
+ int by0 = y0 - 54 * lbw / 5;
+ int bh = 108 * lbw / 5;
+
+ static const int bx[5] = { -6, -3, -1, 2, 5 };
+ static const int bw[5] = { 1, 1, 2, 2, 1 };
+
+ int i;
+ for (i = 0; i < 5; i++) {
+ XRectangle *bar = &x->logo_bars[i];
+ bar->x = x0 + lbw * bx[i];
+ bar->y = by0;
+ bar->width = lbw * bw[i];
+ bar->height = bh;
+ XUnionRectWithRegion(bar, x->logo_zbars, x->logo_zbars);
+ }
+
+ static const int zx[4] = { -7, 7, -7, 7 };
+ static const int zy[4] = { -8, -8, 8, 8 };
+
+ for (i = 0; i < 4; i++) {
+ x->logo_z[i].x = x0 + lbw * zx[i];
+ x->logo_z[i].y = y0 + lbw * zy[i];
+ }
+ return (0);
+}
+
+int _zbar_window_attach(zbar_window_t *w, void *display, unsigned long win)
+{
+ window_state_t *x = w->state;
+ if (w->display) {
+ /* cleanup existing resources */
+ if (x->gc)
+ XFreeGC(w->display, x->gc);
+ assert(!x->exposed);
+ if (x->font) {
+ XFreeFont(w->display, x->font);
+ x->font = NULL;
+ }
+ if (x->logo_zbars) {
+ XDestroyRegion(x->logo_zbars);
+ x->logo_zbars = NULL;
+ }
+ if (x->exposed) {
+ XDestroyRegion(x->exposed);
+ x->exposed = NULL;
+ }
+ w->display = NULL;
+ }
+ w->xwin = 0;
+
+ if (!display || !win) {
+ if (x) {
+ free(x);
+ w->state = NULL;
+ }
+ return (0);
+ }
+
+ if (!x)
+ x = w->state = calloc(1, sizeof(window_state_t));
+
+ w->display = display;
+ w->xwin = win;
+ x->gc = XCreateGC(display, win, 0, NULL);
+
+ XWindowAttributes attr;
+ XGetWindowAttributes(w->display, w->xwin, &attr);
+ w->width = attr.width;
+ w->height = attr.height;
+ _zbar_window_resize(w);
+
+ window_alloc_colors(w);
+ window_hide_cursor(w);
+
+ /* load overlay font */
+ x->font = XLoadQueryFont(w->display, ZBAR_OVERLAY_FONT);
+ if (x->font)
+ XSetFont(w->display, x->gc, x->font->fid);
+
+ /* FIXME add interface preference override */
+#ifdef HAVE_X11_EXTENSIONS_XVLIB_H
+ if (!_zbar_window_probe_xv(w))
+ return (0);
+#endif
+
+ zprintf(1, "falling back to XImage\n");
+ return (_zbar_window_probe_ximage(w));
+}
+
+int _zbar_window_expose(zbar_window_t *w, int x, int y, int width, int height)
+{
+ window_state_t *xs = w->state;
+ if (!xs->exposed)
+ xs->exposed = XCreateRegion();
+ XRectangle r;
+ r.x = x;
+ r.y = y;
+ r.width = width;
+ r.height = height;
+ XUnionRectWithRegion(&r, xs->exposed, xs->exposed);
+ return (0);
+}
+
+int _zbar_window_begin(zbar_window_t *w)
+{
+ window_state_t *xs = w->state;
+ if (xs->exposed)
+ XSetRegion(w->display, xs->gc, xs->exposed);
+
+ return (0);
+}
+
+int _zbar_window_end(zbar_window_t *w)
+{
+ window_state_t *x = w->state;
+ XSetClipMask(w->display, x->gc, None);
+ if (x->exposed) {
+ XDestroyRegion(x->exposed);
+ x->exposed = NULL;
+ }
+ XFlush(w->display);
+ return (0);
+}
+
+int _zbar_window_clear(zbar_window_t *w)
+{
+ if (!w->display)
+ return (0);
+ window_state_t *x = w->state;
+ int screen = DefaultScreen(w->display);
+ XSetForeground(w->display, x->gc, WhitePixel(w->display, screen));
+ XFillRectangle(w->display, w->xwin, x->gc, 0, 0, w->width, w->height);
+ return (0);
+}
+
+int _zbar_window_draw_polygon(zbar_window_t *w, uint32_t rgb,
+ const point_t *pts, int npts)
+{
+ window_state_t *xs = w->state;
+ XSetForeground(w->display, xs->gc, xs->colors[rgb]);
+
+ point_t org = w->scaled_offset;
+ XPoint xpts[npts + 1];
+ int i;
+ for (i = 0; i < npts; i++) {
+ point_t p = window_scale_pt(w, pts[i]);
+ xpts[i].x = p.x + org.x;
+ xpts[i].y = p.y + org.y;
+ }
+ xpts[npts] = xpts[0];
+
+ XDrawLines(w->display, w->xwin, xs->gc, xpts, npts + 1, CoordModeOrigin);
+
+ return (0);
+}
+
+int _zbar_window_draw_marker(zbar_window_t *w, uint32_t rgb, point_t p)
+{
+ window_state_t *xs = w->state;
+ XSetForeground(w->display, xs->gc, xs->colors[rgb]);
+ XDrawRectangle(w->display, w->xwin, xs->gc, p.x - 2, p.y - 2, 4, 4);
+ XDrawLine(w->display, w->xwin, xs->gc, p.x, p.y - 3, p.x, p.y + 3);
+ XDrawLine(w->display, w->xwin, xs->gc, p.x - 3, p.y, p.x + 3, p.y);
+ return (0);
+}
+
+int _zbar_window_draw_text(zbar_window_t *w, uint32_t rgb, point_t p,
+ const char *text)
+{
+ window_state_t *xs = w->state;
+ if (!xs->font)
+ return (-1);
+
+ XSetForeground(w->display, xs->gc, xs->colors[rgb]);
+
+ int n = 0;
+ while (n < 32 && text[n] && isprint(text[n]))
+ n++;
+
+ int width = XTextWidth(xs->font, text, n);
+ if (p.x >= 0)
+ p.x -= width / 2;
+ else
+ p.x += w->width - width;
+
+ int dy = xs->font->ascent + xs->font->descent;
+ if (p.y >= 0)
+ p.y -= dy / 2;
+ else
+ p.y = w->height + p.y * dy * 5 / 4;
+
+ XDrawString(w->display, w->xwin, xs->gc, p.x, p.y, text, n);
+ return (0);
+}
+
+int _zbar_window_fill_rect(zbar_window_t *w, uint32_t rgb, point_t org,
+ point_t size)
+{
+ window_state_t *xs = w->state;
+ XSetForeground(w->display, xs->gc, xs->colors[rgb]);
+ XFillRectangle(w->display, w->xwin, xs->gc, org.x, org.y, size.x, size.y);
+ return (0);
+}
+
+int _zbar_window_draw_logo(zbar_window_t *w)
+{
+ window_state_t *x = w->state;
+ int screen = DefaultScreen(w->display);
+
+ /* clear to white */
+ XSetForeground(w->display, x->gc, WhitePixel(w->display, screen));
+ XFillRectangle(w->display, w->xwin, x->gc, 0, 0, w->width, w->height);
+
+ if (!x->logo_scale || !x->logo_zbars)
+ return (0);
+
+ XSetForeground(w->display, x->gc, BlackPixel(w->display, screen));
+ XFillRectangles(w->display, w->xwin, x->gc, x->logo_bars, 5);
+
+ XSetLineAttributes(w->display, x->gc, 2 * x->logo_scale, LineSolid,
+ CapRound, JoinRound);
+
+ XSetForeground(w->display, x->gc, x->logo_colors[0]);
+ XDrawLines(w->display, w->xwin, x->gc, x->logo_z, 4, CoordModeOrigin);
+
+ if (x->exposed) {
+ XIntersectRegion(x->logo_zbars, x->exposed, x->exposed);
+ XSetRegion(w->display, x->gc, x->exposed);
+ } else
+ XSetRegion(w->display, x->gc, x->logo_zbars);
+
+ XSetForeground(w->display, x->gc, x->logo_colors[1]);
+ XDrawLines(w->display, w->xwin, x->gc, x->logo_z, 4, CoordModeOrigin);
+
+ /* reset GC */
+ XSetLineAttributes(w->display, x->gc, 0, LineSolid, CapButt, JoinMiter);
+ return (0);
+}