-Changed drawing model. Everything is handled through DrawingContext now and
[supertux.git] / src / screen / font.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 "font.h"
27 #include "drawing_context.h"
28
29 Font::Font(const std::string& file, int kind_, int w_, int h_, int shadowsize_)
30 {
31   kind = kind_;
32   w = w_;
33   h = h_;
34   shadowsize = shadowsize_;
35
36   int mx, my;
37   SDL_Surface *conv;
38   int pixels;
39   int i;
40   
41   if(kind == TEXT_TEXT)
42     {
43       mx = 26;
44       my = 3;
45     }
46   else if(kind == TEXT_NUM)
47     {
48       mx = 10;
49       my = 1;
50     }
51   else
52     {
53       mx = 0;
54       my = 0;
55     }
56
57   chars = new Surface(file, USE_ALPHA);
58
59   // Load shadow font.
60   conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
61   pixels = conv->w * conv->h;
62   SDL_LockSurface(conv);
63   for(i = 0; i < pixels; ++i)
64     {
65       Uint32 *p = (Uint32 *)conv->pixels + i;
66       *p = *p & conv->format->Amask;
67     }
68   SDL_UnlockSurface(conv);
69   SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
70   shadow_chars = new Surface(conv, USE_ALPHA);
71
72   SDL_FreeSurface(conv);
73 }
74
75 Font::~Font()
76 {
77   delete chars;
78   delete shadow_chars;
79 }
80
81 float
82 Font::get_height() const
83 {
84   return h;
85 }
86
87 float
88 Font::get_text_width(const std::string& text) const
89 {
90   return text.size() * w;
91 }
92
93 void
94 Font::draw(const std::string& text, const Vector& pos)
95 {
96   if(shadowsize != 0)
97     draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize));
98
99   draw_chars(chars, text, pos);
100 }
101
102 void
103 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos)
104 {
105   size_t i, j;
106
107   SurfaceImpl* impl = pchars->impl;
108
109   int x = int(pos.x);
110   int y = int(pos.y);
111   if(kind == TEXT_TEXT)
112     {
113       for( i = 0, j = 0; i < text.size(); ++i,++j)
114         {
115           if( text[i] >= ' ' && text[i] <= '/')
116             impl->draw_part((int)(text[i] - ' ')*w,  0 , x+(j*w), y, w, h, 255);
117           else if( text[i] >= '0' && text[i] <= '?')
118             impl->draw_part((int)(text[i] - '0')*w, h*1, x+(j*w), y, w, h, 255);
119           else if ( text[i] >= '@' && text[i] <= 'O')
120             impl->draw_part((int)(text[i] - '@')*w, h*2, x+(j*w), y, w, h, 255);
121           else if ( text[i] >= 'P' && text[i] <= '_')
122             impl->draw_part((int)(text[i] - 'P')*w, h*3, x+(j*w), y, w, h, 255);
123           else if ( text[i] >= '`' && text[i] <= 'o')
124             impl->draw_part((int)(text[i] - '`')*w, h*4, x+(j*w), y, w, h, 255);
125           else if ( text[i] >= 'p' && text[i] <= '~')
126             impl->draw_part((int)(text[i] - 'p')*w, h*5, x+(j*w), y, w, h, 255);
127           else if ( text[i] == '\n')
128             {
129               y += h + 2;
130               j = 0;
131             }
132         }
133     }
134   else if(kind == TEXT_NUM)
135     {
136       for( i = 0, j = 0; i < text.size(); ++i, ++j)
137         {
138           if ( text[i] >= '0' && text[i] <= '9')
139             impl->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255);
140           else if ( text[i] == '\n')
141             {
142               y += h + 2;
143               j = 0;
144             }
145         }
146     }
147 }
148
149 /* --- SCROLL TEXT FUNCTION --- */
150
151 #define MAX_VEL     10
152 #define SPEED_INC   0.01
153 #define SCROLL      60
154 #define ITEMS_SPACE 4
155
156 void display_text_file(const std::string& file, const std::string& surface, float scroll_speed)
157 {
158   Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA);
159   display_text_file(file, sur, scroll_speed);
160   delete sur;
161 }
162
163 void display_text_file(const std::string& file, Surface* surface, float scroll_speed)
164 {
165   int done;
166   float scroll;
167   float speed;
168   FILE* fi;
169   char temp[1024];
170   std::vector<std::string> names;
171   char filename[1024];
172   
173   sprintf(filename,"%s/%s", datadir.c_str(), file.c_str());
174   if((fi = fopen(filename,"r")) != NULL)
175     {
176       while(fgets(temp, sizeof(temp), fi) != NULL)
177         {
178           temp[strlen(temp)-1]='\0';
179           names.push_back(temp);
180         }
181       fclose(fi);
182     }
183   else
184     {
185       names.push_back("File was not found!");
186       names.push_back(filename);
187       names.push_back("Shame on the guy, who");
188       names.push_back("forgot to include it");
189       names.push_back("in your SuperTux distribution.");
190     }
191
192   scroll = 0;
193   speed = scroll_speed / 50;
194   done = 0;
195
196   DrawingContext context;
197   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
198
199   Uint32 lastticks = SDL_GetTicks();
200   while(!done)
201     {
202       /* in case of input, exit */
203       SDL_Event event;
204       while(SDL_PollEvent(&event))
205         switch(event.type)
206           {
207           case SDL_KEYDOWN:
208             switch(event.key.keysym.sym)
209               {
210               case SDLK_UP:
211                 speed -= SPEED_INC;
212                 break;
213               case SDLK_DOWN:
214                 speed += SPEED_INC;
215                 break;
216               case SDLK_SPACE:
217               case SDLK_RETURN:
218                 if(speed >= 0)
219                   scroll += SCROLL;
220                 break;
221               case SDLK_ESCAPE:
222                 done = 1;
223                 break;
224               default:
225                 break;
226               }
227             break;
228           case SDL_QUIT:
229             done = 1;
230             break;
231           default:
232             break;
233           }
234
235       if(speed > MAX_VEL)
236         speed = MAX_VEL;
237       else if(speed < -MAX_VEL)
238         speed = -MAX_VEL;
239
240       /* draw the credits */
241       context.draw_surface(surface, Vector(0,0), 0);
242
243       float y = 0;
244       for(size_t i = 0; i < names.size(); i++) {
245         if(names[i].size() == 0) {
246           y += white_text->get_height() + ITEMS_SPACE;
247           continue;
248         }
249
250         Font* font = 0;
251         switch(names[i][0])
252         {
253           case ' ': font = white_small_text; break;
254           case '\t': font = white_text; break;
255           case '-': font = white_big_text; break;
256           case '*': font = blue_text; break;
257           default: font = blue_text; break;
258         }
259
260         context.draw_text_center(font,
261             names[i].substr(1, names[i].size()-1),
262             Vector(0, screen->h + y - scroll), LAYER_FOREGROUND1);
263         y += font->get_height() + ITEMS_SPACE;
264       }
265
266       context.do_drawing();
267
268       if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0)
269         done = 1;
270
271       Uint32 ticks = SDL_GetTicks();
272       scroll += speed * (ticks - lastticks);
273       lastticks = ticks;
274       if(scroll < 0)
275         scroll = 0;
276
277       SDL_Delay(10);
278     }
279
280   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
281   Menu::set_current(main_menu);
282 }
283