// Copyright (C) 2006 Jason Woofenden // // This file is part of VoR. // // VoR is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // VoR is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with VoR; see the file COPYING. If not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, // MA 02111-1307, USA. #include #include #include #include "font.h" font *cur_font; extern SDL_Surface *surf_screen; int font_height() { return cur_font->bounds[0].h; } void font_set(font *to) { cur_font = to; } // return true if column of pixels (pix points to the top one) is all black int line_clear(unsigned char* pix, int height, int width) { int i; for(i = 0; i < height; ++i) { if(pix[0] != 0) { return 0; } pix += width; } return 1; } // return the number of consecutive colums of pixels are still clear (or still not clear) int find_change(unsigned char* pix, int height, int width) { int i; int state = line_clear(pix, height, width); pix += 3; for(i = 1; /*forever*/; pix += 3, ++i) { if(line_clear(pix, height, width) != state) { return i; } } } void font_free(font* garbage) { SDL_FreeSurface(garbage->pixels); free(garbage); } font* font_load(const char *filename) { font* new_font; int i; unsigned char* pix; int x = 0; int width; new_font = (font*) malloc(sizeof(font)); if(!new_font) { fprintf(stderr, "couldn't allocate memory for font.\n"); exit(1); } new_font->pixels = (SDL_Surface*)IMG_Load(filename); if(!new_font->pixels) { fprintf(stderr, "couldn't load font file '%s'.\n", filename); exit(1); } //SDL_SetColorKey(new_font->pixels, SDL_SRCCOLORKEY, 0); pix = new_font->pixels->pixels; // set all font rects to be the full height for(i = 0; i < 94; ++i) { new_font->bounds[i].y = 0; new_font->bounds[i].h = new_font->pixels->h; } // find the characters new_font->bounds[0].x = 0; // the first character starts at the begining for(i = 0; i < 93; ) { // find the end of the character width = find_change(pix, new_font->pixels->h, new_font->pixels->pitch); x += width; pix += width * new_font->pixels->format->BytesPerPixel; new_font->bounds[i].w = width; ++i; width = find_change(pix, new_font->pixels->h, new_font->pixels->pitch); x += width; pix += width * new_font->pixels->format->BytesPerPixel; new_font->bounds[i].x = x; } new_font->bounds[93].w = new_font->pixels->w - new_font->bounds[93].x; // the last character ends at the end // There is a common problem where with some fonts there is a column of all // black pixels between the parts of the double-quote, and this code thinks // that it is two seperate characters. This code currently assumes that // there is no such column. To change it so it assumes that the // double-quote character looks like 2, change the loop above to start at // zero, and uncomment the following indented stuff. // // The above has 3 problems: // // // 1) space is missing from the begining // // 2) ! is first instead of seccond // // 3) " is taking 2nd and 3rd position // // // merge pieces of double-quote // width = font_rects[2].x - font_rects[1].x; // font_rects[2].w += width; // font_rects[2].x = font_rects[1].x; // // // move ! // font_rects[1].x = font_rects[0].x; // font_rects[1].w = font_rects[0].w; // the width of the space is set to half the space between the first two characters width = new_font->bounds[1].x - (new_font->bounds[0].x + new_font->bounds[0].w); new_font->space_width = width / 2; new_font->letter_spacing = new_font->space_width / 4 ; if(new_font->space_width < 2) { new_font->space_width = 2; } if(new_font->letter_spacing < 1) { new_font->letter_spacing = 1; } font_set(new_font); return new_font; } void font_write(int x, int y, const char* message) { SDL_Rect dest = {x, y, 0, font_height()}; char c; if(message[0] == 0) { return; } for(c = *message++; c; c = *message++) { if(c > 31 && c < 127) { if(c == 32) { dest.x += cur_font->space_width; } else { c -= 33; dest.w = cur_font->bounds[(int)c].w; SDL_BlitSurface(cur_font->pixels, &(cur_font->bounds[(int)c]), surf_screen, &dest); dest.x += dest.w; } dest.x += cur_font->letter_spacing; } else { fprintf(stderr, "tried to print unknown char: %d (0x%x)\n", c, c); } } } // return the width in pixels of the string int font_width(const char* message) { int width = 0; char c; if(message[0] == 0) { return 0; } for(c = *message++; c; c = *message++) { if(c > 31 && c < 127) { if(c == 32) { width += cur_font->space_width; } else { c -= 33; width += cur_font->bounds[(int)c].w; } width += cur_font->letter_spacing; } else { fprintf(stderr, "tried to print unknown char: %d (0x%x)\n", c, c); } } // don't count spacing after the last char if(width) { width -= cur_font->letter_spacing; } return width; }