#include "oglfont.h" #include #include #include #include #include #include #define GL_Y_FIX(f) (1 - (f)) static void _compile(oglf_font_t *font) { int chr; font->base_list = glGenLists(OGLF_MAX_ASCII); glBindTexture(GL_TEXTURE_2D, font->fontTex); for (chr = 0; chr < OGLF_MAX_ASCII; chr++) { glNewList(font->base_list + chr - 1, GL_COMPILE); if (font->chars[chr].w) { glBegin(GL_QUADS); glTexCoord2f( (float) font->chars[chr].x / (float) font->w, (float) GL_Y_FIX((font->chars[chr].y+font->chars[chr].h) / (float) font->h)); glVertex2d((float) font->chars[chr].x_ofs, (float) font->chars[chr].h + font->chars[chr].y_ofs); glTexCoord2f( (float) (font->chars[chr].x + font->chars[chr].w) / (float) font->w, (float) GL_Y_FIX((font->chars[chr].y + font->chars[chr].h) / (float) font->h)); glVertex2d((float) font->chars[chr].w + font->chars[chr].x_ofs, (float) font->chars[chr].h + font->chars[chr].y_ofs); glTexCoord2f((float) (font->chars[chr].x + font->chars[chr].w) / (float) font->w, (float) GL_Y_FIX( font->chars[chr].y / (float) font->h)); glVertex2d((float) font->chars[chr].w + font->chars[chr].x_ofs, (float) font->chars[chr].y_ofs); glTexCoord2f((float) font->chars[chr].x / (float) font->w, (float) GL_Y_FIX( font->chars[chr].y / (float) font->h)); glVertex2d((float) font->chars[chr].x_ofs, (float) font->chars[chr].y_ofs); glEnd(); glTranslatef((float) (font->chars[chr].x_advance ), 0, 0); } else { // if char has no width, treat it like a space glTranslatef((float) font->base, 0, 0); } glEndList(); } } static int _starts_with(const char *buffer, const char *text) { const char *text_ptr = text; const char *buffer_ptr = buffer; while (*text_ptr != 0) { if (*text_ptr != *buffer_ptr) return 0; text_ptr++; buffer_ptr++; } return 1; } static int _parse_line(oglf_font_t *font, char *buffer) { if (_starts_with(buffer, "common")) { int count = sscanf(buffer, "common lineHeight=%d base=%d scaleW=%d scaleH=%d pages=%d\n", &font->line_h, &font->base, &font->w, &font->h, &font->pages); if (count != 5) return 0; } else if (_starts_with(buffer, "char ")) { oglf_char_t temp_char; int id; int count = sscanf( buffer, "char id=%d x=%d y=%d width=%d height=%d xoffset=%d yoffset=%d xadvance=%d page=%d chnl=%*d\n", &id, &temp_char.x, &temp_char.y, &temp_char.w, &temp_char.h, &temp_char.x_ofs, &temp_char.y_ofs, &temp_char.x_advance, &temp_char.page); font->chars[id] = temp_char; if (count != 9) return 0; } return 1; } int oglf_load(oglf_font_t *font, const char *bmf_path, unsigned int texture) { FILE *file; char buffer[256]; file = fopen(bmf_path, "r"); // could not open file for read if (file == 0) return 0; font->chars = (oglf_char_t *) malloc(OGLF_MAX_ASCII * sizeof(oglf_char_t)); while (fgets(buffer, sizeof(buffer), file) != 0) { int result = _parse_line(font, buffer); if (result == 0) return 0; } fclose(file); // close the source file font->fontTex = texture; font->scale = 1.f; _compile(font); return 1; } // calculate the approx. width of a string of text // note: no kerning info is currently evaluated int oglf_width(oglf_font_t *font, const char *text) { int w, l, i; w = 0; l = strlen(text); for (i = 0; i < l; i++) { //w += font->chars[text[i]].w; w += font->chars[text[i]].x_advance; } return w; } // destroy the charset void oglf_destroy(oglf_font_t *font) { glDeleteLists(font->base_list, OGLF_MAX_ASCII); glDeleteTextures(1, &font->fontTex); free(font->chars); } /* void ogl___font_in(ogl_font *font); void bmf___font_in(ogl_font *font) { ogl___font_in(font); } */ void oglf_begin(oglf_font_t *font, int width, int height) { glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); //glNormal3f( 0.0, 0.0, 1.0); // set projection matrix glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); //int newheight = (_width / 16.0) * 9.0; glOrtho(0.0, (double)width, (double)height, 0.0, -1.0, 1.0); // prepare model matrix glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); //glScalef(font->scale, font->scale, 1.f); glBindTexture(GL_TEXTURE_2D, font->fontTex); glEnable(GL_TEXTURE_2D); glAlphaFunc(GL_GEQUAL,0.1); glEnable(GL_ALPHA_TEST); } void oglf_print_l(oglf_font_t *font, float x, float y, const char *text, int l) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(x, y, 0); glCallLists(l, GL_UNSIGNED_BYTE, text); glPopMatrix(); } void oglf_end() { glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void oglf_print(oglf_font_t *font, float x, float y, const char *text) { oglf_print_l(font, x, y, text, strlen(text)); } void oglf_printf(oglf_font_t *font, int x, int y, const char *fmt, ...) { char text[OGLF_MAX_LINE], *line_start, *c; float h; va_list ap; int row; if (strlen(fmt) == 0) return; va_start(ap, fmt); vsprintf(text, fmt, ap); va_end(ap); line_start = text; row = 0; h = font->h / .63f; NextL: c = strchr(line_start, '\n'); if (c) { row++; oglf_print_l(font, (float) x, (float) (y - h * row), line_start, c - line_start); line_start = c + 1; goto NextL; } oglf_print_l(font, (float) x, (float) (y - h * row), line_start, strlen( line_start)); } /* #define OGLF_CENTER_TEXT(rect, txtw, ofs) ((float)((rect[ofs+_W] - txtw - rect[ofs])/2 + rect[ofs])) // printf function which takes in account the alignment void ogl_printf_al(oglf_font_t *font, alignment align, GLuint *rect, const char *fmt, ...) { char text[BMF_MAX_LINE]; va_list ap; if (!strlen(fmt)) return; va_start(ap, fmt); vsprintf(text, fmt, ap); va_end(ap); switch (align) { case al_left: ogl_print(font, (float) rect[_X], OGLF_CENTER_TEXT(rect, font->line_h, _Y), text); break; case al_right: ogl_print(font, ((float) rect[_W] - ogl__width(font, text)), OGLF_CENTER_TEXT(rect, font->line_h, _Y), text); break; case al_center: ogl_print(font, OGLF_CENTER_TEXT(rect, ogl__width(font, text), _X), OGLF_CENTER_TEXT(rect, font->line_h, _Y), text); break; } } */