1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
// 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 <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#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 pitch) {
int i;
for(i = 0; i < height; ++i) {
if(pix[0] != 0) {
return 0;
}
pix += pitch;
}
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 pitch, int Bpp) {
int i;
int state = line_clear(pix, height, pitch);
pix += Bpp;
for(i = 1; /*forever*/; pix += Bpp, ++i) {
if(line_clear(pix, height, pitch) != 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, new_font->pixels->format->BytesPerPixel);
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, new_font->pixels->format->BytesPerPixel);
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;
}
|