From bfbc623c960ce4ba4ceed0ed2aa7ed2821a6e556 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 8 Oct 2013 18:34:35 +0200 Subject: [PATCH] Experiments with Xft rendering --- Makefile | 7 ++- test.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 test.c diff --git a/Makefile b/Makefile index 0434fa3..31eeafb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ ARCHIVE=osdd-$(VERSION).tar.gz CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99 -all: osdd osdc osd-batt osd-alsa +# all: osdd osdc osd-batt osd-alsa +all: test osdd: osdd.o util.o osdc: osdc.o util.o client.o @@ -19,6 +20,10 @@ osd-batt: LDLIBS+=-lX11 osd-alsa.o: CFLAGS+=$(shell pkg-config --cflags alsa) osd-alsa: LDLIBS+=$(shell pkg-config --libs alsa) -lX11 +test.o: CFLAGS+=$(shell pkg-config --cflags xft) +test: LDFLAGS+=$(shell pkg-config --libs xft) -l Xext +test: test.o util.o + clean: rm -f *~ *.o TAGS core osdd osdc osd-batt osd-alsa diff --git a/test.c b/test.c new file mode 100644 index 0000000..676a1e5 --- /dev/null +++ b/test.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG +#include "osd.h" + +struct osd_state { + Display *dpy; + int screen; + Visual *visual; + Colormap cmap; + int depth; + int screen_width; + int screen_height; + Window win; + Pixmap mask_bitmap; + Pixmap image_pixmap; + GC gc; + GC mask_gc; + + // Xft stuff + XftFont *font; + XftDraw *xft_draw; +}; + +int +main(int argc, char **argv) +{ + XInitThreads(); + + struct osd_state osd_static; + bzero(&osd_static, sizeof(osd_static)); + struct osd_state *osd = &osd_static; + + osd->dpy = XOpenDisplay(NULL); + if (!osd->dpy) + die("Cannot open display"); + + int event_basep, error_basep; + if (!XShapeQueryExtension(osd->dpy, &event_basep, &error_basep)) + die("XShape extension not supported by X server, giving up"); + + osd->screen = XDefaultScreen(osd->dpy); + osd->visual = XDefaultVisual(osd->dpy, osd->screen); + osd->depth = XDefaultDepth(osd->dpy, osd->screen); + osd->cmap = DefaultColormap(osd->dpy, osd->screen); + + // These can change. And what about Xinerama? + osd->screen_width = XDisplayWidth(osd->dpy, osd->screen); + osd->screen_height = XDisplayHeight(osd->dpy, osd->screen); + + XSetWindowAttributes win_attr = { + .override_redirect = 0, // FIXME: 1 + }; + osd->win = XCreateWindow(osd->dpy, + XRootWindow(osd->dpy, osd->screen), + 0, 0, + osd->screen_width, osd->screen_height, + 0, + osd->depth, + CopyFromParent, + osd->visual, + CWOverrideRedirect, + &win_attr); + XStoreName(osd->dpy, osd->win, "OSD"); + + // FIXME: Size + osd->mask_bitmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, 1); + osd->image_pixmap = XCreatePixmap(osd->dpy, osd->win, osd->screen_width, osd->screen_height, osd->depth); + DBG("depth = %d\n", osd->depth); + + XGCValues gcv = { + .graphics_exposures = 0, + }; + osd->gc = XCreateGC(osd->dpy, osd->win, GCGraphicsExposures, &gcv); + osd->mask_gc = XCreateGC(osd->dpy, osd->mask_bitmap, GCGraphicsExposures, &gcv); + + XSetBackground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen)); + XSetForeground(osd->dpy, osd->gc, BlackPixel(osd->dpy, osd->screen)); + + XSetBackground(osd->dpy, osd->mask_gc, WhitePixel(osd->dpy, osd->screen)); + XSetForeground(osd->dpy, osd->mask_gc, BlackPixel(osd->dpy, osd->screen)); + + // FIXME: Stay on top + + XFillRectangle(osd->dpy, osd->image_pixmap, osd->gc, 0, 0, osd->screen_width, osd->screen_height); + + osd->font = XftFontOpenName(osd->dpy, osd->screen, "times-64"); + if (!osd->font) + die("Cannot open font"); + + osd->xft_draw = XftDrawCreate(osd->dpy, osd->image_pixmap, osd->visual, osd->cmap); + if (!osd->xft_draw) + die("Cannot create XftDraw"); + + XRenderColor xrc = { .red = 0, .green = 0xffff, .blue = 0, .alpha = 0xffff }; + XftColor xfc; + if (!XftColorAllocValue(osd->dpy, osd->visual, osd->cmap, &xrc, &xfc)) + die("XftColorAllocValue failed"); + const unsigned char str[] = "Žluťoučká vlkodlačice"; + XftDrawStringUtf8(osd->xft_draw, &xfc, osd->font, 100, 100, str, strlen((char *) str)); + + XGlyphInfo gi; + XftTextExtentsUtf8(osd->dpy, osd->font, str, strlen((char *) str), &gi); + DBG("Glyph info: (%d,%d)+(%d,%d) off (%d,%d)\n", gi.x, gi.y, gi.width, gi.height, gi.xOff, gi.yOff); + XftDrawRect(osd->xft_draw, &xfc, 100 + gi.x, 100 - gi.y, gi.width, gi.height); + + XftDrawRect(osd->xft_draw, &xfc, 30, 30, 50, 50); + + XSelectInput(osd->dpy, osd->win, ExposureMask); + XMapRaised(osd->dpy, osd->win); + XFlush(osd->dpy); + + struct pollfd pfd = { + .fd = ConnectionNumber(osd->dpy), + .events = POLLIN, + }; + + for (;;) + { + timestamp_t now = get_current_time(); + timestamp_t wait_until = now - 1; + + DBG("... waiting for %d ms\n", (int)(wait_until - now)); + poll(&pfd, 1, wait_until - now); + if (pfd.revents & POLLIN) + { + while (XPending(osd->dpy)) + { + XEvent ev; + XNextEvent(osd->dpy, &ev); + switch (ev.type) + { + case Expose: + { + XExposeEvent *ex = &ev.xexpose; + DBG("Expose cnt=%d (%d,%d)+(%d,%d)\n", ex->count, ex->x, ex->y, ex->width, ex->height); + XCopyArea(osd->dpy, osd->image_pixmap, osd->win, osd->gc, ex->x, ex->y, ex->width, ex->height, ex->x, ex->y); + break; + } + default: + DBG("Event %d\n", ev.type); + } + } + } + } + + // FIXME: Cleanup +} -- 2.39.2