]> icculus.org git repositories - dana/openbox.git/blob - glft/render.c
let's hear it for conics!
[dana/openbox.git] / glft / render.c
1 #include "render.h"
2 #include "font.h"
3 #include "debug.h"
4 #include <glib.h>
5 #include <GL/glx.h>
6
7 #define TPOINTS 5.0
8
9 #define TOFLOAT(x) (((x) >> 6) + ((x) & 63)/64.0)
10
11 #include FT_OUTLINE_H
12
13 struct GlftWalkState {
14     int drawing;
15     float x, y;
16 };
17
18 static struct GlftWalkState state;
19
20 int GlftMoveToFunc(FT_Vector *to, void *user)
21 {
22     state.x = TOFLOAT(to->x);
23     state.y = TOFLOAT(to->y);
24     printf("move to %f:%f\n", state.x, state.y);
25     if (state.drawing) {
26         glEnd();
27     }
28     glBegin(GL_LINE_STRIP);
29     glVertex2f(state.x, state.y);
30     state.drawing = 1;
31     return 0;
32 }
33
34 int GlftLineToFunc(FT_Vector *to, void *user)
35 {
36     state.x = TOFLOAT(to->x);
37     state.y = TOFLOAT(to->y);
38     glVertex2f(state.x, state.y);
39     printf("line to %f:%f\n", state.x, state.y);
40     return 0;
41 }
42
43 int GlftConicToFunc(FT_Vector *c, FT_Vector *to, void *user)
44 {
45     float t, u, x, y;
46
47     for (t = 0, u = 1; t < 1.0; t += 1.0/TPOINTS, u = 1.0-t) {
48         x = u*u*state.x + 2*t*u*TOFLOAT(c->x) + t*t*TOFLOAT(to->x);
49         y = u*u*state.y + 2*t*u*TOFLOAT(c->y) + t*t*TOFLOAT(to->y);
50         glVertex2f(x, y);
51     }
52     state.x = TOFLOAT(to->x);
53     state.y = TOFLOAT(to->y);
54     glVertex2f(state.x, state.y);
55     printf("conic the hedgehog!\n");
56     return 0;
57 }
58
59 int GlftCubicToFunc(FT_Vector *c1, FT_Vector *c2, FT_Vector *to, void 
60 *user)
61 {
62     GlftLineToFunc(to, user);
63     printf("cubic\n");
64     return 0;
65 }
66
67 FT_Outline_Funcs GlftFuncs = {
68     GlftMoveToFunc,
69     GlftLineToFunc,
70     GlftConicToFunc,
71     GlftCubicToFunc,
72     0,
73     0
74 };
75
76 void GlftRenderGlyph(FT_Face face, unsigned int dlist)
77 {
78     int err;
79     FT_GlyphSlot slot = face->glyph;
80
81     state.x = 0;
82     state.y = 0;
83     state.drawing = 0;
84
85     glNewList(dlist, GL_COMPILE);
86     err = FT_Outline_Decompose(&slot->outline, &GlftFuncs, NULL);
87     g_assert(!err);
88     if (state.drawing)
89         glEnd();
90     glEndList();
91 }
92
93 void GlftRenderString(struct GlftFont *font, const char *str, int bytes,
94                       int x, int y)
95 {
96     const char *c;
97     struct GlftGlyph *g;
98
99     if (!g_utf8_validate(str, bytes, NULL)) {
100         GlftDebug("Invalid UTF-8 in string\n");
101         return;
102     }
103
104     glPushMatrix();
105
106     c = str;
107     while (c - str < bytes) {
108         g = GlftFontGlyph(font, c);
109         if (g) {
110             glCallList(g->dlist);
111             glTranslatef(g->width, 0.0, 0.0);
112         } else
113             glTranslatef(font->max_advance_width, 0.0, 0.0);
114         c = g_utf8_next_char(c);
115     }
116
117     glPopMatrix();
118 }
119
120 void GlftMeasureString(struct GlftFont *font,
121                        const char *str,
122                        int bytes,
123                        int *w,
124                        int *h)
125 {
126     const char *c;
127     struct GlftGlyph *g;
128
129     if (!g_utf8_validate(str, bytes, NULL)) {
130         GlftDebug("Invalid UTF-8 in string\n");
131         return;
132     }
133
134     *w = 0;
135     *h = 0;
136
137     c = str;
138     while (c - str < bytes) {
139         g = GlftFontGlyph(font, c);
140         if (g) {
141             *w += g->width;
142             *h = MAX(g->height, *h);
143         } else {
144             *w += font->max_advance_width;
145         }
146         c = g_utf8_next_char(c);
147     }
148 }