- memleak fix and menu fix from MatzeB
[supertux.git] / src / text.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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
19 //  02111-1307, USA.
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include "globals.h"
24 #include "defines.h"
25 #include "screen.h"
26 #include "text.h"
27
28 Text::Text(const std::string& file, int kind_, int w_, int h_)
29 {
30   kind = kind_;
31   w = w_;
32   h = h_;
33
34   int mx, my;
35   SDL_Surface *conv;
36   int pixels;
37   int i;
38   
39   if(kind == TEXT_TEXT)
40     {
41       mx = 26;
42       my = 3;
43     }
44   else if(kind == TEXT_NUM)
45     {
46       mx = 10;
47       my = 1;
48     }
49   else
50     {
51       mx = 0;
52       my = 0;
53     }
54
55   chars = new Surface(file, USE_ALPHA);
56
57   // Load shadow font.
58   conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
59   pixels = conv->w * conv->h;
60   SDL_LockSurface(conv);
61   for(i = 0; i < pixels; ++i)
62     {
63       Uint32 *p = (Uint32 *)conv->pixels + i;
64       *p = *p & conv->format->Amask;
65     }
66   SDL_UnlockSurface(conv);
67   SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
68   shadow_chars = new Surface(conv, USE_ALPHA);
69
70   SDL_FreeSurface(conv);
71 }
72
73 void
74 Text::draw(const  char* text, int x, int y, int shadowsize, int update)
75 {
76   if(text != NULL)
77     {
78       if(shadowsize != 0)
79         draw_chars(shadow_chars, text,x+shadowsize,y+shadowsize, update);
80
81       draw_chars(chars, text,x,y, update);
82     }
83 }
84
85 void
86 Text::draw_chars(Surface* pchars,const  char* text, int x, int y, int update)
87 {
88   int i,j,len;
89
90   len = strlen(text);
91   int w = this->w;
92   int h = this->h;
93
94   if(kind == TEXT_TEXT)
95     {
96       for( i = 0, j = 0; i < len; ++i,++j)
97         {
98           if( text[i] >= 'A' && text[i] <= 'Z')
99             pchars->draw_part((int)(text[i] - 'A')*w, 0, x+(j*w), y, w, h, 255,  update);
100           else if( text[i] >= 'a' && text[i] <= 'z')
101             pchars->draw_part((int)(text[i] - 'a')*w, h, x+(j*w), y, w, h, 255,  update);
102           else if ( text[i] >= '!' && text[i] <= '9')
103             pchars->draw_part((int)(text[i] - '!')*w, h*2, x+(j*w), y, w, h, 255,  update);
104           else if ( text[i] == '?')
105             pchars->draw_part(25*w, h*2, x+(j*w), y, w, h, 255,  update);
106           else if ( text[i] == '\n')
107             {
108               y += h + 2;
109               j = 0;
110             }
111         }
112     }
113   else if(kind == TEXT_NUM)
114     {
115       for( i = 0, j = 0; i < len; ++i, ++j)
116         {
117           if ( text[i] >= '0' && text[i] <= '9')
118             pchars->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255, update);
119           else if ( text[i] == '\n')
120             {
121               y += h + 2;
122               j = 0;
123             }
124         }
125     }
126 }
127
128 void
129 Text::draw_align(const char* text, int x, int y,
130                       TextHAlign halign, TextVAlign valign, int shadowsize, int update)
131 {
132   if(text != NULL)
133     {
134       switch (halign)
135         {
136         case A_RIGHT:
137           x += -(strlen(text)*w);
138           break;
139         case A_HMIDDLE:
140           x += -((strlen(text)*w)/2);
141           break;
142         case A_LEFT:
143           // default
144           break;
145         }
146
147       switch (valign)
148         {
149         case A_BOTTOM:
150           y -= h;
151           break;
152           
153         case A_VMIDDLE:
154           y -= h/2;
155
156         case A_TOP:
157           // default
158           break;
159         }
160
161       draw(text, x, y, shadowsize, update);
162     }
163 }
164
165 void
166 Text::drawf(const  char* text, int x, int y,
167                  TextHAlign halign, TextVAlign valign, int shadowsize, int update)
168 {
169   if(text != NULL)
170     {
171       if(halign == A_RIGHT)  /* FIXME: this doesn't work correctly for strings with newlines.*/
172         x += screen->w - (strlen(text)*w);
173       else if(halign == A_HMIDDLE)
174         x += screen->w/2 - ((strlen(text)*w)/2);
175
176       if(valign == A_BOTTOM)
177         y += screen->h - h;
178       else if(valign == A_VMIDDLE)
179         y += screen->h/2 - h/2;
180
181       draw(text,x,y,shadowsize, update);
182     }
183 }
184
185 Text::~Text()
186 {
187   if(kind == TEXT_TEXT)
188     delete chars;
189   else if(kind == TEXT_NUM)
190     delete chars;
191 }
192
193 /* --- ERASE TEXT: --- */
194
195 void
196 Text::erasetext(const  char * text, int x, int y, Surface * ptexture, int update, int shadowsize)
197 {
198   SDL_Rect dest;
199
200   dest.x = x;
201   dest.y = y;
202   dest.w = strlen(text) * w + shadowsize;
203   dest.h = h;
204
205   if (dest.w > screen->w)
206     dest.w = screen->w;
207
208   ptexture->draw_part(dest.x,dest.y,dest.x,dest.y,dest.w,dest.h, 255, update);
209
210   if (update == UPDATE)
211     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
212 }
213
214
215 /* --- ERASE CENTERED TEXT: --- */
216
217 void
218 Text::erasecenteredtext(const  char * text, int y, Surface * ptexture, int update, int shadowsize)
219 {
220   erasetext(text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize);
221 }