4 // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
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.
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.
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
27 #include "app/globals.h"
28 #include "lisp/parser.h"
29 #include "lisp/lisp.h"
32 #include "drawing_context.h"
34 using namespace SuperTux;
36 Font::Font(const std::string& file, FontType ntype, int nw, int nh,
38 : chars(0), shadow_chars(0), type(ntype), w(nw), h(nh),
39 shadowsize(nshadowsize)
41 chars = new Surface(file, true);
51 last_char = first_char + (chars->h / h) * 16;
52 if(last_char > 127) // we have left out some control chars at 128-159
57 SDL_Surface* conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
58 int pixels = conv->w * conv->h;
59 SDL_LockSurface(conv);
60 for(int i = 0; i < pixels; ++i) {
61 Uint32 *p = (Uint32 *)conv->pixels + i;
62 *p = *p & conv->format->Amask;
64 SDL_UnlockSurface(conv);
65 SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
66 shadow_chars = new Surface(conv, true);
67 SDL_FreeSurface(conv);
78 Font::get_text_width(const std::string& text) const
80 /** Let's calculate the size of the biggest paragraph */
81 std::string::size_type l, hl, ol;
86 l = text.find("\n", l+1);
87 if(l == std::string::npos)
99 Font::get_text_height(const std::string& text) const
101 /** Let's calculate height of the text */
102 std::string::size_type l, hh;
106 l = text.find("\n", l+1);
107 if(l == std::string::npos)
116 Font::get_height() const
122 Font::draw(const std::string& text, const Vector& pos_, int allignment, Uint32 drawing_effect, int alpha)
124 /* Cut lines changes into seperate strings, needed to support center/right text
125 allignments with break lines.
126 Feel free to replace this hack with a more elegant solution
129 std::string::size_type l, i, y;
135 l = text.find("\n", i);
136 if(l == std::string::npos)
142 temp[text.copy(temp, l - i, i)] = '\0';
144 // calculate X positions based on the allignment type
145 Vector pos = Vector(pos_);
146 if(allignment == CENTER_ALLIGN)
147 pos.x -= get_text_width(temp) / 2;
148 else if(allignment == RIGHT_ALLIGN)
149 pos.x -= get_text_width(temp);
151 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
159 Font::draw_text(const std::string& text, const Vector& pos, Uint32 drawing_effect, int alpha)
162 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
163 drawing_effect, alpha);
165 draw_chars(chars, text, pos, drawing_effect, alpha);
169 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
170 Uint32 drawing_effect, int alpha)
172 SurfaceImpl* impl = pchars->impl;
175 for(size_t i = 0; i < text.size(); ++i)
177 int c = (unsigned char) text[i];
178 if(c > 127) // correct for the 32 controlchars at 128-159
180 // a non-printable character?
186 if(c == ' ' || c < first_char || c > last_char) {
191 int index = c - first_char;
192 int source_x = (index % 16) * w;
193 int source_y = (index / 16) * h;
195 impl->draw_part(source_x, source_y, p.x, p.y, w, h, alpha, drawing_effect);
200 /* --- SCROLL TEXT FUNCTION --- */
203 #define SPEED_INC 0.01
205 #define ITEMS_SPACE 4
207 void SuperTux::display_text_file(const std::string& file, float scroll_speed,
208 Font* heading_font, Font* normal_font, Font* small_font,
209 Font* reference_font)
212 std::string background_file;
213 std::vector<std::string> names;
215 std::string filename = datadir + "/" + file;
218 std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
220 const lisp::Lisp* text_lisp = root->get_lisp("supertux-text");
222 throw std::runtime_error("File isn't a supertux-text file");
224 if(!text_lisp->get("text", text))
225 throw std::runtime_error("file doesn't contain a text field");
226 if(!text_lisp->get("background", background_file))
227 throw std::runtime_error("file doesn't contain a background file");
228 } catch(std::exception& e) {
229 std::cerr << "Couldn't load file '" << filename << "': " << e.what() <<
234 // Split text string lines into a vector
236 std::string::size_type i, l;
240 l = text.find("\n", i);
242 if(l == std::string::npos)
245 temp[text.copy(temp, text.size() - i, i)] = '\0';
246 names.push_back(temp);
251 temp[text.copy(temp, l-i, i)] = '\0';
252 names.push_back(temp);
257 // load background image
258 Surface* background = new Surface(datadir + "/images/background/" + background_file, false);
262 float speed = scroll_speed / 50;
263 float left_border = 50;
265 DrawingContext context;
266 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
268 Uint32 lastticks = SDL_GetTicks();
271 /* in case of input, exit */
273 while(SDL_PollEvent(&event))
277 switch(event.key.keysym.sym)
306 else if(speed < -MAX_VEL)
309 /* draw the credits */
310 context.draw_surface(background, Vector(0,0), 0);
313 for(size_t i = 0; i < names.size(); i++) {
314 if(names[i].size() == 0) {
315 y += normal_font->get_height() + ITEMS_SPACE;
323 case ' ': font = small_font; break;
324 case '\t': font = normal_font; break;
325 case '-': font = heading_font; break;
326 case '*': font = reference_font; break;
327 case '#': font = normal_font; center = false; break;
334 context.draw_text(font,
335 names[i].substr(1, names[i].size()-1),
336 Vector(screen->w/2, screen->h + y - scroll),
337 CENTER_ALLIGN, LAYER_FOREGROUND1);
339 context.draw_text(font,
340 names[i].substr(1, names[i].size()-1),
341 Vector(left_border, screen->h + y - scroll),
342 LEFT_ALLIGN, LAYER_FOREGROUND1);
346 y += font->get_height() + ITEMS_SPACE;
349 context.do_drawing();
351 if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0)
354 Uint32 ticks = SDL_GetTicks();
355 scroll += speed * (ticks - lastticks);
363 SDL_EnableKeyRepeat(0, 0); // disables key repeating