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