summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-03-16 21:11:39 +0000
committerDana Jansens <danakj@orodu.net>2003-03-16 21:11:39 +0000
commitf8a47de5ec444c452093371e3db16857eb39a490 (patch)
tree31db2567842d98232775f9980f7a8d2586c0ac71 /render
parent8ba0586bcbdc7fe9648f1063812126d71a041670 (diff)
merge the C branch into HEAD
Diffstat (limited to 'render')
-rw-r--r--render/.cvsignore6
-rw-r--r--render/Makefile.am17
-rw-r--r--render/color.c57
-rw-r--r--render/color.h19
-rw-r--r--render/font.c75
-rw-r--r--render/gradient.c320
-rw-r--r--render/gradient.h14
-rw-r--r--render/render.c190
-rw-r--r--render/render.h145
-rw-r--r--render/test.c81
10 files changed, 924 insertions, 0 deletions
diff --git a/render/.cvsignore b/render/.cvsignore
new file mode 100644
index 00000000..8ce2c9d1
--- /dev/null
+++ b/render/.cvsignore
@@ -0,0 +1,6 @@
+? .deps
+? .libs
+? Makefile
+? Makefile.in
+? rendertest
+
diff --git a/render/Makefile.am b/render/Makefile.am
new file mode 100644
index 00000000..dfe8d5fb
--- /dev/null
+++ b/render/Makefile.am
@@ -0,0 +1,17 @@
+CPPFLAGS=$(XFT_CFLAGS) $(PYTHON_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
+-DG_LOG_DOMAIN=\"Render\"
+
+LIBS=$(XFT_LIBS) $(PYTHON_LIBS) $(GLIB_LIBS) @LIBS@
+
+noinst_PROGRAMS=rendertest
+rendertest_SOURCES=$(librender_a_SOURCES)
+
+noinst_LIBRARIES=librender.a
+librender_a_SOURCES=render.c test.c gradient.c color.c
+
+noinst_HEADERS=render.h gradient.h color.h
+
+MAINTAINERCLEANFILES= Makefile.in
+
+distclean-local:
+ $(RM) *\~ *.orig *.rej .\#*
diff --git a/render/color.c b/render/color.c
new file mode 100644
index 00000000..83c2aa37
--- /dev/null
+++ b/render/color.c
@@ -0,0 +1,57 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "render.h"
+#include "color.h"
+#include "../kernel/openbox.h"
+void color_allocate_gc(color_rgb *in)
+{
+ XGCValues gcv;
+
+ gcv.foreground = in->pixel;
+ gcv.cap_style = CapProjecting;
+ in->gc = XCreateGC(ob_display, ob_root, GCForeground | GCCapStyle, &gcv);
+}
+
+color_rgb *color_parse(char *colorname)
+{
+ g_assert(colorname != NULL);
+ // get rgb values from colorname
+
+ XColor xcol;
+ xcol.red = 0;
+ xcol.green = 0;
+ xcol.blue = 0;
+ xcol.pixel = 0;
+ if (!XParseColor(ob_display, render_colormap, colorname, &xcol)) {
+ g_warning("unable to parse color '%s'", colorname);
+ return NULL;
+ }
+ return color_new(xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
+}
+
+color_rgb *color_new(int r, int g, int b)
+{
+/* this should be replaced with something far cooler */
+ color_rgb *out;
+ XColor xcol;
+ xcol.red = (r << 8) | r;
+ xcol.green = (g << 8) | g;
+ xcol.blue = (b << 8) | b;
+ if (XAllocColor(ob_display, render_colormap, &xcol)) {
+ out = g_new(color_rgb, 1);
+ out->r = xcol.red >> 8;
+ out->g = xcol.green >> 8;
+ out->b = xcol.blue >> 8;
+ out->gc = None;
+ out->pixel = xcol.pixel;
+ return out;
+ }
+ return NULL;
+}
+
+void color_free(color_rgb *c)
+{
+ if (c->gc != None)
+ XFreeGC(ob_display, c->gc);
+ free(c);
+}
diff --git a/render/color.h b/render/color.h
new file mode 100644
index 00000000..1e0cc57a
--- /dev/null
+++ b/render/color.h
@@ -0,0 +1,19 @@
+#ifndef __color_h
+#define __color_h
+
+#include <X11/Xlib.h>
+
+typedef struct color_rgb {
+ int r;
+ int g;
+ int b;
+ unsigned long pixel;
+ GC gc;
+} color_rgb;
+
+void color_allocate_gc(color_rgb *in);
+color_rgb *color_parse(char *colorname);
+color_rgb *color_new(int r, int g, int b);
+void color_free(color_rgb *in);
+
+#endif /* __color_h */
diff --git a/render/font.c b/render/font.c
new file mode 100644
index 00000000..eb72feb1
--- /dev/null
+++ b/render/font.c
@@ -0,0 +1,75 @@
+#include "font.h"
+
+#include "../src/gettext.h"
+#define _(str) gettext(str)
+
+font_open(const std::string &fontstring,
+ bool shadow, unsigned char offset, unsigned char tint)
+{
+ assert(screen_num >= 0);
+ assert(tint <= CHAR_MAX);
+
+ if (!_xft_init) {
+ if (!XftInit(0)) {
+ printf(_("Couldn't initialize Xft.\n\n"));
+ ::exit(3);
+ }
+#ifdef DEBUG
+ int version = XftGetVersion();
+ printf("Using Xft %d.%d.%d (Built against %d.%d.%d).\n",
+ version / 10000 % 100, version / 100 % 100, version % 100,
+ XFT_MAJOR, XFT_MINOR, XFT_REVISION);
+#endif
+ _xft_init = true;
+ }
+
+ if ((_xftfont = XftFontOpenName(ob_display, _screen_num,
+ fontstring)))
+ return;
+
+ printf(_("Unable to load font: %s\n"), _fontstring.c_str());
+ printf(_("Trying fallback font: %s\n"), "fixed");
+
+ if ((_xftfont = XftFontOpenName(ob_display, _screen_num,
+ "fixed")))
+ return;
+
+ printf(_("Unable to load font: %s\n"), "fixed");
+ printf(_("Aborting!.\n"));
+
+ exit(3); // can't continue without a font
+}
+
+
+destroy_fonts(void)
+{
+ if (_xftfont)
+ XftFontClose(ob_display, _xftfont);
+}
+
+
+int font_measure_string(const char *)
+{
+ XGlyphInfo info;
+
+ if (string.utf8())
+ XftTextExtentsUtf8(**display, _xftfont,
+ (FcChar8*)string.c_str(), string.bytes(), &info);
+ else
+ XftTextExtents8(ob_display, _xftfont,
+ (FcChar8*)string.c_str(), string.bytes(), &info);
+
+ return (signed) info.xOff + (_shadow ? _offset : 0);
+}
+
+
+int font_height(void)
+{
+ return (signed) _xftfont->height + (_shadow ? _offset : 0);
+}
+
+
+int font_max_char_width(void)
+{
+ return (signed) _xftfont->max_advance_width;
+}
diff --git a/render/gradient.c b/render/gradient.c
new file mode 100644
index 00000000..8ea86aa1
--- /dev/null
+++ b/render/gradient.c
@@ -0,0 +1,320 @@
+#include <stdio.h>
+#include <glib.h>
+#include "render.h"
+#include "gradient.h"
+#include "../kernel/openbox.h"
+#include "color.h"
+
+void gradient_render(Surface *sf, int w, int h)
+{
+ pixel32 *data = sf->data.planar.pixel_data;
+ pixel32 current;
+ unsigned int r,g,b;
+ int off, x;
+
+ switch (sf->data.planar.grad) {
+ case Background_Solid: /* already handled */
+ return;
+ case Background_Vertical:
+ gradient_vertical(sf, w, h);
+ break;
+ case Background_Horizontal:
+ gradient_horizontal(sf, w, h);
+ break;
+ case Background_Diagonal:
+ gradient_diagonal(sf, w, h);
+ break;
+ case Background_CrossDiagonal:
+ gradient_crossdiagonal(sf, w, h);
+ break;
+ default:
+ printf("unhandled gradient\n");
+ }
+
+ if (sf->data.planar.relief == Flat && sf->data.planar.border) {
+ r = sf->data.planar.border_color->r;
+ g = sf->data.planar.border_color->g;
+ b = sf->data.planar.border_color->b;
+ current = (r << default_red_shift)
+ + (g << default_green_shift)
+ + (b << default_blue_shift);
+ for (off = 0, x = 0; x < w; ++x, off++) {
+ *(data + off) = current;
+ *(data + off + ((h-1) * w)) = current;
+ }
+ for (off = 0, x = 0; x < h; ++x, off++) {
+ *(data + (off * w)) = current;
+ *(data + (off * w) + w - 1) = current;
+ }
+ }
+
+ if (sf->data.planar.relief != Flat) {
+ if (sf->data.planar.bevel == Bevel1) {
+ for (off = 1, x = 1; x < w - 1; ++x, off++)
+ highlight(data + off,
+ data + off + (h-1) * w,
+ sf->data.planar.relief==Raised);
+ for (off = 0, x = 0; x < h; ++x, off++)
+ highlight(data + off * w,
+ data + off * w + w - 1,
+ sf->data.planar.relief==Raised);
+ }
+
+ if (sf->data.planar.bevel == Bevel2) {
+ for (off = 2, x = 2; x < w - 2; ++x, off++)
+ highlight(data + off + w,
+ data + off + (h-2) * w,
+ sf->data.planar.relief==Raised);
+ for (off = 1, x = 1; x < h-1; ++x, off++)
+ highlight(data + off * w + 1,
+ data + off * w + w - 2,
+ sf->data.planar.relief==Raised);
+ }
+ }
+}
+
+
+
+void gradient_vertical(Surface *sf, int w, int h)
+{
+ pixel32 *data = sf->data.planar.pixel_data;
+ pixel32 current;
+ float dr, dg, db;
+ unsigned int r,g,b;
+ int x, y;
+
+ dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
+ dr/= (float)h;
+
+ dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
+ dg/= (float)h;
+
+ db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
+ db/= (float)h;
+
+ for (y = 0; y < h; ++y) {
+ r = sf->data.planar.primary->r + (int)(dr * y);
+ g = sf->data.planar.primary->g + (int)(dg * y);
+ b = sf->data.planar.primary->b + (int)(db * y);
+ current = (r << default_red_shift)
+ + (g << default_green_shift)
+ + (b << default_blue_shift);
+ for (x = 0; x < w; ++x, ++data)
+ *data = current;
+ }
+}
+
+void gradient_horizontal(Surface *sf, int w, int h)
+{
+ pixel32 *data = sf->data.planar.pixel_data;
+ pixel32 current;
+ float dr, dg, db;
+ unsigned int r,g,b;
+ int x, y;
+
+ dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
+ dr/= (float)w;
+
+ dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
+ dg/= (float)w;
+
+ db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
+ db/= (float)w;
+
+ for (x = 0; x < w; ++x, ++data) {
+ r = sf->data.planar.primary->r + (int)(dr * x);
+ g = sf->data.planar.primary->g + (int)(dg * x);
+ b = sf->data.planar.primary->b + (int)(db * x);
+ current = (r << default_red_shift)
+ + (g << default_green_shift)
+ + (b << default_blue_shift);
+ for (y = 0; y < h; ++y)
+ *(data + y*w) = current;
+ }
+}
+
+void gradient_diagonal(Surface *sf, int w, int h)
+{
+ pixel32 *data = sf->data.planar.pixel_data;
+ pixel32 current;
+ float drx, dgx, dbx, dry, dgy, dby;
+ unsigned int r,g,b;
+ int x, y;
+
+ for (y = 0; y < h; ++y) {
+ drx = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
+ dry = drx/(float)h;
+ drx/= (float)w;
+
+ dgx = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
+ dgy = dgx/(float)h;
+ dgx/= (float)w;
+
+ dbx = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
+ dby = dbx/(float)h;
+ dbx/= (float)w;
+ for (x = 0; x < w; ++x, ++data) {
+ r = sf->data.planar.primary->r + ((int)(drx * x) + (int)(dry * y))/2;
+ g = sf->data.planar.primary->g + ((int)(dgx * x) + (int)(dgy * y))/2;
+ b = sf->data.planar.primary->b + ((int)(dbx * x) + (int)(dby * y))/2;
+ current = (r << default_red_shift)
+ + (g << default_green_shift)
+ + (b << default_blue_shift);
+ *data = current;
+ }
+ }
+}
+
+void gradient_crossdiagonal(Surface *sf, int w, int h)
+{
+ pixel32 *data = sf->data.planar.pixel_data;
+ pixel32 current;
+ float drx, dgx, dbx, dry, dgy, dby;
+ unsigned int r,g,b;
+ int x, y;
+
+ for (y = 0; y < h; ++y) {
+ drx = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
+ dry = drx/(float)h;
+ drx/= (float)w;
+
+ dgx = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
+ dgy = dgx/(float)h;
+ dgx/= (float)w;
+
+ dbx = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
+ dby = dbx/(float)h;
+ dbx/= (float)w;
+ for (x = w; x > 0; --x, ++data) {
+ r = sf->data.planar.primary->r + ((int)(drx * (x-1)) + (int)(dry * y))/2;
+ g = sf->data.planar.primary->g + ((int)(dgx * (x-1)) + (int)(dgy * y))/2;
+ b = sf->data.planar.primary->b + ((int)(dbx * (x-1)) + (int)(dby * y))/2;
+ current = (r << default_red_shift)
+ + (g << default_green_shift)
+ + (b << default_blue_shift);
+ *data = current;
+ }
+ }
+}
+
+void highlight(pixel32 *x, pixel32 *y, gboolean raised)
+{
+ int r, g, b;
+
+ pixel32 *up, *down;
+ if (raised) {
+ up = x;
+ down = y;
+ } else {
+ up = y;
+ down = x;
+ }
+ r = (*up >> default_red_shift) & 0xFF;
+ r += r >> 1;
+ g = (*up >> default_green_shift) & 0xFF;
+ g += g >> 1;
+ b = (*up >> default_blue_shift) & 0xFF;
+ b += b >> 1;
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ *up = (r << default_red_shift) + (g << default_green_shift)
+ + (b << default_blue_shift);
+
+ r = (*down >> default_red_shift) & 0xFF;
+ r = (r >> 1) + (r >> 2);
+ g = (*down >> default_green_shift) & 0xFF;
+ g = (g >> 1) + (g >> 2);
+ b = (*down >> default_blue_shift) & 0xFF;
+ b = (b >> 1) + (b >> 2);
+ *down = (r << default_red_shift) + (g << default_green_shift)
+ + (b << default_blue_shift);
+}
+
+void gradient_solid(Appearance *l, int w, int h)
+{
+ int i;
+ PlanarSurface *sp = &l->surface.data.planar;
+ int left = 0, top = 0, right = w - 1, bottom = h - 1;
+
+ if (sp->primary->gc == None)
+ color_allocate_gc(sp->primary);
+ XFillRectangle(ob_display, l->pixmap, sp->primary->gc
+ , 0, 0, w, h);
+
+ if (l->surface.data.planar.interlaced) {
+ if (sp->secondary->gc == None)
+ color_allocate_gc(sp->secondary);
+ for (i = 0; i < h; i += 2)
+ XDrawLine(ob_display, l->pixmap, sp->secondary->gc,
+ 0, i, w, i);
+ }
+/*
+ switch (texture.relief()) {
+ case RenderTexture::Raised:
+ switch (texture.bevel()) {
+ case RenderTexture::Bevel1:
+ XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
+ left, bottom, right, bottom);
+ XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
+ right, bottom, right, top);
+
+ XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
+ left, top, right, top);
+ XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
+ left, bottom, left, top);
+ break;
+ case RenderTexture::Bevel2:
+ XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
+ left + 1, bottom - 2, right - 2, bottom - 2);
+ XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
+ right - 2, bottom - 2, right - 2, top + 1);
+
+ XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
+ left + 1, top + 1, right - 2, top + 1);
+ XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
+ left + 1, bottom - 2, left + 1, top + 1);
+ break;
+ default:
+ assert(false); // unhandled RenderTexture::BevelType
+ }
+ break;
+ case RenderTexture::Sunken:
+ switch (texture.bevel()) {
+ case RenderTexture::Bevel1:
+ XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
+ left, bottom, right, bottom);
+ XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
+ right, bottom, right, top);
+
+ XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
+ left, top, right, top);
+ XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
+ left, bottom, left, top);
+ break;
+ case RenderTexture::Bevel2:
+ XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
+ left + 1, bottom - 2, right - 2, bottom - 2);
+ XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
+ right - 2, bottom - 2, right - 2, top + 1);
+
+ XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
+ left + 1, top + 1, right - 2, top + 1);
+ XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
+ left + 1, bottom - 2, left + 1, top + 1);
+
+ break;
+ default:
+ assert(false); // unhandled RenderTexture::BevelType
+ }
+ break;
+ case RenderTexture::Flat:
+ if (texture.border())
+ XDrawRectangle(**display, sf.pixmap(), texture.borderColor().gc(),
+ left, top, right, bottom);
+ break;
+ default:
+ assert(false); // unhandled RenderTexture::ReliefType
+ }
+*/
+}
diff --git a/render/gradient.h b/render/gradient.h
new file mode 100644
index 00000000..626278f5
--- /dev/null
+++ b/render/gradient.h
@@ -0,0 +1,14 @@
+#ifndef __gradient_h
+#define __gradient_h
+
+#include "render.h"
+
+void gradient_render(Surface *sf, int w, int h);
+void gradient_vertical(Surface *sf, int w, int h);
+void gradient_horizontal(Surface *sf, int w, int h);
+void gradient_diagonal(Surface *sf, int w, int h);
+void gradient_crossdiagonal(Surface *sf, int w, int h);
+void gradient_solid(Appearance *l, int w, int h); /* needs access to pixmap */
+void highlight(pixel32 *x, pixel32 *y, gboolean raised);
+
+#endif /* __gradient_h */
diff --git a/render/render.c b/render/render.c
new file mode 100644
index 00000000..cdbf01f5
--- /dev/null
+++ b/render/render.c
@@ -0,0 +1,190 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <glib.h>
+#include "render.h"
+#include "gradient.h"
+#include "../kernel/openbox.h"
+
+int render_depth;
+Visual *render_visual;
+Colormap render_colormap;
+
+void render_startup(void)
+{
+ paint = x_paint;
+
+ render_depth = DefaultDepth(ob_display, ob_screen);
+ render_visual = DefaultVisual(ob_display, ob_screen);
+ render_colormap = DefaultColormap(ob_display, ob_screen);
+
+ if (render_depth < 8) {
+ XVisualInfo vinfo_template, *vinfo_return;
+ // search for a TrueColor Visual... if we can't find one...
+ // we will use the default visual for the screen
+ int vinfo_nitems;
+ int best = -1;
+
+ vinfo_template.screen = ob_screen;
+ vinfo_template.class = TrueColor;
+ vinfo_return = XGetVisualInfo(ob_display,
+ VisualScreenMask | VisualClassMask,
+ &vinfo_template, &vinfo_nitems);
+ if (vinfo_return) {
+ int i;
+ int max_depth = 1;
+ for (i = 0; i < vinfo_nitems; ++i) {
+ if (vinfo_return[i].depth > max_depth) {
+ if (max_depth == 24 && vinfo_return[i].depth > 24)
+ break; // prefer 24 bit over 32
+ max_depth = vinfo_return[i].depth;
+ best = i;
+ }
+ }
+ if (max_depth < render_depth) best = -1;
+ }
+ if (best != -1) {
+ render_depth = vinfo_return[best].depth;
+ render_visual = vinfo_return[best].visual;
+ render_colormap = XCreateColormap(ob_display, ob_root, render_visual,
+ AllocNone);
+ }
+ XFree(vinfo_return);
+ }
+}
+
+void x_paint(Window win, Appearance *l, int w, int h)
+{
+ int i;
+ XImage *im;
+
+ if (w <= 0 || h <= 0) return;
+
+ g_assert(l->surface.type == Surface_Planar);
+// printf("painting window %ld\n", win);
+
+ if (l->pixmap != None) XFreePixmap(ob_display, l->pixmap);
+ l->pixmap = XCreatePixmap(ob_display, ob_root, w, h, render_depth);
+ g_assert(l->pixmap != None);
+
+ if (l->xftdraw != NULL)
+ XftDrawDestroy(l->xftdraw);
+ l->xftdraw = XftDrawCreate(ob_display, l->pixmap, render_visual,
+ render_colormap);
+ g_assert(l->xftdraw != NULL);
+
+ if (l->surface.data.planar.pixel_data != NULL)
+ g_free(l->surface.data.planar.pixel_data);
+ l->surface.data.planar.pixel_data = g_new(pixel32, w * h);
+
+ if (l->surface.data.planar.grad == Background_Solid)
+ gradient_solid(l, w, h);
+ else gradient_render(&l->surface, w, h);
+ for (i = 0; i < l->textures; i++) {
+ printf("I AM DOING SOMETHING NOW\n");
+ }
+//reduce depth
+ if (l->surface.data.planar.grad != Background_Solid) {
+ im = XCreateImage(ob_display, render_visual, render_depth,
+ ZPixmap, 0, NULL, w, h, 32, 0);
+ g_assert(im != None);
+ im->byte_order = endian;
+ im->data = l->surface.data.planar.pixel_data;
+ XPutImage(ob_display, l->pixmap, DefaultGC(ob_display, ob_screen),
+ im, 0, 0, 0, 0, w, h);
+ im->data = NULL;
+ XDestroyImage(im);
+ }
+ XSetWindowBackgroundPixmap(ob_display, win, l->pixmap);
+ XClearWindow(ob_display, win);
+}
+
+/*
+void gl_paint(Window win, Appearance *l)
+{
+ glXMakeCurrent(ob_display, win, gl_context);
+}
+*/
+
+void render_shutdown(void)
+{
+}
+
+Appearance *appearance_new(SurfaceType type, int numtex)
+{
+ PlanarSurface *p;
+ Appearance *out;
+
+ out = g_new(Appearance, 1);
+ out->surface.type = type;
+ out->textures = numtex;
+ out->xftdraw = NULL;
+ if (numtex) out->texture = g_new(Texture, numtex);
+ out->pixmap = None;
+
+ switch (type) {
+ case Surface_Planar:
+ p = &out->surface.data.planar;
+ p->primary = NULL;
+ p->secondary = NULL;
+ p->border_color = NULL;
+ p->pixel_data = NULL;
+ break;
+ }
+ return out;
+}
+
+Appearance *appearance_copy(Appearance *orig)
+{
+ PlanarSurface *spo, *spc;
+ Appearance *copy = g_new(Appearance, 1);
+ copy->surface.type = orig->surface.type;
+ switch (orig->surface.type) {
+ case Surface_Planar:
+ spo = &(orig->surface.data.planar);
+ spc = &(copy->surface.data.planar);
+ spc->grad = spo->grad;
+ spc->relief = spo->relief;
+ spc->bevel = spo->bevel;
+ if (spo->primary != NULL)
+ spc->primary = color_new(spo->primary->r,
+ spo->primary->g,
+ spo->primary->b);
+ else spc->primary = NULL;
+
+ if (spo->secondary != NULL)
+ spc->secondary = color_new(spo->secondary->r,
+ spo->secondary->g,
+ spo->secondary->b);
+ else spc->secondary = NULL;
+
+ if (spo->border_color != NULL)
+ spc->border_color = color_new(spo->border_color->r,
+ spo->border_color->g,
+ spo->border_color->b);
+ else spc->border_color = NULL;
+
+ spc->interlaced = spo->interlaced;
+ spc->border = spo->border;
+ spc->pixel_data = NULL;
+ break;
+ }
+ copy->textures = orig->textures;
+ copy->texture = NULL; /* XXX FIX ME */
+ copy->pixmap = None;
+ copy->xftdraw = NULL;
+ return copy;
+}
+
+void appearance_free(Appearance *a)
+{
+ PlanarSurface *p;
+ if (a->textures)
+ g_free(a->texture);
+ if (a->surface.type == Surface_Planar) {
+ p = &a->surface.data.planar;
+ if (p->primary != NULL) color_free(p->primary);
+ if (p->secondary != NULL) color_free(p->secondary);
+ if (p->border_color != NULL) color_free(p->border_color);
+ }
+ g_free(a);
+}
diff --git a/render/render.h b/render/render.h
new file mode 100644
index 00000000..b79fae5e
--- /dev/null
+++ b/render/render.h
@@ -0,0 +1,145 @@
+#ifndef __render_h
+#define __render_h
+
+#include <X11/Xlib.h>
+#define _XFT_NO_COMPAT_ /* no Xft 1 API */
+#include <X11/Xft/Xft.h>
+#include <glib.h>
+#include "color.h"
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#else
+# ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+# endif
+#endif
+
+#ifdef HAVE_STDINT_H
+typedef uint32_t pixel32;
+typedef uint16_t pixel16;
+#else
+typedef u_int32_t pixel32;
+typedef u_int16_t pixel16;
+#endif /* HAVE_STDINT_H */
+
+#if (G_ENDIAN == G_BIG_ENDIAN)
+#define default_red_shift 0
+#define default_green_shift 8
+#define default_blue_shift 16
+#define endian MSBFirst
+#else
+#define default_red_shift 16
+#define default_green_shift 8
+#define default_blue_shift 0
+#define endian LSBFirst
+#endif /* G_ENDIAN == G_BIG_ENDIAN */
+
+typedef enum {
+ Surface_Planar,
+ Surface_Nonplanar
+} SurfaceType;
+
+typedef enum {
+ Flat,
+ Raised,
+ Sunken
+} ReliefType;
+
+typedef enum {
+ Bevel1,
+ Bevel2
+} BevelType;
+
+typedef enum {
+ Background_ParentRelative,
+ Background_Solid,
+ Background_Horizontal,
+ Background_Vertical,
+ Background_Diagonal,
+ Background_CrossDiagonal,
+ Background_PipeCross,
+ Background_Rectangle,
+ Background_Pyramid,
+ Background_Elliptic
+} SurfaceColorType;
+
+typedef enum {
+ Bitmask,
+ Text,
+ RGBA
+} TextureType;
+
+typedef struct PlanarSurface {
+ SurfaceColorType grad;
+ ReliefType relief;
+ BevelType bevel;
+ color_rgb *primary;
+ color_rgb *secondary;
+ color_rgb *border_color;
+ gboolean interlaced;
+ gboolean border;
+ pixel32 *pixel_data;
+} PlanarSurface;
+
+typedef struct NonplanarSurface {
+ int poo;
+} NonplanarSurface;
+
+typedef union {
+ PlanarSurface planar;
+ NonplanarSurface nonplanar;
+} SurfaceData;
+
+typedef struct Surface {
+ SurfaceType type;
+ SurfaceColorType colortype;
+ SurfaceData data;
+} Surface;
+
+typedef struct TextureText {
+ color_rgb *color;
+ char *string;
+} TextureText;
+
+typedef struct TextureMask {
+ color_rgb *color;
+} TextureMask;
+
+typedef struct TextureRGBA {
+ int poo;
+} TextureRGBA;
+
+typedef union {
+ TextureRGBA rgba;
+ TextureText text;
+ TextureMask mask;
+} TextureData;
+
+typedef struct Texture {
+ TextureType type;
+ TextureData data;
+} Texture;
+
+typedef struct Appearance {
+ Surface surface;
+ int textures;
+ Texture *texture;
+ Pixmap pixmap;
+ XftDraw *xftdraw;
+} Appearance;
+
+extern Visual *render_visual;
+extern int render_depth;
+extern Colormap render_colormap;
+
+void (*paint)(Window win, Appearance *l, int w, int h);
+
+void render_startup(void);
+void init_appearance(Appearance *l);
+void x_paint(Window win, Appearance *l, int w, int h);
+void render_shutdown(void);
+Appearance *appearance_new(SurfaceType type, int numtex);
+Appearance *appearance_copy(Appearance *a);
+void appearance_free(Appearance *a);
+#endif /*__render_h*/
diff --git a/render/test.c b/render/test.c
new file mode 100644
index 00000000..114819af
--- /dev/null
+++ b/render/test.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/shape.h>
+#include <GL/glx.h>
+#include <string.h>
+#include <stdlib.h>
+#include "render.h"
+#include <glib.h>
+
+static int x_error_handler(Display * disp, XErrorEvent * error)
+{
+ char buf[1024];
+ XGetErrorText(disp, error->error_code, buf, 1024);
+ printf("%s\n", buf);
+ return 0;
+}
+
+Display *ob_display;
+int ob_screen;
+Window ob_root;
+
+int main()
+{
+ Window win;
+ GC gc;
+ Pixmap pm;
+ Appearance *look;
+
+ int grabbed = 0;
+ Window root;
+ XGCValues values;
+ XEvent report;
+ int h = 500, w = 500, tmp;
+ XVisualInfo *vi;
+ int i;
+
+ ob_display = XOpenDisplay(NULL);
+ XSetErrorHandler(x_error_handler);
+ ob_screen = DefaultScreen(ob_display);
+ ob_root = RootWindow(ob_display, ob_screen);
+ win =
+ XCreateWindow(ob_display, RootWindow(ob_display, 0)
+ , 10, 10, w, h, 10,
+ CopyFromParent, // depth
+ CopyFromParent, // class
+ CopyFromParent, // visual
+ 0, // valuemask
+ 0); // attributes
+ XMapWindow(ob_display, win);
+ XSelectInput(ob_display, win, ExposureMask | StructureNotifyMask);
+ root = RootWindow (ob_display, DefaultScreen (ob_display));
+ render_startup();
+
+ look = appearance_new(Surface_Planar, 0);
+ look->surface.data.planar.grad = Background_Solid;
+ look->surface.data.planar.secondary = color_new(0xFF, 0xFF, 0xFF);
+ look->surface.data.planar.primary = color_parse("Red");
+ look->surface.data.planar.interlaced = FALSE;
+ if (ob_display == NULL) {
+ fprintf(stderr, "couldn't connect to X server :0\n");
+ return 0;
+ }
+
+ paint(win, look, 500, 500);
+ while (1) {
+ XNextEvent(ob_display, &report);
+ switch (report.type) {
+ case Expose:
+ break;
+ case ConfigureNotify:
+ w = report.xconfigure.width;
+ h = report.xconfigure.height;
+ paint(win, look, w, h);
+ printf("confignotify %i:%i\n", w, h);
+ break;
+ }
+
+ }
+
+ return 1;
+}