/* * Komposter * * Copyright (c) 2010 Noora Halme et al. (see AUTHORS) * * This code is licensed under the GNU General Public * License version 2. See LICENSE for full text. * * Font loading, pre-rendering and drawing to display * */ #include "font.h" // number of font styles specified #define FONT_STYLES 8 // from main.c extern char respath[512]; // eight font styles char fontfile[FONT_STYLES][255]={ "m42.TTF", // komposter title font "", "acknowtt.ttf", // tiny pixel font for modules "078MKSD_MC.TTF", // module descriptions "m42.TTF", // title font at 8x scale "", "", "", }; int fontsize[FONT_STYLES]={ 8, 0, 13, //12, 22, //16, 64, 0, 0, 0 }; // freetype library struct and font face structs FT_Library ft; FT_Face font[FONT_STYLES]; // data for prerendered font bitmaps int font_advance[FONT_STYLES][255]; int font_xoffset[FONT_STYLES][255]; int font_yoffset[FONT_STYLES][255]; int font_width[FONT_STYLES][255]; int font_height[FONT_STYLES][255]; float font_ucoord[FONT_STYLES][255]; float font_vcoord[FONT_STYLES][255]; GLuint font_texture[FONT_STYLES][255]; u32 *font_bitmap[FONT_STYLES][255]; // round a 32-bit value upward to nearest power of 2 unsigned int tpow2(unsigned int x) { x--;x|=x>>1;x|=x>>2;x|=x>>4;x|=x>>8;x|=x>>16;x++;return x; } // initialize freetype, load font faces and prerender the font // glyphs with sizes specified in the global font settings int font_init(void) { char fullpath[512]; int err, i, j, c, rc, f, texw, texh; GLuint p; FT_GlyphSlot slot; // init freetype err=FT_Init_FreeType(&ft); if (err) { printf("Freetype error on FT_Init_FreeType()\n"); return 0; } // load font faces and set sizes for(i=0;i 0) { // err=FT_New_Face(ft, fontfile[i], 0, &font[i]); err=FT_New_Face(ft, fullpath, 0, &font[i]); if (err) { printf("Freetype error on FT_New_Face(), path %s\n", fullpath); return 0; } err=FT_Set_Pixel_Sizes(font[i], 0, fontsize[i]); // err=FT_Set_Pixel_Sizes(font[i], fontsize[i], fontsize[i]); } } // prerender all glyphs for(f=0;f 0) { slot=font[f]->glyph; for(c=0;c<255;c++) { // awful kludge to fix W and M with the bitmap font rc=c; if (c=='W') rc='w'; if (c=='M') rc='m'; // render character err=FT_Load_Char(font[f], rc, FT_LOAD_RENDER); if (err) { printf("Freetype error on FT_Load_Char()\n"); continue; } // save metrics font_advance[f][c]=slot->advance.x >> 6; font_xoffset[f][c]=slot->bitmap_left; font_yoffset[f][c]=-slot->bitmap_top; font_width[f][c]=slot->bitmap.width; font_height[f][c]=slot->bitmap.rows; texw=tpow2(slot->bitmap.width); texh=tpow2(slot->bitmap.rows); font_ucoord[f][c]=(float)(slot->bitmap.width)/(float)(texw); font_vcoord[f][c]=(float)(slot->bitmap.rows)/(float)(texh); // alloc ram for bimap and convert to RGBA font_bitmap[f][c]=calloc(texw*texh, sizeof(GLuint)); for (j=0;jbitmap.rows;j++) { for(i=0;ibitmap.width;i++) { p= 0xffffff|((u32)(slot->bitmap.buffer[j*slot->bitmap.pitch+i]) << 24); font_bitmap[f][c][ ( slot->bitmap.rows-(j+1) )*texw + i] = p; } } // generate opengl texture for the bitmap glEnable(GL_TEXTURE_2D); glGenTextures(1, &font_texture[f][c]); glBindTexture(GL_TEXTURE_2D, font_texture[f][c]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, font_bitmap[f][c]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glDisable(GL_TEXTURE_2D); } } } return 1; } // render text using a preloaded face/size // fontnr is preloaded face/size number, color is argb // align 0=left, 1=center, 2=right void render_text(const char *text, float x, float y, int fontnr, u32 color, int align) { unsigned long sw, n; float xp, yp; // calc text bitmap width (note: linefeeds fuck up center and right alignment) sw=0; n=0; while(n>16)&0xff, (color>>8)&0xff, color&0xff, color>>24); glBindTexture(GL_TEXTURE_2D, font_texture[fontnr][(int)text[n]]); glBegin(GL_QUADS); glTexCoord2f(0, font_vcoord[fontnr][(int)text[n]]); glVertex2f(xp+font_xoffset[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]); glTexCoord2f(font_ucoord[fontnr][(int)text[n]], font_vcoord[fontnr][(int)text[n]]); glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]); glTexCoord2f(font_ucoord[fontnr][(int)text[n]], 0); glVertex2f(xp+font_xoffset[fontnr][(int)text[n]]+font_width[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]); glTexCoord2f(0, 0); glVertex2f(xp+font_xoffset[fontnr][(int)text[n]], yp+font_yoffset[fontnr][(int)text[n]]+font_height[fontnr][(int)text[n]]); glEnd(); glDisable(GL_TEXTURE_2D); xp+=font_advance[fontnr][(int)text[n]]; n++; } }