1 /*
2  * Komposter
3  *
4  * Copyright (c) 2010 Noora Halme et al. (see AUTHORS)
5  *
6  * This code is licensed under the GNU General Public
7  * License version 2. See LICENSE for full text.
8  *
9  * Font loading, pre-rendering and drawing to display
10  *
11  */
12 
13 #include "font.h"
14 
15 // number of font styles specified
16 #define FONT_STYLES 8
17 
18 // from main.c
19 extern char respath[512];
20 
21 // eight font styles
22 char fontfile[FONT_STYLES][255]={
23   "m42.TTF",		    // komposter title font
24   "",
25   "acknowtt.ttf",             // tiny pixel font for modules
26   "078MKSD_MC.TTF",           // module descriptions
27   "m42.TTF",		// title font at 8x scale
28   "",
29   "",
30   "",
31 };
32 int fontsize[FONT_STYLES]={
33   8,
34   0,
35   13, //12,
36   22, //16,
37   64,
38   0,
39   0,
40   0
41 };
42 
43 
44 // freetype library struct and font face structs
45 FT_Library ft;
46 FT_Face font[FONT_STYLES];
47 
48 // data for prerendered font bitmaps
49 int font_advance[FONT_STYLES][255];
50 int font_xoffset[FONT_STYLES][255];
51 int font_yoffset[FONT_STYLES][255];
52 int font_width[FONT_STYLES][255];
53 int font_height[FONT_STYLES][255];
54 float font_ucoord[FONT_STYLES][255];
55 float font_vcoord[FONT_STYLES][255];
56 GLuint font_texture[FONT_STYLES][255];
57 u32 *font_bitmap[FONT_STYLES][255];
58 
59 
60 // round a 32-bit value upward to nearest power of 2
tpow2(unsigned int x)61 unsigned int tpow2(unsigned int x)
62 { x--;x|=x>>1;x|=x>>2;x|=x>>4;x|=x>>8;x|=x>>16;x++;return x; }
63 
64 
65 // initialize freetype, load font faces and prerender the font
66 // glyphs with sizes specified in the global font settings
font_init(void)67 int font_init(void)
68 {
69   char fullpath[512];
70   int err, i, j, c, rc, f, texw, texh;
71   GLuint p;
72   FT_GlyphSlot slot;
73 
74   // init freetype
75   err=FT_Init_FreeType(&ft);
76   if (err) {
77     printf("Freetype error on FT_Init_FreeType()\n");
78     return 0;
79   }
80 
81   // load font faces and set sizes
82   for(i=0;i<FONT_STYLES;i++) {
83     strncpy(fullpath, respath, 511);
84     strncat(fullpath, fontfile[i], 511);
85     if (fontsize[i] > 0) {
86 //      err=FT_New_Face(ft, fontfile[i], 0, &font[i]);
87       err=FT_New_Face(ft, fullpath, 0, &font[i]);
88       if (err) {
89         printf("Freetype error on FT_New_Face(), path %s\n", fullpath);
90         return 0;
91       }
92       err=FT_Set_Pixel_Sizes(font[i], 0, fontsize[i]);
93 //      err=FT_Set_Pixel_Sizes(font[i], fontsize[i], fontsize[i]);
94     }
95   }
96 
97   // prerender all glyphs
98   for(f=0;f<FONT_STYLES;f++) {
99     if (fontsize[f] > 0) {
100       slot=font[f]->glyph;
101       for(c=0;c<255;c++) {
102         // awful kludge to fix W and M with the bitmap font
103         rc=c;
104         if (c=='W') rc='w';
105         if (c=='M') rc='m';
106 
107         // render character
108         err=FT_Load_Char(font[f], rc, FT_LOAD_RENDER);
109         if (err) {
110           printf("Freetype error on FT_Load_Char()\n");
111           continue;
112         }
113 
114         // save metrics
115         font_advance[f][c]=slot->advance.x >> 6;
116         font_xoffset[f][c]=slot->bitmap_left;
117         font_yoffset[f][c]=-slot->bitmap_top;
118         font_width[f][c]=slot->bitmap.width;
119         font_height[f][c]=slot->bitmap.rows;
120         texw=tpow2(slot->bitmap.width);
121         texh=tpow2(slot->bitmap.rows);
122         font_ucoord[f][c]=(float)(slot->bitmap.width)/(float)(texw);
123         font_vcoord[f][c]=(float)(slot->bitmap.rows)/(float)(texh);
124 
125         // alloc ram for bimap and convert to RGBA
126         font_bitmap[f][c]=calloc(texw*texh, sizeof(GLuint));
127         for (j=0;j<slot->bitmap.rows;j++)
128         {
129           for(i=0;i<slot->bitmap.width;i++) {
130             p= 0xffffff|((u32)(slot->bitmap.buffer[j*slot->bitmap.pitch+i]) << 24);
131             font_bitmap[f][c][ ( slot->bitmap.rows-(j+1) )*texw + i] = p;
132           }
133         }
134 
135         // generate opengl texture for the bitmap
136         glEnable(GL_TEXTURE_2D);
137         glGenTextures(1, &font_texture[f][c]);
138         glBindTexture(GL_TEXTURE_2D, font_texture[f][c]);
139         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, font_bitmap[f][c]);
140         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
141         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
142         glDisable(GL_TEXTURE_2D);
143       }
144     }
145   }
146 
147   return 1;
148 }
149 
150 
151 
152 
153 // render text using a preloaded face/size
154 // fontnr is preloaded face/size number, color is argb
155 // align 0=left, 1=center, 2=right
render_text(const char * text,float x,float y,int fontnr,u32 color,int align)156 void render_text(const char *text, float x, float y, int fontnr, u32 color, int align)
157 {
158   unsigned long sw, n;
159   float xp, yp;
160 
161   // calc text bitmap width (note: linefeeds fuck up center and right alignment)
162   sw=0; n=0;
163   while(n<strlen(text))
164   {
165     sw+=font_advance[fontnr][(int)text[n]];
166     n++;
167   }
168 
169   // render the string using textured quads
170   xp=x;
171   if (align==1) xp-=(sw/2);
172   if (align==2) xp-=sw;
173   yp=y; n=0;
174   while(n<strlen(text))
175   {
176     if ((int)text[n]=='\n') { yp+=fontsize[fontnr]+2; xp=x; n++; continue; }
177     glEnable(GL_TEXTURE_2D);
178     glColor4ub((color>>16)&0xff, (color>>8)&0xff, color&0xff, color>>24);
179     glBindTexture(GL_TEXTURE_2D, font_texture[fontnr][(int)text[n]]);
180     glBegin(GL_QUADS);
181       glTexCoord2f(0, font_vcoord[fontnr][(int)text[n]]);
182       glVertex2f(xp+font_xoffset[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
183       glTexCoord2f(font_ucoord[fontnr][(int)text[n]], font_vcoord[fontnr][(int)text[n]]);
184       glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]);
185       glTexCoord2f(font_ucoord[fontnr][(int)text[n]], 0);
186       glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]],
187                yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
188       glTexCoord2f(0, 0);
189       glVertex2f(xp+font_xoffset[fontnr][(int)text[n]],
190                yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]);
191     glEnd();
192     glDisable(GL_TEXTURE_2D);
193 
194     xp+=font_advance[fontnr][(int)text[n]];
195     n++;
196   }
197 }
198 
199