diff options
Diffstat (limited to 'zbar/window/x.c')
-rw-r--r-- | zbar/window/x.c | 338 |
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); +} |