]> icculus.org git repositories - dana/openbox.git/blob - glft/render.c
proper vertical alignment
[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 void GlftRenderGlyph(FT_Face face, struct GlftGlyph *g)
12 {
13     unsigned char *padbuf;
14     int err, i;
15     FT_GlyphSlot slot = face->glyph;
16
17     err = FT_Render_Glyph(slot, ft_render_mode_normal);
18         g_assert(!err);
19
20     g->texw = slot->bitmap.width;
21     g->texh = slot->bitmap.rows;
22
23     g->left = slot->bitmap_left;
24
25     g->yoff = slot->bitmap.rows - slot->bitmap_top;
26     g->padx = 1;
27     while (g->padx < slot->bitmap.width)
28        g->padx <<= 1;
29
30     g->pady = 1;
31     while (g->pady < slot->bitmap.rows)
32        g->pady <<= 1;
33
34     padbuf = g_new0(unsigned char, g->padx * g->pady);
35     for (i = 0; i < slot->bitmap.rows; i++)
36         memcpy(padbuf + i*g->padx,
37                slot->bitmap.buffer + i*slot->bitmap.width,
38                slot->bitmap.width);
39     glBindTexture(GL_TEXTURE_2D, g->tnum);
40     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
41     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
42     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
43     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
44     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
45     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
46     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g->padx, g->pady,
47                  0, GL_GREEN, GL_UNSIGNED_BYTE, padbuf);
48
49     g_free(padbuf);
50 }
51
52 void GlftRenderString(struct GlftFont *font, const char *str, int bytes,
53                       int x, int y)
54 {
55     const char *c;
56     struct GlftGlyph *g, *p = NULL;
57
58     if (!g_utf8_validate(str, bytes, NULL)) {
59         GlftDebug("Invalid UTF-8 in string\n");
60         return;
61     }
62
63     glPushMatrix();
64
65     c = str;
66     while (c - str < bytes) {
67         g = GlftFontGlyph(font, c);
68         if (g) {
69             glTranslatef(GlftFontAdvance(font, p, g), 0.0, 0.0);
70             glBindTexture(GL_TEXTURE_2D, g->tnum);
71             glBegin(GL_QUADS);
72             glColor3f(1.0, 1.0, 1.0);
73
74             glTexCoord2f(0, g->texh/(float)g->pady);
75             glVertex2i(g->left, 0 - g->yoff);
76
77             glTexCoord2f(g->texw/(float)g->padx, g->texh/(float)g->pady);
78             glVertex2i(g->left + g->texw, 0 - g->yoff);
79
80             glTexCoord2f(g->texw/(float)g->padx, 0);
81             glVertex2i(g->left + g->texw, g->texh - g->yoff);
82
83             glTexCoord2f(0, 0);
84             glVertex2i(g->left, g->texh - g->yoff);
85             glEnd();
86         } else
87             glTranslatef(font->max_advance_width, 0.0, 0.0);
88         p = g;
89         c = g_utf8_next_char(c);
90     }
91
92     glPopMatrix();
93 }
94
95 void GlftMeasureString(struct GlftFont *font,
96                        const char *str,
97                        int bytes,
98                        int *w,
99                        int *h)
100 {
101     const char *c;
102     struct GlftGlyph *g, *p = NULL;
103
104     if (!g_utf8_validate(str, bytes, NULL)) {
105         GlftDebug("Invalid UTF-8 in string\n");
106         return;
107     }
108
109     *w = 0;
110     *h = 0;
111
112     c = str;
113     while (c - str < bytes) {
114         g = GlftFontGlyph(font, c);
115         if (g) {
116             *w += GlftFontAdvance(font, p, g);
117             *h = MAX(g->height, *h);
118         } else
119             *w += font->max_advance_width;
120         p = g;
121         c = g_utf8_next_char(c);
122     }
123 }