]> icculus.org git repositories - dana/openbox.git/blob - glft/render.c
take the glyphs x values into account for spacing
[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 15.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     if (state.drawing) {
25         glEnd();
26     }
27     glBegin(GL_LINE_STRIP);
28     glVertex2f(state.x, state.y);
29     state.drawing = 1;
30     return 0;
31 }
32
33 int GlftLineToFunc(FT_Vector *to, void *user)
34 {
35     state.x = TOFLOAT(to->x);
36     state.y = TOFLOAT(to->y);
37     glVertex2f(state.x, state.y);
38     return 0;
39 }
40
41 int GlftConicToFunc(FT_Vector *c, FT_Vector *to, void *user)
42 {
43     float t, u, x, y;
44
45     for (t = 0, u = 1; t < 1.0; t += 1.0/TPOINTS, u = 1.0-t) {
46         x = u*u*state.x + 2*t*u*TOFLOAT(c->x) + t*t*TOFLOAT(to->x);
47         y = u*u*state.y + 2*t*u*TOFLOAT(c->y) + t*t*TOFLOAT(to->y);
48         glVertex2f(x, y);
49     }
50     state.x = TOFLOAT(to->x);
51     state.y = TOFLOAT(to->y);
52     glVertex2f(state.x, state.y);
53     return 0;
54 }
55
56 int GlftCubicToFunc(FT_Vector *c1, FT_Vector *c2, FT_Vector *to, void 
57 *user)
58 {
59     GlftLineToFunc(to, user);
60     g_message("cubic not currently rendered properly\n");
61     return 0;
62 }
63
64 FT_Outline_Funcs GlftFuncs = {
65     GlftMoveToFunc,
66     GlftLineToFunc,
67     GlftConicToFunc,
68     GlftCubicToFunc,
69     0,
70     0
71 };
72
73 void GlftRenderGlyph(FT_Face face, unsigned int dlist)
74 {
75     int err;
76     FT_GlyphSlot slot = face->glyph;
77
78     state.x = 0;
79     state.y = 0;
80     state.drawing = 0;
81
82     glNewList(dlist, GL_COMPILE);
83     err = FT_Outline_Decompose(&slot->outline, &GlftFuncs, NULL);
84     g_assert(!err);
85     if (state.drawing)
86         glEnd();
87     glEndList();
88 }
89
90 void GlftRenderString(struct GlftFont *font, const char *str, int bytes,
91                       int x, int y)
92 {
93     const char *c;
94     struct GlftGlyph *g, *p = NULL;
95
96     if (!g_utf8_validate(str, bytes, NULL)) {
97         GlftDebug("Invalid UTF-8 in string\n");
98         return;
99     }
100
101     glPushMatrix();
102
103     c = str;
104     while (c - str < bytes) {
105         g = GlftFontGlyph(font, c);
106         if (g) {
107             glTranslatef(GlftFontAdvance(font, p, g), 0.0, 0.0);
108             glCallList(g->dlist);
109         } else
110             glTranslatef(font->max_advance_width, 0.0, 0.0);
111         p = g;
112         c = g_utf8_next_char(c);
113     }
114
115     glPopMatrix();
116 }
117
118 void GlftMeasureString(struct GlftFont *font,
119                        const char *str,
120                        int bytes,
121                        int *w,
122                        int *h)
123 {
124     const char *c;
125     struct GlftGlyph *g, *p = NULL;
126
127     if (!g_utf8_validate(str, bytes, NULL)) {
128         GlftDebug("Invalid UTF-8 in string\n");
129         return;
130     }
131
132     *w = 0;
133     *h = 0;
134
135     c = str;
136     while (c - str < bytes) {
137         g = GlftFontGlyph(font, c);
138         if (g) {
139             *w += GlftFontAdvance(font, p, g);
140             *h = MAX(g->height, *h);
141         } else
142             *w += font->max_advance_width;
143         p = g;
144         c = g_utf8_next_char(c);
145     }
146 }