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