#define TRUNC(x) ((x) >> 6)
#define ROUND(x) (((x)+32) & -64)
-void dest_glyph_map_value(gpointer data)
+void dest_glyph_map_value(gpointer key, gpointer val, gpointer data)
{
- struct GlftGlyph *g = data;
+ struct GlftGlyph *g = val;
glDeleteLists(g->dlist, 1);
- free(data);
+ free(g);
}
struct GlftFont *GlftFontOpen(const char *name)
goto openfail0;
}
- font->glyph_map = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
- dest_glyph_map_value);
-
if (font->char_width)
font->max_advance_width = font->char_width;
else
if (font->minspace) font->height = font->ascent + font->descent;
else font->height = font->face->size->metrics.height >> 6;
+ font->glyph_map = g_hash_table_new(g_int_hash, g_int_equal);
+
return font;
openfail0:
FT_Done_Face(font->face);
FcPatternDestroy(font->pat);
FcCharSetDestroy(font->chars);
+ g_hash_table_foreach(font->glyph_map, dest_glyph_map_value, NULL);
g_hash_table_destroy(font->glyph_map);
free(font);
}
#include <glib.h>
#include <GL/glx.h>
+#include FT_OUTLINE_H
+
+struct GlftWalkState {
+ int drawing;
+ float x, y;
+};
+
+static struct GlftWalkState state;
+
+int GlftMoveToFunc(FT_Vector *to, void *user)
+{
+ state.x = (to->x >> 6) + (to->x & 63)/64;
+ state.y = (to->y >> 6) + (to->y & 63)/64;
+ printf("move to %f:%f\n", state.x, state.y);
+ if (state.drawing) {
+ glEnd();
+ state.drawing = 0;
+ }
+ return 0;
+}
+
+int GlftLineToFunc(FT_Vector *to, void *user)
+{
+ if (!state.drawing) {
+ glBegin(GL_LINES);
+ glVertex2f(state.x, state.y);
+ }
+ state.x = (to->x >> 6) + (to->x & 63)/64;
+ state.y = (to->y >> 6) + (to->y & 63)/64;
+ printf("line to %f:%f\n", state.x, state.y);
+ glVertex2f(state.x, state.y);
+ return 0;
+}
+
+int GlftConicToFunc(FT_Vector *c, FT_Vector *to, void *user)
+{
+ GlftLineToFunc(to, user);
+ printf("conic the hedgehog!\n");
+ return 0;
+}
+
+int GlftCubicToFunc(FT_Vector *c1, FT_Vector *c2, FT_Vector *to, void
+*user)
+{
+ GlftLineToFunc(to, user);
+ printf("cubic\n");
+ return 0;
+}
+
+FT_Outline_Funcs GlftFuncs = {
+ GlftMoveToFunc,
+ GlftLineToFunc,
+ GlftConicToFunc,
+ GlftCubicToFunc,
+ 0,
+ 0
+};
+
void GlftRenderGlyph(FT_Face face, unsigned int dlist)
{
+ int err;
FT_GlyphSlot slot = face->glyph;
+
+ state.x = 0;
+ state.y = 0;
+ state.drawing = 0;
+
+ glNewList(dlist, GL_COMPILE);
+ err = FT_Outline_Decompose(&slot->outline, &GlftFuncs, NULL);
+ g_assert(!err);
+ if (state.drawing)
+ glEnd();
+ glEndList();
}
void GlftRenderString(struct GlftFont *font, const char *str, int bytes,
#include "glft.h"
#include <stdio.h>
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <string.h>
+#include <stdlib.h>
+#include "render.h"
+#include <glib.h>
+#include <GL/glx.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;
+}
+
+#define X 10
+#define Y 10
+#define W 500
+#define H 500
+
int main(int argc, char **argv)
{
+ Display *display;
+ Window win;
+ XVisualInfo *vi;
+ XEvent report, report2;
+ XClassHint chint;
+ Atom delete_win, protocols;
+ GLXContext cont;
+ int quit;
+ int config[] =
+ { GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, GLX_RGBA, None };
+
struct GlftFont *font;
if (argc < 2) {
- printf("Usage: %s fontname\n", argv[0]);
+ printf("Usage: %s fontname text\n", argv[0]);
return 1;
}
if (!GlftInit()) return 1;
font = GlftFontOpen(argv[1]);
+
+ if (!(display = XOpenDisplay(NULL))) {
+ fprintf(stderr, "couldn't connect to X server in DISPLAY\n");
+ return EXIT_FAILURE;
+ }
+ XSetErrorHandler(x_error_handler);
+ win = XCreateWindow(display, RootWindow(display, DefaultScreen(display)),
+ X, Y, W, H, 0,
+ CopyFromParent, /* depth */
+ CopyFromParent, /* class */
+ CopyFromParent, /* visual */
+ 0, /* valuemask */
+ 0); /* attributes */
+ XSelectInput(display, win, ExposureMask | StructureNotifyMask);
+ XMapWindow(display, win);
+
+ vi = glXChooseVisual(display, DefaultScreen(display), config);
+ if (vi == NULL)
+ printf("no conforming visual\n");
+ cont = glXCreateContext(display, vi, NULL, GL_TRUE);
+ if (cont == NULL)
+ printf("context creation failed\n");
+ glXMakeCurrent(display, win, cont);
+
+
+
+ chint.res_name = "rendertest";
+ chint.res_class = "Rendertest";
+ XSetClassHint(display, win, &chint);
+
+ delete_win = XInternAtom(display, "WM_DELETE_WINDOW", False);
+ protocols = XInternAtom(display, "WM_PROTOCOLS", False);
+ XSetWMProtocols(display, win, &delete_win, 1);
+ glClearColor(0.0, 0.0, 1.0, 0.0);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, 30, 0, 40, 0, 10);
+ glMatrixMode(GL_MODELVIEW);
+
+ quit = 0;
+ while (!quit) {
+ XNextEvent(display, &report);
+ switch (report.type) {
+ case ClientMessage:
+ if ((Atom)report.xclient.message_type == protocols)
+ if ((Atom)report.xclient.data.l[0] == delete_win)
+ quit = 1;
+ case Expose:
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ GlftRenderString(font, argv[2], strlen(argv[2]), 0, 0);
+ glXSwapBuffers(display, win);
+ case ConfigureNotify:
+ break;
+ }
+
+ }
GlftFontClose(font);
- return 0;
+ return 1;
}