JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
7e750bf1b5daa1df9105e5d1b4e179967bff4729
[vor.git] / SFont.c
1 /*  SFont: a simple font library that uses special images as fonts
2     Copyright (C) 2003 Karl Bartel
3
4     License: GPL or LGPL (at your choice)
5     WWW: http://www.linux-games.com/sfont/
6
7     This program is free software; you can redistribute it and/or modify        
8     it under the terms of the GNU General Public License as published by        
9     the Free Software Foundation; either version 2 of the License, or           
10     (at your option) any later version.                                         
11                                                                                 
12     This program is distributed in the hope that it will be useful,       
13     but WITHOUT ANY WARRANTY; without even the implied warranty of              
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               
15     GNU General Public License for more details.                
16                                                                                
17     You should have received a copy of the GNU General Public License           
18     along with this program; if not, write to the Free Software                 
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   
20                                                                                 
21     Karl Bartel
22     Cecilienstr. 14                                                    
23     12307 Berlin
24     GERMANY
25     karlb@gmx.net                                                      
26 */                                                                            
27 #include <SDL.h>
28
29 #include <assert.h>
30 #include <stdlib.h>
31 #include "SFont.h"
32
33 static Uint32
34 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
35 {
36    Uint8  *bits;
37    Uint32 Bpp;
38
39    assert(X>=0);
40    assert(X<Surface->w);
41    
42    Bpp = Surface->format->BytesPerPixel;
43    bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
44
45    // Get the pixel
46    switch(Bpp) {
47       case 1:
48          return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
49          break;
50       case 2:
51          return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
52          break;
53       case 3: { // Format/endian independent 
54          Uint8 r, g, b;
55          r = *((bits)+Surface->format->Rshift/8);
56          g = *((bits)+Surface->format->Gshift/8);
57          b = *((bits)+Surface->format->Bshift/8);
58          return SDL_MapRGB(Surface->format, r, g, b);
59          }
60          break;
61       case 4:
62          return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
63          break;
64    }
65
66    return -1;
67 }
68
69 SFont_Font *
70 SFont_InitFont(SDL_Surface* Surface)
71 {
72     int x = 0, i = 0;
73     Uint32 pixel;
74     SFont_Font* Font;
75     Uint32 pink;
76
77     if (Surface == NULL)
78         return NULL;
79
80     Font = (SFont_Font *) malloc(sizeof(SFont_Font));
81     Font->Surface = Surface;
82
83     SDL_LockSurface(Surface);
84
85     pink = SDL_MapRGB(Surface->format, 255, 0, 255);
86     while (x < Surface->w) {
87         if (GetPixel(Surface, x, 0) == pink) { 
88             Font->CharPos[i++]=x;
89             while((x < Surface->w) && (GetPixel(Surface, x, 0)== pink))
90                 x++;
91             Font->CharPos[i++]=x;
92         }
93         x++;
94     }
95     Font->MaxPos = x-1;
96     
97     pixel = GetPixel(Surface, 0, Surface->h-1);
98     SDL_UnlockSurface(Surface);
99     SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, pixel);
100
101     return Font;
102 }
103
104 void
105 SFont_FreeFont(SFont_Font* FontInfo)
106 {
107     SDL_FreeSurface(FontInfo->Surface);
108     free(FontInfo);
109 }
110
111 void
112 SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
113                 int x, int y, const char *text)
114 {
115     const char* c;
116     int charoffset;
117     SDL_Rect srcrect, dstrect;
118
119     if(text == NULL)
120         return;
121
122     // these values won't change in the loop
123     srcrect.y = 1;
124     dstrect.y = y;
125     srcrect.h = dstrect.h = Font->Surface->h - 1;
126
127     for(c = text; *c != '\0' && x <= Surface->w ; c++) {
128         charoffset = ((int) (*c - 33)) * 2 + 1;
129         // skip spaces and nonprintable characters
130         if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
131             x += Font->CharPos[2]-Font->CharPos[1];
132             continue;
133         }
134
135         srcrect.w = dstrect.w = 
136             (Font->CharPos[charoffset+2] + Font->CharPos[charoffset+1])/2 -
137             (Font->CharPos[charoffset] + Font->CharPos[charoffset-1])/2;
138         srcrect.x = (Font->CharPos[charoffset]+Font->CharPos[charoffset-1])/2;
139         dstrect.x = x - (float)(Font->CharPos[charoffset]
140                               - Font->CharPos[charoffset-1])/2;
141
142         SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect); 
143
144         x += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
145     }
146 }
147
148 int
149 SFont_TextWidth(const SFont_Font *Font, const char *text)
150 {
151     const char* c;
152     int charoffset=0;
153     int width = 0;
154
155     if(text == NULL)
156         return 0;
157
158     for(c = text; *c != '\0'; c++) {
159         charoffset = ((int) *c - 33) * 2 + 1;
160         // skip spaces and nonprintable characters
161         if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
162             width += Font->CharPos[2]-Font->CharPos[1];
163             continue;
164         }
165         
166         width += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
167     }
168
169     return width;
170 }
171
172 int
173 SFont_TextHeight(const SFont_Font* Font)
174 {
175     return Font->Surface->h - 1;
176 }
177
178 void
179 SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font *Font,
180                 int y, const char *text)
181 {
182     SFont_Write(Surface, Font, Surface->w/2 - SFont_TextWidth(Font, text)/2,
183                         y, text);
184 }