Added support for data files internationalization by a simple 3 lines code in lisprea...
[supertux.git] / src / screen / font.cpp
index 45f9e93..d414e1f 100644 (file)
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
 
-#include <stdlib.h>
-#include <string.h>
+#include <cstdlib>
+#include <cstring>
+
 #include "globals.h"
 #include "defines.h"
 #include "screen.h"
 #include "font.h"
 #include "drawing_context.h"
+#include "../lispreader.h"
 
-Font::Font(const std::string& file, int kind_, int w_, int h_, int shadowsize_)
+Font::Font(const std::string& file, FontType ntype, int nw, int nh,
+        int nshadowsize)
+    : chars(0), shadow_chars(0), type(ntype), w(nw), h(nh),
+      shadowsize(nshadowsize)
 {
-  kind = kind_;
-  w = w_;
-  h = h_;
-  shadowsize = shadowsize_;
-
-  int mx, my;
-  SDL_Surface *conv;
-  int pixels;
-  int i;
-  
-  if(kind == TEXT_TEXT)
-    {
-      mx = 26;
-      my = 3;
-    }
-  else if(kind == TEXT_NUM)
-    {
-      mx = 10;
-      my = 1;
-    }
-  else
-    {
-      mx = 0;
-      my = 0;
-    }
-
   chars = new Surface(file, USE_ALPHA);
-
+  switch(type) {
+    case TEXT:
+      first_char = 32;
+      break;
+    case NUM:
+      first_char = 48;
+      break;
+  }
+  last_char = first_char + (chars->h / h) * 16;
+  if(last_char > 127) // we have left out some control chars at 128-159
+    last_char += 32;
+   
   // Load shadow font.
-  conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
-  pixels = conv->w * conv->h;
-  SDL_LockSurface(conv);
-  for(i = 0; i < pixels; ++i)
-    {
+  if(shadowsize > 0) {
+    SDL_Surface* conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
+    int pixels = conv->w * conv->h;
+    SDL_LockSurface(conv);
+    for(int i = 0; i < pixels; ++i) {
       Uint32 *p = (Uint32 *)conv->pixels + i;
       *p = *p & conv->format->Amask;
     }
-  SDL_UnlockSurface(conv);
-  SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
-  shadow_chars = new Surface(conv, USE_ALPHA);
-
-  SDL_FreeSurface(conv);
+    SDL_UnlockSurface(conv);
+    SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
+    shadow_chars = new Surface(conv, USE_ALPHA);
+    SDL_FreeSurface(conv);
+  }
 }
 
 Font::~Font()
@@ -91,59 +82,45 @@ Font::get_text_width(const std::string& text) const
 }
 
 void
-Font::draw(const std::string& text, const Vector& pos)
+Font::draw(const std::string& text, const Vector& pos, Uint32 drawing_effect)
 {
-  if(shadowsize != 0)
-    draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize));
+  if(shadowsize > 0)
+    draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
+               drawing_effect);
 
-  draw_chars(chars, text, pos);
+  draw_chars(chars, text, pos, drawing_effect);
 }
 
 void
-Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos)
+Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
+                 Uint32 drawing_effect)
 {
-  size_t i, j;
-
   SurfaceImpl* impl = pchars->impl;
 
-  int x = int(pos.x);
-  int y = int(pos.y);
-  if(kind == TEXT_TEXT)
-    {
-      for( i = 0, j = 0; i < text.size(); ++i,++j)
-        {
-          if( text[i] >= ' ' && text[i] <= '/')
-            impl->draw_part((int)(text[i] - ' ')*w,  0 , x+(j*w), y, w, h, 255);
-          else if( text[i] >= '0' && text[i] <= '?')
-            impl->draw_part((int)(text[i] - '0')*w, h*1, x+(j*w), y, w, h, 255);
-          else if ( text[i] >= '@' && text[i] <= 'O')
-            impl->draw_part((int)(text[i] - '@')*w, h*2, x+(j*w), y, w, h, 255);
-          else if ( text[i] >= 'P' && text[i] <= '_')
-            impl->draw_part((int)(text[i] - 'P')*w, h*3, x+(j*w), y, w, h, 255);
-          else if ( text[i] >= '`' && text[i] <= 'o')
-            impl->draw_part((int)(text[i] - '`')*w, h*4, x+(j*w), y, w, h, 255);
-          else if ( text[i] >= 'p' && text[i] <= '~')
-            impl->draw_part((int)(text[i] - 'p')*w, h*5, x+(j*w), y, w, h, 255);
-          else if ( text[i] == '\n')
-            {
-              y += h + 2;
-              j = 0;
-            }
-        }
+  Vector p = pos;
+  for(size_t i = 0; i < text.size(); ++i)
+  {
+    int c = (unsigned char) text[i];
+    if(c > 127) // correct for the 32 controlchars at 128-159
+      c -= 32;
+    // a non-printable character?
+    if(c == '\n') {
+      p.x = pos.x;
+      p.y += h + 2;
+      continue;
     }
-  else if(kind == TEXT_NUM)
-    {
-      for( i = 0, j = 0; i < text.size(); ++i, ++j)
-        {
-          if ( text[i] >= '0' && text[i] <= '9')
-            impl->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255);
-          else if ( text[i] == '\n')
-            {
-              y += h + 2;
-              j = 0;
-            }
-        }
+    if(c == ' ' || c < first_char || c > last_char) {
+      p.x += w;
+      continue;
     }
+    
+    int index = c - first_char;
+    int source_x = (index % 16) * w;
+    int source_y = (index / 16) * h;
+
+    impl->draw_part(source_x, source_y, p.x, p.y, w, h, 255, drawing_effect);
+    p.x += w;
+  }
 }
 
 /* --- SCROLL TEXT FUNCTION --- */
@@ -162,36 +139,40 @@ void display_text_file(const std::string& file, const std::string& surface, floa
 
 void display_text_file(const std::string& file, Surface* surface, float scroll_speed)
 {
-  int done;
-  float scroll;
-  float speed;
-  FILE* fi;
-  char temp[1024];
+  std::string text;
   std::vector<std::string> names;
-  char filename[1024];
   
-  sprintf(filename,"%s/%s", datadir.c_str(), file.c_str());
-  if((fi = fopen(filename,"r")) != NULL)
+  lisp_object_t* root_obj = lisp_read_from_file(datadir + file);
+  lisp_object_t* cur = lisp_car(root_obj);
+
+  if (lisp_symbol_p(cur) && strcmp(lisp_symbol(cur), "text") == 0)
     {
-      while(fgets(temp, sizeof(temp), fi) != NULL)
-        {
-          temp[strlen(temp)-1]='\0';
-          names.push_back(temp);
-        }
-      fclose(fi);
+      LispReader reader(lisp_cdr(root_obj));
+      reader.read_string("text", text);
     }
   else
     {
-      names.push_back("File was not found!");
-      names.push_back(filename);
-      names.push_back("Shame on the guy, who");
-      names.push_back("forgot to include it");
-      names.push_back("in your SuperTux distribution.");
+      std::cerr << "Error: Could not open text. Ignoring...\n";
+      return;
+    }
+
+  unsigned int l, i;
+  l = 0;
+  while(true)
+    {
+    i = l;
+    l = text.find("\n", i);
+    if(l != std::string::npos)
+      break;
+
+    char* temp = 0;
+    text.copy(temp, l, i);
+    names.push_back(temp);
     }
 
-  scroll = 0;
-  speed = scroll_speed / 50;
-  done = 0;
+  int done = 0;
+  float scroll = 0;
+  float speed = scroll_speed / 50;
 
   DrawingContext context;
   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);