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