qMax <qwiglydee@gmail.com>'s font patch, adds unicode support and support for drawing...
authorIngo Ruhnke <grumbel@gmx.de>
Thu, 21 Aug 2008 22:07:11 +0000 (22:07 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Thu, 21 Aug 2008 22:07:11 +0000 (22:07 +0000)
SVN-Revision: 5736

36 files changed:
data/images/engine/fonts/README
src/badguy/dispenser.cpp
src/colorscheme.cpp [new file with mode: 0644]
src/console.cpp
src/gui/menu.cpp
src/gui/menu.hpp
src/levelintro.cpp
src/levelintro.hpp
src/mainloop.cpp
src/object/gameobjs.cpp
src/object/gameobjs.hpp
src/object/level_time.cpp
src/object/level_time.hpp
src/object/text_object.cpp
src/object/text_object.hpp
src/player_status.cpp
src/player_status.hpp
src/resources.cpp
src/resources.hpp
src/statistics.cpp
src/statistics.hpp
src/textscroller.cpp
src/tile_set.cpp
src/title.cpp
src/trigger/climbable.cpp
src/trigger/climbable.hpp
src/trigger/secretarea_trigger.cpp
src/trigger/secretarea_trigger.hpp
src/video/drawing_context.cpp
src/video/drawing_context.hpp
src/video/font.cpp
src/video/font.hpp
src/video/gl_renderer.cpp
src/video/sdl_renderer.cpp
src/worldmap/worldmap.cpp
src/worldmap/worldmap.hpp

index 4faa8d3..9392ef3 100644 (file)
@@ -1,3 +1,4 @@
-The list of letters in UTF-8 format that is currently used in the fonts can be optained with:
+These are images containing glyphs of font.
+They expectde to be in RGBA pixel format and any SDL-loabale file format.
+Glyphs themselves and charsets described in data/fonts/*.stf files.
 
-ruby -e '((32..127).to_a + (128+32..383).to_a).each_with_index{|c,idx| print [c].pack("I"); if ((idx+1) % 16 == 0) then print [10].pack("I") end }' | recode "UCS-4LE..UTF-8"
index 3bbe81b..6010b14 100644 (file)
@@ -18,6 +18,7 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include <config.h>
+#include <stdexcept>
 
 #include "dispenser.hpp"
 #include "object/bullet.hpp"
diff --git a/src/colorscheme.cpp b/src/colorscheme.cpp
new file mode 100644 (file)
index 0000000..5673e00
--- /dev/null
@@ -0,0 +1,54 @@
+#include "video/color.hpp"
+
+namespace LevelIntro {
+  Color header_color(1.0,1.0,1.0);
+  Color author_color(1.0,1.0,1.0);
+  Color stat_hdr_color(1.0,1.0,1.0);
+  Color stat_color(1.0,1.0,1.0);
+}
+
+namespace Statistics {
+  Color header_color(0.5,1.0,0.2);
+  Color text_color(1.0,1.0,1.0);
+}
+
+namespace Menu {
+  Color default_color(1.0,1.0,1.0);
+  Color active_color(0.6,1.0,1.0);
+  Color inactive_color(0.5,0.5,1.0);
+  Color label_color(0.8,0.4,0.2);
+  Color field_color(1.0,0.8,0.6);
+}
+
+namespace PlayerStatus {
+  Color text_color(1.0,1.0,0.6);
+}
+
+namespace TextObject {
+  Color default_color(1.0,1.0,0.6);
+}
+
+namespace FloatingText {
+  Color text_color(1.0,1.0,0.6);
+}
+
+namespace LevelTime {
+  Color text_color(1.0,1.0,0.6);
+}
+
+namespace SecretAreaTrigger {
+  Color text_color(1.0,1.0,0.6);
+}
+
+namespace Climbable {
+  Color text_color(1.0,1.0,0.6);
+}
+
+namespace WorldMapNS { 
+  namespace WorldMap {
+  Color level_title_color(1.0,1.0,0.2);
+  Color message_color(1.0,1.0,1.0);
+  Color teleporter_message_color(0.5,1.0,0.5);
+}}
+
+
index fb1f5f3..9c82a0e 100644 (file)
@@ -53,9 +53,7 @@ Console::~Console()
 void
 Console::init_graphics()
 {
-  font.reset(new Font(Font::FIXED,
-                      "images/engine/fonts/andale12.png",
-                      "images/engine/fonts/andale12-shadow.png", 7, 14, 1));
+  font.reset(new Font(Font::FIXED,"fonts/andale12.stf",1));
   fontheight = font->get_height();
   background.reset(new Surface("images/engine/console.png"));
   background2.reset(new Surface("images/engine/console2.png"));
index b7873b6..6571e3f 100644 (file)
@@ -51,11 +51,6 @@ std::vector<Menu*> Menu::last_menus;
 std::list<Menu*> Menu::all_menus;
 Menu* Menu::current_ = 0;
 Menu* Menu::previous = 0;
-Font* Menu::default_font;
-Font* Menu::active_font;
-Font* Menu::inactive_font;
-Font* Menu::label_font;
-Font* Menu::field_font;
 
 /* just displays a Yes/No text that can be used to confirm stuff */
 bool confirm_dialog(Surface *background, std::string text)
@@ -207,11 +202,11 @@ void
 MenuItem::set_help(const std::string& help_text)
 {
   std::string overflow;
-  help = Menu::default_font->wrap_to_width(help_text, 600, &overflow);
+  help = normal_font->wrap_to_width(help_text, 600, &overflow);
   while (!overflow.empty())
     {
       help += "\n";
-      help += Menu::default_font->wrap_to_width(overflow, 600, &overflow);
+      help += normal_font->wrap_to_width(overflow, 600, &overflow);
     }
 }
 
@@ -626,19 +621,19 @@ Menu::draw_item(DrawingContext& context, int index)
 
   MenuItem& pitem = *(items[index]);
 
-  Font* text_font = default_font;
+  Color text_color = default_color;
   float x_pos       = pos_x;
   float y_pos       = pos_y + 24*index - menu_height/2 + 12;
   int shadow_size = 2;
-  int text_width  = int(text_font->get_text_width(pitem.text));
-  int input_width = int(text_font->get_text_width(pitem.input) + 10);
+  int text_width  = int(normal_font->get_text_width(pitem.text));
+  int input_width = int(normal_font->get_text_width(pitem.input) + 10);
   int list_width = 0;
 
   float left  = pos_x - menu_width/2 + 16;
   float right = pos_x + menu_width/2 - 16;
 
   if(pitem.list.size() > 0) {
-    list_width = (int) text_font->get_text_width(pitem.list[pitem.selected]);
+    list_width = (int) normal_font->get_text_width(pitem.list[pitem.selected]);
   }
 
   if (arrange_left)
@@ -647,7 +642,7 @@ Menu::draw_item(DrawingContext& context, int index)
   if(index == active_item)
     {
       shadow_size = 3;
-      text_font = active_font;
+      text_color = active_color;
     }
 
   if(active_item == index)
@@ -669,9 +664,9 @@ Menu::draw_item(DrawingContext& context, int index)
     {
     case MN_INACTIVE:
       {
-        context.draw_text(inactive_font, pitem.text,
-                          Vector(pos_x, y_pos - int(inactive_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, inactive_color);
         break;
       }
 
@@ -691,9 +686,9 @@ Menu::draw_item(DrawingContext& context, int index)
       }
     case MN_LABEL:
       {
-        context.draw_text(label_font, pitem.text,
-                          Vector(pos_x, y_pos - int(label_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(big_font, pitem.text,
+                          Vector(pos_x, y_pos - int(big_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, label_color);
         break;
       }
     case MN_TEXTFIELD:
@@ -703,33 +698,33 @@ Menu::draw_item(DrawingContext& context, int index)
         if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD)
           {
             if(active_item == index)
-              context.draw_text(field_font,
+              context.draw_text(normal_font,
                                 pitem.get_input_with_symbol(true),
-                                Vector(right, y_pos - int(field_font->get_height()/2)),
-                                ALIGN_RIGHT, LAYER_GUI);
+                                Vector(right, y_pos - int(normal_font->get_height()/2)),
+                                ALIGN_RIGHT, LAYER_GUI, field_color);
             else
-              context.draw_text(field_font,
+              context.draw_text(normal_font,
                                 pitem.get_input_with_symbol(false),
-                                Vector(right, y_pos - int(field_font->get_height()/2)),
-                                ALIGN_RIGHT, LAYER_GUI);
+                                Vector(right, y_pos - int(normal_font->get_height()/2)),
+                                ALIGN_RIGHT, LAYER_GUI, field_color);
           }
         else
-          context.draw_text(field_font, pitem.input,
-                            Vector(right, y_pos - int(field_font->get_height()/2)),
-                            ALIGN_RIGHT, LAYER_GUI);
+          context.draw_text(normal_font, pitem.input,
+                            Vector(right, y_pos - int(normal_font->get_height()/2)),
+                            ALIGN_RIGHT, LAYER_GUI, field_color);
 
-        context.draw_text(text_font, pitem.text,
-                          Vector(left, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_LEFT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(left, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
         break;
       }
     case MN_STRINGSELECT:
       {
         float roff = arrow_left->get_width();
         // Draw left side
-        context.draw_text(text_font, pitem.text,
-                          Vector(left, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_LEFT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(left, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
 
         // Draw right side
         context.draw_surface(arrow_left.get(),
@@ -738,16 +733,16 @@ Menu::draw_item(DrawingContext& context, int index)
         context.draw_surface(arrow_right.get(),
                              Vector(right - roff, y_pos - 8),
                              LAYER_GUI);
-        context.draw_text(field_font, pitem.list[pitem.selected],
-                          Vector(right - roff, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_RIGHT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.list[pitem.selected],
+                          Vector(right - roff, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_RIGHT, LAYER_GUI, text_color);
         break;
       }
     case MN_BACK:
       {
-        context.draw_text(text_font, pitem.text,
-                          Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                          ALIGN_CENTER, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                          ALIGN_CENTER, LAYER_GUI, text_color);
         context.draw_surface(back.get(),
                              Vector(x_pos + text_width/2  + 16, y_pos - 8),
                              LAYER_GUI);
@@ -756,9 +751,9 @@ Menu::draw_item(DrawingContext& context, int index)
 
     case MN_TOGGLE:
       {
-        context.draw_text(text_font, pitem.text,
-                          Vector(pos_x - menu_width/2 + 16, y_pos - (text_font->get_height()/2)),
-                          ALIGN_LEFT, LAYER_GUI);
+        context.draw_text(normal_font, pitem.text,
+                          Vector(pos_x - menu_width/2 + 16, y_pos - (normal_font->get_height()/2)),
+                          ALIGN_LEFT, LAYER_GUI, text_color);
 
         if(pitem.toggled)
           context.draw_surface(checkbox_checked.get(),
@@ -771,15 +766,15 @@ Menu::draw_item(DrawingContext& context, int index)
         break;
       }
     case MN_ACTION:
-      context.draw_text(text_font, pitem.text,
-                        Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                        ALIGN_CENTER, LAYER_GUI);
+      context.draw_text(normal_font, pitem.text,
+                        Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                        ALIGN_CENTER, LAYER_GUI, text_color);
       break;
 
     case MN_GOTO:
-      context.draw_text(text_font, pitem.text,
-                        Vector(pos_x, y_pos - int(text_font->get_height()/2)),
-                        ALIGN_CENTER, LAYER_GUI);
+      context.draw_text(normal_font, pitem.text,
+                        Vector(pos_x, y_pos - int(normal_font->get_height()/2)),
+                        ALIGN_CENTER, LAYER_GUI, text_color);
       break;
     }
 }
@@ -792,12 +787,12 @@ Menu::get_width() const
   float menu_width = 0;
   for(unsigned int i = 0; i < items.size(); ++i)
   {
-    Font* font = default_font;
+    Font* font = normal_font;
     if(items[i]->kind == MN_LABEL)
-      font = label_font;
+      font = big_font;
 
     float w = font->get_text_width(items[i]->text) +
-        label_font->get_text_width(items[i]->input) + 16;
+        big_font->get_text_width(items[i]->input) + 16;
     if(items[i]->kind == MN_TOGGLE)
       w += 32;
 
@@ -860,8 +855,8 @@ Menu::draw(DrawingContext& context)
 
   if (!items[active_item]->help.empty())
     {
-      int text_width  = (int) default_font->get_text_width(items[active_item]->help);
-      int text_height = (int) default_font->get_text_height(items[active_item]->help);
+      int text_width  = (int) normal_font->get_text_width(items[active_item]->help);
+      int text_height = (int) normal_font->get_text_height(items[active_item]->help);
       
       Rect text_rect(pos_x - text_width/2 - 8, 
                      SCREEN_HEIGHT - 48 - text_height/2 - 4,
@@ -879,7 +874,7 @@ Menu::draw(DrawingContext& context)
                                16.0f,
                                LAYER_GUI-10);
 
-      context.draw_text(default_font, items[active_item]->help,
+      context.draw_text(normal_font, items[active_item]->help,
                         Vector(pos_x, SCREEN_HEIGHT - 48 - text_height/2),
                         ALIGN_CENTER, LAYER_GUI);
     }
index 6aaeb3f..2875b13 100644 (file)
@@ -91,6 +91,11 @@ private:
 \f
 class Menu
 {
+  static Color default_color;
+  static Color active_color;
+  static Color inactive_color;
+  static Color label_color;
+  static Color field_color;
 private:
   static std::vector<Menu*> last_menus;
 
@@ -149,12 +154,6 @@ private:
   bool close;
 
 public:
-  static Font* default_font;
-  static Font* active_font;
-  static Font* inactive_font;
-  static Font* label_font;
-  static Font* field_font;
-
   std::vector<MenuItem*> items;
 
   Menu();
index b6ee5f1..5ad48a1 100644 (file)
@@ -26,7 +26,6 @@
 #include "mainloop.hpp"
 #include "gettext.hpp"
 #include "resources.hpp"
-#include "video/font.hpp"
 #include "video/drawing_context.hpp"
 #include "gui/menu.hpp"
 #include "main.hpp"
@@ -35,7 +34,6 @@
 #include "sprite/sprite_manager.hpp"
 #include "random_generator.hpp"
 
-
 LevelIntro::LevelIntro(const Level* level, const Statistics* best_level_statistics)
         : level(level), best_level_statistics(best_level_statistics), player_sprite_py(0), player_sprite_vy(0)
 {
@@ -83,20 +81,20 @@ void
 LevelIntro::draw(DrawingContext& context)
 {
   const Statistics& stats = level->stats;
-  int py = static_cast<int>(SCREEN_HEIGHT / 2 - gold_text->get_height() / 2);
+  int py = static_cast<int>(SCREEN_HEIGHT / 2 - normal_font->get_height() / 2);
 
   context.draw_filled_rect(Vector(0, 0), Vector(SCREEN_WIDTH, SCREEN_HEIGHT), Color(0.0f, 0.0f, 0.0f, 1.0f), 0);
 
   {
-    context.draw_center_text(gold_text, level->get_name(), Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(gold_text->get_height());
+    context.draw_center_text(normal_font, level->get_name(), Vector(0, py), LAYER_FOREGROUND1, LevelIntro::header_color);
+    py += static_cast<int>(normal_font->get_height());
   }
 
   std::string author = level->get_author();
   if ((author != "") && (author != "SuperTux Team")) {
     std::string author_text = std::string(_("contributed by ")) + author;
-    context.draw_center_text(white_small_text, author_text, Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(white_small_text->get_height());
+    context.draw_center_text(small_font, author_text, Vector(0, py), LAYER_FOREGROUND1, LevelIntro::author_color);
+    py += static_cast<int>(small_font->get_height());
   }
 
   py += 32;
@@ -109,29 +107,29 @@ LevelIntro::draw(DrawingContext& context)
   py += 32;
 
   {
-    context.draw_center_text(blue_text, std::string("- ") + _("Best Level Statistics") + std::string(" -"), Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(blue_text->get_height());
+    context.draw_center_text(normal_font, std::string("- ") + _("Best Level Statistics") + std::string(" -"), Vector(0, py), LAYER_FOREGROUND1, LevelIntro::header_color);
+    py += static_cast<int>(normal_font->get_height());
   }
 
   {
     std::stringstream ss;
     ss << _("Coins") << ": " << Statistics::coins_to_string((best_level_statistics && (best_level_statistics->coins >= 0)) ? best_level_statistics->coins : 0, stats.total_coins);
-    context.draw_center_text(white_text, ss.str(), Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(white_text->get_height());
+    context.draw_center_text(normal_font, ss.str(), Vector(0, py), LAYER_FOREGROUND1, LevelIntro::stat_color);
+    py += static_cast<int>(normal_font->get_height());
   }
   
   {
     std::stringstream ss;
     ss << _("Secrets") << ": " << Statistics::secrets_to_string((best_level_statistics && (best_level_statistics->coins >= 0)) ? best_level_statistics->secrets : 0, stats.total_secrets);
-    context.draw_center_text(white_text, ss.str(), Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(white_text->get_height());
+    context.draw_center_text(normal_font, ss.str(), Vector(0, py), LAYER_FOREGROUND1,LevelIntro::stat_color);
+    py += static_cast<int>(normal_font->get_height());
   }
 
   {
     std::stringstream ss;
     ss << _("Time") << ": " << Statistics::time_to_string((best_level_statistics && (best_level_statistics->coins >= 0)) ? best_level_statistics->time : 0);
-    context.draw_center_text(white_text, ss.str(), Vector(0, py), LAYER_FOREGROUND1);
-    py += static_cast<int>(white_text->get_height());
+    context.draw_center_text(normal_font, ss.str(), Vector(0, py), LAYER_FOREGROUND1,LevelIntro::stat_color);
+    py += static_cast<int>(normal_font->get_height());
   }
 
 }
index fc60287..6765eed 100644 (file)
 
 class DrawingContext;
 class Surface;
-class Font;
 
 /**
  * Screen that welcomes the player to a level
  */
 class LevelIntro : public Screen
 {
+  static Color header_color;
+  static Color author_color;
+  static Color stat_color;
 public:
   LevelIntro(const Level* level, const Statistics* best_level_statistics);
   virtual ~LevelIntro();
index 1a7a132..08525fa 100644 (file)
@@ -124,8 +124,8 @@ MainLoop::draw_fps(DrawingContext& context, float fps_fps)
   char str[60];
   snprintf(str, sizeof(str), "%3.1f", fps_fps);
   const char* fpstext = "FPS";
-  context.draw_text(white_text, fpstext, Vector(SCREEN_WIDTH - white_text->get_text_width(fpstext) - gold_text->get_text_width(" 99999") - BORDER_X, BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
-  context.draw_text(gold_text, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
+  context.draw_text(small_font, fpstext, Vector(SCREEN_WIDTH - small_font->get_text_width(fpstext) - small_font->get_text_width(" 99999") - BORDER_X, BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
+  context.draw_text(small_font, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
 }
 
 void
index a0276ed..59b09ce 100644 (file)
@@ -170,7 +170,7 @@ FloatingText::draw(DrawingContext& context)
   context.push_transform();
   context.set_alpha(alpha);
 
-  context.draw_text(gold_text, text, position, ALIGN_LEFT, LAYER_OBJECTS+1);
+  context.draw_text(normal_font, text, position, ALIGN_LEFT, LAYER_OBJECTS+1, FloatingText::text_color);
 
   context.pop_transform();
 }
index b3d50d7..c733466 100644 (file)
@@ -66,6 +66,7 @@ private:
 
 class FloatingText : public GameObject
 {
+  static Color text_color;
 public:
   FloatingText(const Vector& pos, const std::string& text_);
   FloatingText(const Vector& pos, int s);  // use this for score, for instance
index 92a5a90..3244a46 100644 (file)
@@ -96,9 +96,9 @@ LevelTime::draw(DrawingContext& context)
 
     Surface* time_surf = time_surface.get();
     if (time_surf) {
-      float all_width = time_surf->get_width() + white_text->get_text_width(time_text);
+      float all_width = time_surf->get_width() + normal_font->get_text_width(time_text);
       context.draw_surface(time_surf, Vector((SCREEN_WIDTH - all_width)/2, BORDER_Y + 1), LAYER_FOREGROUND1);
-      context.draw_text(gold_text, time_text, Vector((SCREEN_WIDTH - all_width)/2 + time_surf->get_width(), BORDER_Y), ALIGN_LEFT, LAYER_FOREGROUND1);
+      context.draw_text(normal_font, time_text, Vector((SCREEN_WIDTH - all_width)/2 + time_surf->get_width(), BORDER_Y), ALIGN_LEFT, LAYER_FOREGROUND1, LevelTime::text_color);
     }
   }
 
index 2ef9c8c..348bd9c 100644 (file)
 #include "lisp/lisp.hpp"
 #include "video/surface.hpp"
 #include "script_interface.hpp"
+#include "video/color.hpp"
 
 class LevelTime : public GameObject, public ScriptInterface
 {
+    static Color text_color;
 public:
     LevelTime(const lisp::Lisp& reader);
 
index 4271628..ebe3e32 100644 (file)
@@ -33,7 +33,7 @@ TextObject::TextObject(std::string name)
     pos(0, 0)
 {
   this->name = name;
-  font = blue_text;
+  font = normal_font;
   centered = false;
 }
 
@@ -62,18 +62,12 @@ TextObject::unexpose(HSQUIRRELVM vm, SQInteger table_idx)
 void
 TextObject::set_font(const std::string& name)
 {
-  if(name == "gold") {
-    font = gold_text;
-  } else if(name == "white") {
-    font = white_text;
-  } else if(name == "blue") {
-    font = blue_text;
-  } else if(name == "gray") {
-    font = gray_text;
+  if(name == "normal") {
+    font = normal_font;
   } else if(name == "big") {
-    font = white_big_text;
+    font = big_font;
   } else if(name == "small") {
-    font = white_small_text;
+    font = small_font;
   } else {
     log_warning << "Unknown font '" << name << "'." << std::endl;
   }
@@ -134,9 +128,9 @@ TextObject::draw(DrawingContext& context)
   context.draw_filled_rect(spos, Vector(width, height),
       Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-50);
   if (centered) {
-    context.draw_center_text(font, text, spos, LAYER_GUI-40);
+    context.draw_center_text(font, text, spos, LAYER_GUI-40, TextObject::default_color);
   } else {
-    context.draw_text(font, text, spos + Vector(10, 10), ALIGN_LEFT, LAYER_GUI-40);
+    context.draw_text(font, text, spos + Vector(10, 10), ALIGN_LEFT, LAYER_GUI-40, TextObject::default_color);
   }
 
   context.pop_transform();
index b5e0862..c0e35b3 100644 (file)
@@ -24,6 +24,7 @@
 #include "scripting/text.hpp"
 #include "script_interface.hpp"
 #include "anchor_point.hpp"
+#include "video/color.hpp"
 
 class Font;
 
@@ -31,6 +32,7 @@ class Font;
 class TextObject : public GameObject, public Scripting::Text,
                    public ScriptInterface
 {
+  static Color default_color;
 public:
   TextObject(std::string name = "");
   virtual ~TextObject();
index 4bed7df..84925da 100644 (file)
@@ -159,9 +159,9 @@ PlayerStatus::draw(DrawingContext& context)
 
   Surface* coin_surf = coin_surface.get();
   if (coin_surf) {
-    context.draw_surface(coin_surf, Vector(SCREEN_WIDTH - BORDER_X - coin_surf->get_width() - gold_fixed_text->get_text_width(coins_text), BORDER_Y + 1), LAYER_HUD);
+    context.draw_surface(coin_surf, Vector(SCREEN_WIDTH - BORDER_X - coin_surf->get_width() - fixed_font->get_text_width(coins_text), BORDER_Y + 1), LAYER_HUD);
   }
-  context.draw_text(gold_fixed_text, coins_text, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y), ALIGN_RIGHT, LAYER_HUD);
+  context.draw_text(fixed_font, coins_text, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y), ALIGN_RIGHT, LAYER_HUD, PlayerStatus::text_color);
 
   context.pop_transform();
 }
index 85ac059..520bd74 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <memory>
 #include "serializable.hpp"
+#include "video/color.hpp"
 
 namespace lisp{ class Writer; }
 namespace lisp{ class Lisp; }
@@ -41,6 +42,7 @@ class DrawingContext;
  */
 class PlayerStatus : public Serializable
 {
+  static Color text_color;
 public:
   PlayerStatus();
   ~PlayerStatus();
index ba34085..4e6f6e1 100644 (file)
 #include <config.h>
 
 #include "sprite/sprite_manager.hpp"
-#include "gui/menu.hpp"
-#include "gui/button.hpp"
 #include "resources.hpp"
 #include "file_system.hpp"
 #include "tile_manager.hpp"
 #include "object/gameobjs.hpp"
 #include "object/player.hpp"
+#include "gui/mousecursor.hpp"
+#include "player_status.hpp"
 
 MouseCursor* mouse_cursor = NULL;
 
-Font* gold_text = NULL;
-Font* gold_fixed_text = NULL;
-Font* blue_text = NULL;
-Font* gray_text = NULL;
-Font* white_text = NULL;
-Font* white_small_text = NULL;
-Font* white_big_text = NULL;
+Font* fixed_font = NULL;
+Font* normal_font = NULL;
+Font* small_font = NULL;
+Font* big_font = NULL;
 
 /* Load graphics/sounds shared between all levels: */
 void load_shared()
@@ -46,35 +43,10 @@ void load_shared()
   MouseCursor::set_current(mouse_cursor);
 
   /* Load global images: */
-  gold_text  = new Font(Font::VARIABLE,
-                        "images/engine/fonts/gold.png",
-                        "images/engine/fonts/shadow.png", 16, 18);
-  gold_fixed_text  = new Font(Font::FIXED,
-                        "images/engine/fonts/gold.png",
-                        "images/engine/fonts/shadow.png", 16, 18);
-  blue_text  = new Font(Font::VARIABLE,
-                        "images/engine/fonts/blue.png",
-                        "images/engine/fonts/shadow.png", 16, 18, 3);
-  white_text = new Font(Font::VARIABLE,
-                        "images/engine/fonts/white.png",
-                        "images/engine/fonts/shadow.png", 16, 18);
-  gray_text  = new Font(Font::VARIABLE,
-                        "images/engine/fonts/gray.png",
-                       "images/engine/fonts/shadow.png", 16, 18);
-  white_small_text = new Font(Font::VARIABLE,
-                              "images/engine/fonts/white-small.png",
-                              "images/engine/fonts/shadow-small.png", 8, 9, 1);
-  white_big_text = new Font(Font::VARIABLE,
-                            "images/engine/fonts/white-big.png",
-                            "images/engine/fonts/shadow-big.png", 20, 22, 3);
-
-  Menu::default_font  = white_text;
-  Menu::active_font   = blue_text;
-  Menu::inactive_font = gray_text;
-  Menu::label_font    = white_big_text;
-  Menu::field_font    = gold_text;
-
-  Button::info_font = white_small_text;
+  fixed_font = new Font(Font::FIXED, "fonts/white.stf");
+  normal_font = new Font(Font::VARIABLE, "fonts/white.stf");
+  small_font = new Font(Font::VARIABLE, "fonts/white-small.stf", 1);
+  big_font = new Font(Font::VARIABLE, "fonts/white-big.stf", 3);
 
   tile_manager   = new TileManager();
   sprite_manager = new SpriteManager();
@@ -86,13 +58,9 @@ void load_shared()
 void unload_shared()
 {
   /* Free global images: */
-  delete gold_text;
-  delete gold_fixed_text;
-  delete white_text;
-  delete blue_text;
-  delete gray_text;
-  delete white_small_text;
-  delete white_big_text;
+  delete normal_font;
+  delete small_font;
+  delete big_font;
 
   delete sprite_manager;
   sprite_manager = NULL;
index 27d1e98..c9e5bad 100644 (file)
@@ -25,13 +25,10 @@ class MouseCursor;
 
 extern MouseCursor* mouse_cursor;
 
-extern Font* gold_text;
-extern Font* gold_fixed_text;
-extern Font* white_text;
-extern Font* blue_text;
-extern Font* gray_text;
-extern Font* white_small_text;
-extern Font* white_big_text;
+extern Font* fixed_font;
+extern Font* normal_font;
+extern Font* small_font;
+extern Font* big_font;
 
 void load_shared();
 void unload_shared();
index 9f9191e..eddd71d 100644 (file)
@@ -129,7 +129,7 @@ Statistics::draw_worldmap_info(DrawingContext& context)
   // skip draw if stats were declared invalid
   if (!valid) return;
 
-  context.draw_text(white_small_text, std::string("- ") + _("Best Level Statistics") + " -", Vector((WMAP_INFO_LEFT_X + WMAP_INFO_RIGHT_X) / 2, WMAP_INFO_TOP_Y1), ALIGN_CENTER, LAYER_GUI);
+  context.draw_text(small_font, std::string("- ") + _("Best Level Statistics") + " -", Vector((WMAP_INFO_LEFT_X + WMAP_INFO_RIGHT_X) / 2, WMAP_INFO_TOP_Y1), ALIGN_CENTER, LAYER_GUI,Statistics::header_color);
 
   std::string caption_buf;
   std::string stat_buf;
@@ -158,9 +158,9 @@ Statistics::draw_worldmap_info(DrawingContext& context)
           break;
     }
 
-    context.draw_text(white_small_text, caption_buf, Vector(WMAP_INFO_LEFT_X, posy), ALIGN_LEFT, LAYER_GUI);
-    context.draw_text(white_small_text, stat_buf, Vector(WMAP_INFO_RIGHT_X, posy), ALIGN_RIGHT, LAYER_GUI);
-    posy += white_small_text->get_height() + 2;
+    context.draw_text(small_font, caption_buf, Vector(WMAP_INFO_LEFT_X, posy), ALIGN_LEFT, LAYER_GUI, Statistics::header_color);
+    context.draw_text(small_font, stat_buf, Vector(WMAP_INFO_RIGHT_X, posy), ALIGN_RIGHT, LAYER_GUI, Statistics::text_color);
+    posy += small_font->get_height() + 2;
   }
 
 }
@@ -202,25 +202,25 @@ Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, S
   context.draw_surface(backdrop, Vector(bd_x, bd_y), LAYER_GUI);
   context.pop_transform();
 
-  context.draw_text(white_text, _("You"), Vector(col2_x, row1_y), ALIGN_LEFT, LAYER_GUI);
-  context.draw_text(white_text, _("Best"), Vector(col3_x, row1_y), ALIGN_LEFT, LAYER_GUI);
+  context.draw_text(normal_font, _("You"), Vector(col2_x, row1_y), ALIGN_LEFT, LAYER_GUI, Statistics::header_color);
+  context.draw_text(normal_font, _("Best"), Vector(col3_x, row1_y), ALIGN_LEFT, LAYER_GUI, Statistics::header_color);
 
-  context.draw_text(white_text, _("Coins"), Vector(col2_x-16, row3_y), ALIGN_RIGHT, LAYER_GUI);
+  context.draw_text(normal_font, _("Coins"), Vector(col2_x-16, row3_y), ALIGN_RIGHT, LAYER_GUI, Statistics::header_color);
   int coins_best = (best_stats && (best_stats->coins > coins)) ? best_stats->coins : coins;
   int total_coins_best = (best_stats && (best_stats->total_coins > total_coins)) ? best_stats->total_coins : total_coins;
-  context.draw_text(gold_text, coins_to_string(coins, total_coins), Vector(col2_x, row3_y), ALIGN_LEFT, LAYER_GUI);
-  context.draw_text(gold_text, coins_to_string(coins_best, total_coins_best), Vector(col3_x, row3_y), ALIGN_LEFT, LAYER_GUI);
+  context.draw_text(normal_font, coins_to_string(coins, total_coins), Vector(col2_x, row3_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
+  context.draw_text(normal_font, coins_to_string(coins_best, total_coins_best), Vector(col3_x, row3_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
 
-  context.draw_text(white_text, _("Secrets"), Vector(col2_x-16, row4_y), ALIGN_RIGHT, LAYER_GUI);
+  context.draw_text(normal_font, _("Secrets"), Vector(col2_x-16, row4_y), ALIGN_RIGHT, LAYER_GUI, Statistics::header_color);
   int secrets_best = (best_stats && (best_stats->secrets > secrets)) ? best_stats->secrets : secrets;
   int total_secrets_best = (best_stats && (best_stats->total_secrets > total_secrets)) ? best_stats->total_secrets : total_secrets;
-  context.draw_text(gold_text, secrets_to_string(secrets, total_secrets), Vector(col2_x, row4_y), ALIGN_LEFT, LAYER_GUI);
-  context.draw_text(gold_text, secrets_to_string(secrets_best, total_secrets_best), Vector(col3_x, row4_y), ALIGN_LEFT, LAYER_GUI);
+  context.draw_text(normal_font, secrets_to_string(secrets, total_secrets), Vector(col2_x, row4_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
+  context.draw_text(normal_font, secrets_to_string(secrets_best, total_secrets_best), Vector(col3_x, row4_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
 
-  context.draw_text(white_text, _("Time"), Vector(col2_x-16, row2_y), ALIGN_RIGHT, LAYER_GUI);
+  context.draw_text(normal_font, _("Time"), Vector(col2_x-16, row2_y), ALIGN_RIGHT, LAYER_GUI, Statistics::header_color);
   float time_best = (best_stats && (best_stats->time < time)) ? best_stats->time : time;
-  context.draw_text(gold_text, time_to_string(time), Vector(col2_x, row2_y), ALIGN_LEFT, LAYER_GUI);
-  context.draw_text(gold_text, time_to_string(time_best), Vector(col3_x, row2_y), ALIGN_LEFT, LAYER_GUI);
+  context.draw_text(normal_font, time_to_string(time), Vector(col2_x, row2_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
+  context.draw_text(normal_font, time_to_string(time_best), Vector(col3_x, row2_y), ALIGN_LEFT, LAYER_GUI, Statistics::text_color);
 }
 
 void
index 1fe6460..a6c6c37 100644 (file)
@@ -23,6 +23,7 @@
 #define SUPERTUX_STATISTICS_H
 
 #include <squirrel.h>
+#include "video/color.hpp"
 
 namespace lisp { class Writer; }
 namespace lisp { class Lisp; }
@@ -34,6 +35,8 @@ class DrawingContext;
  *  number of jumps and stuff */
 class Statistics
 {
+  static Color header_color;
+  static Color text_color;
 public:
   int coins; /**< coins collected */
   int total_coins; /**< coins in level */
index 74dc067..d4c4ad7 100644 (file)
@@ -230,19 +230,19 @@ Font* get_font_by_format_char(char format_char) {
   switch(format_char)
   {
     case ' ':
-      return white_small_text;
+      return small_font;
       break;
     case '\t':
-      return white_text;
+      return normal_font;
       break;
     case '-':
-      return white_big_text;
+      return big_font;
       break;
     case '*':
-      return blue_text;
+      return normal_font; // blue_text 
       break;
     case '#':
-      return white_text;
+      return normal_font;
       break;
     case '!':
       return 0;
@@ -283,7 +283,7 @@ InfoBoxLine::LineType get_linetype_by_format_char(char format_char) {
 }
 }
 
-InfoBoxLine::InfoBoxLine(char format_char, const std::string& text) : lineType(NORMAL), font(white_text), text(text), image(0)
+InfoBoxLine::InfoBoxLine(char format_char, const std::string& text) : lineType(NORMAL), font(normal_font), text(text), image(0)
 {
   font = get_font_by_format_char(format_char);
   lineType = get_linetype_by_format_char(format_char);
@@ -337,7 +337,6 @@ InfoBoxLine::split(const std::string& text, float width)
       lines.push_back(new InfoBoxLine(format_char, s2));
       s = overflow;
     } while (s.length() > 0);
-
   }
 
   return lines;
@@ -352,10 +351,10 @@ InfoBoxLine::draw(DrawingContext& context, const Rect& bbox, int layer)
       context.draw_surface(image, Vector( (bbox.p1.x + bbox.p2.x - image->get_width()) / 2, position.y), layer);
       break;
     case NORMAL_LEFT:
-      context.draw_text(font, text, Vector(position.x, position.y), ALIGN_LEFT, layer);
+      context.draw_text(font, text, Vector(position.x, position.y), ALIGN_LEFT, layer, Color(1,1,1));
       break;
     default:
-      context.draw_text(font, text, Vector((bbox.p1.x + bbox.p2.x) / 2, position.y), ALIGN_CENTER, layer);
+      context.draw_text(font, text, Vector((bbox.p1.x + bbox.p2.x) / 2, position.y), ALIGN_CENTER, layer,Color(1,1,1));
       break;
   }
 }
index 679851c..19f76fb 100644 (file)
@@ -18,6 +18,7 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
 #include <config.h>
+#include <stdexcept>
 
 #include "tile_set.hpp"
 #include "log.hpp"
index dfd577c..a187aea 100644 (file)
@@ -395,15 +395,15 @@ TitleScreen::draw(DrawingContext& context)
   // FIXME: Add something to scale the frame to the resolution of the screen
   context.draw_surface(frame.get(), Vector(0,0),LAYER_FOREGROUND1);
 
-  context.draw_text(white_small_text, "SuperTux " PACKAGE_VERSION "\n",
+  context.draw_text(small_font, "SuperTux " PACKAGE_VERSION "\n",
       Vector(5, SCREEN_HEIGHT - 50), ALIGN_LEFT, LAYER_FOREGROUND1);
-  context.draw_text(white_small_text,
+  context.draw_text(small_font,
       _(
 "Copyright (c) 2007 SuperTux Devel Team\n"
 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to\n"
 "redistribute it under certain conditions; see the file COPYING for details.\n"
 ),
-      Vector(5, SCREEN_HEIGHT - 50 + white_small_text->get_height() + 5),
+      Vector(5, SCREEN_HEIGHT - 50 + small_font->get_height() + 5),
       ALIGN_LEFT, LAYER_FOREGROUND1);
 }
 
index 38dbccf..3a498d7 100644 (file)
@@ -93,8 +93,8 @@ Climbable::draw(DrawingContext& context)
   if (climbed_by) {
     context.push_transform();
     context.set_translation(Vector(0, 0));
-    Vector pos = Vector(0, SCREEN_HEIGHT/2 - gold_text->get_height()/2);
-    context.draw_center_text(gold_text, _("Up we go..."), pos, LAYER_GUI);
+    Vector pos = Vector(0, SCREEN_HEIGHT/2 - normal_font->get_height()/2);
+    context.draw_center_text(normal_font, _("Up we go..."), pos, LAYER_GUI, Climbable::text_color);
     context.pop_transform();
   }
 }
index 170483d..359985f 100644 (file)
@@ -29,6 +29,7 @@
 
 class Climbable : public TriggerBase, public Serializable
 {
+  static Color text_color;
 public:
   Climbable(const lisp::Lisp& reader);
   Climbable(const Rect& area);
index 3debac0..51fb364 100644 (file)
@@ -77,8 +77,8 @@ SecretAreaTrigger::draw(DrawingContext& context)
   if (message_timer.started()) {
     context.push_transform();
     context.set_translation(Vector(0, 0));
-    Vector pos = Vector(0, SCREEN_HEIGHT/2 - gold_text->get_height()/2);
-    context.draw_center_text(gold_text, _("You found a secret area!"), pos, LAYER_GUI);
+    Vector pos = Vector(0, SCREEN_HEIGHT/2 - normal_font->get_height()/2);
+    context.draw_center_text(normal_font, _("You found a secret area!"), pos, LAYER_GUI, SecretAreaTrigger::text_color);
     context.pop_transform();
   }
   if (message_timer.check()) {
index 2f1130f..8500016 100644 (file)
@@ -28,6 +28,7 @@
 
 class SecretAreaTrigger : public TriggerBase, public Serializable
 {
+  static Color text_color;
 public:
   SecretAreaTrigger(const lisp::Lisp& reader);
   SecretAreaTrigger(const Rect& area, std::string fade_tilemap = "");
index f1fecb7..88e288b 100644 (file)
@@ -152,7 +152,7 @@ DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
 
 void
 DrawingContext::draw_text(const Font* font, const std::string& text,
-    const Vector& position, FontAlignment alignment, int layer)
+    const Vector& position, FontAlignment alignment, int layer, Color color)
 {
   DrawingRequest* request = new(obst) DrawingRequest();
 
@@ -162,6 +162,7 @@ DrawingContext::draw_text(const Font* font, const std::string& text,
   request->layer = layer;
   request->drawing_effect = transform.drawing_effect;
   request->alpha = transform.alpha;
+  request->color = color;
 
   TextRequest* textrequest = new(obst) TextRequest();
   textrequest->font = font;
@@ -174,10 +175,10 @@ DrawingContext::draw_text(const Font* font, const std::string& text,
 
 void
 DrawingContext::draw_center_text(const Font* font, const std::string& text,
-    const Vector& position, int layer)
+    const Vector& position, int layer, Color color)
 {
   draw_text(font, text, Vector(position.x + SCREEN_WIDTH/2, position.y),
-      ALIGN_CENTER, layer);
+      ALIGN_CENTER, layer, color);
 }
 
 void
@@ -385,7 +386,7 @@ DrawingContext::handle_drawing_requests(DrawingRequests& requests)
             {
               const TextRequest* textrequest = (TextRequest*) request.request_data;
               textrequest->font->draw(renderer, textrequest->text, request.pos,
-                  textrequest->alignment, request.drawing_effect, request.alpha);
+                  textrequest->alignment, request.drawing_effect, request.color, request.alpha);
             }
             break;
           case FILLRECT:
@@ -417,7 +418,7 @@ DrawingContext::handle_drawing_requests(DrawingRequests& requests)
             {
               const TextRequest* textrequest = (TextRequest*) request.request_data;
               textrequest->font->draw(renderer, textrequest->text, request.pos,
-                  textrequest->alignment, request.drawing_effect, request.alpha);
+                  textrequest->alignment, request.drawing_effect, request.color, request.alpha);
             }
             break;
           case FILLRECT:
index 46f6d27..0e24d3a 100644 (file)
@@ -65,13 +65,13 @@ public:
                          const Vector& size, const Vector& dest, int layer);
   /// Draws a text.
   void draw_text(const Font* font, const std::string& text,
-                 const Vector& position, FontAlignment alignment, int layer);
+                 const Vector& position, FontAlignment alignment, int layer, Color color = Color(1.0,1.0,1.0));
 
   /// Draws text on screen center (feed Vector.x with a 0).
   /// This is the same as draw_text() with a SCREEN_WIDTH/2 position and
   /// alignment set to LEFT_ALIGN
   void draw_center_text(const Font* font, const std::string& text,
-                        const Vector& position, int layer);
+                        const Vector& position, int layer, Color color = Color(1.0,1.0,1.0));
   /// Draws a color gradient onto the whole screen */
   void draw_gradient(const Color& from, const Color& to, int layer);
   /// Fills a rectangle.
index e0f5664..7ddebbd 100644 (file)
 
 #include <SDL_image.h>
 #include "physfs/physfs_sdl.hpp"
+#include <physfs.h>
+#include "file_system.hpp"
 
-#include "lisp/parser.hpp"
 #include "lisp/lisp.hpp"
+#include "lisp/parser.hpp"
+#include "lisp/list_iterator.hpp"
 #include "screen.hpp"
 #include "font.hpp"
 #include "renderer.hpp"
@@ -38,6 +41,7 @@
 namespace {
 bool     has_multibyte_mark(unsigned char c);
 uint32_t decode_utf8(const std::string& text, size_t& p);
+std::string encode_utf8(uint32_t code);
 
 struct UTF8Iterator
 {
@@ -97,87 +101,183 @@ bool vline_empty(SDL_Surface* surface, int x, int start_y, int end_y, Uint8 thre
 
 Font::Font(GlyphWidth glyph_width_,
            const std::string& filename,
-           const std::string& shadowfile,
-           int char_width, int char_height_,
            int shadowsize_)
-  : glyph_width(glyph_width_),
-    glyph_surface(0), shadow_glyph_surface(0),
-    char_height(char_height_),
-    shadowsize(shadowsize_)
+:   glyph_width(glyph_width_),
+    shadowsize(shadowsize_),
+    glyphs(65536)
 {
-  glyph_surface = new Surface(filename);
-  shadow_glyph_surface  = new Surface(shadowfile);
+  for(unsigned int i=0; i<65536;i++) glyphs[i].surface_idx = -1;
 
-  first_char = 32;
-  char_count = ((int) glyph_surface->get_height() / char_height) * 16;
+  const std::string fontdir = FileSystem::dirname(filename);
+  const std::string fontname = FileSystem::basename(filename);
 
-  if (glyph_width == FIXED)
-    {
-      for(uint32_t i = 0; i < char_count; ++i)
-        {
-          float x = (i % 16) * char_width;
-          float y = (i / 16) * char_height;
+  // scan for prefix-filename in addons search path
+  char **rc = PHYSFS_enumerateFiles(fontdir.c_str());
+  for (char **i = rc; *i != NULL; i++) {
+    std::string filename(*i);
+    if( filename.rfind(fontname) != std::string::npos ) {
+      loadFontFile(fontdir + filename);
+      }
+    }
+  PHYSFS_freeList(rc);
+}
 
-          Glyph glyph;
-          glyph.advance = char_width;
-          glyph.offset  = Vector(0, 0);
-          glyph.rect    = Rect(x, y, x + char_width, y + char_height);
+void 
+Font::loadFontFile(const std::string &filename)
+{
+  lisp::Parser parser;
+  log_debug << "Loading font: " << filename << std::endl;
+  const lisp::Lisp* root = parser.parse(filename);
+  const lisp::Lisp* config_l = root->get_lisp("supertux-font");
+
+  if(!config_l) {
+    std::ostringstream msg;
+    msg << "Font file:" << filename << ": is not a supertux-font file";
+    throw std::runtime_error(msg.str());
+    }
 
-          glyphs.push_back(glyph);
-          shadow_glyphs.push_back(glyph);
-        }
+  int def_char_width=0;
+
+  if( !config_l->get("glyph-width",def_char_width) ) {
+    log_warning << "Font:"<< filename << ": misses default glyph-width" << std::endl;
     }
-  else // glyph_width == VARIABLE
-    {
-      // Load the surface into RAM and scan the pixel data for characters
-      SDL_Surface* surface = IMG_Load_RW(get_physfs_SDLRWops(filename), 1);
-      if(surface == NULL) {
+  
+  if( !config_l->get("glyph-height",char_height) ) {
+    std::ostringstream msg;
+    msg << "Font:" << filename << ": misses glyph-height";
+    throw std::runtime_error(msg.str());
+    }
+
+  lisp::ListIterator iter(config_l);
+  while(iter.next()) {
+    const std::string& token = iter.item();
+    if( token == "surface" ) {
+      const lisp::Lisp * glyphs_val = iter.lisp();
+      int local_char_width;
+      bool monospaced;
+      GlyphWidth local_glyph_width;
+      std::string glyph_image;
+      std::string shadow_image;
+      std::vector<std::string> chars;
+      if( ! glyphs_val->get("glyph-width", local_char_width) ) {
+        local_char_width = def_char_width;
+        }
+      if( ! glyphs_val->get("monospace", monospaced ) ) {
+        local_glyph_width = glyph_width;
+        }
+      else {
+        if( monospaced ) local_glyph_width = FIXED;
+        else local_glyph_width = VARIABLE;
+        }
+      if( ! glyphs_val->get("glyphs", glyph_image) ) {
         std::ostringstream msg;
-        msg << "Couldn't load image '" << filename << "' :" << SDL_GetError();
+        msg << "Font:" << filename << ": missing glyphs image";
         throw std::runtime_error(msg.str());
-      }
-
-      SDL_LockSurface(surface);
-
-      for(uint32_t i = 0; i < char_count; ++i)
-        {
-          int x = (i % 16) * char_width;
-          int y = (i / 16) * char_height;
+        }
+      if( ! glyphs_val->get("shadows", shadow_image) ) {
+        std::ostringstream msg;
+        msg << "Font:" << filename << ": missing shadows image";
+        throw std::runtime_error(msg.str());
+        }
+      if( ! glyphs_val->get_vector("chars", chars) || chars.size() == 0) {
+        std::ostringstream msg;
+        msg << "Font:" << filename << ": missing chars definition";
+        throw std::runtime_error(msg.str());
+        }
 
-          int left = x;
-          while (left < x + char_width &&
-                 vline_empty(surface, left, y, y + char_height, 64))
-            left += 1;
+      if( local_char_width==0 ) {
+        std::ostringstream msg;
+        msg << "Font:" << filename << ": misses glyph-width for some surface";
+        throw std::runtime_error(msg.str());
+        }
 
-          int right = x + char_width - 1;
-          while (right > left &&
-                 vline_empty(surface, right, y, y + char_height, 64))
-            right -= 1;
+      loadFontSurface(glyph_image, shadow_image, chars,
+                 local_glyph_width, local_char_width);
+      }
+    }
+}
 
-          Glyph glyph;
-          glyph.offset = Vector(0, 0);
+void 
+Font::loadFontSurface(
+  const std::string &glyphimage,
+  const std::string &shadowimage,
+  const std::vector<std::string> &chars,
+  GlyphWidth glyph_width,
+  int char_width
+  )
+{
+  Surface glyph_surface = Surface("images/engine/fonts/" + glyphimage);
+  Surface shadow_surface = Surface("images/engine/fonts/" + shadowimage);
 
-          if (left <= right)
-            glyph.rect = Rect(left,  y, right+1, y + char_height);
-          else // glyph is completely transparent
-            glyph.rect = Rect(x,  y, x + char_width, y + char_height);
+  int surface_idx = glyph_surfaces.size();
+  glyph_surfaces.push_back(glyph_surface);
+  shadow_surfaces.push_back(shadow_surface);
 
-          glyph.advance = glyph.rect.get_width() + 1; // FIXME: might be useful to make spacing configurable
+  int row=0, col=0;
+  int wrap = glyph_surface.get_width() / char_width;
+  SDL_Surface *surface = NULL;
+  
+  if( glyph_width == VARIABLE ) {
+    //this does not work:
+    // surface = ((SDL::Texture *)glyph_surface.get_texture())->get_texture();
+    surface = IMG_Load_RW(get_physfs_SDLRWops("images/engine/fonts/"+glyphimage), 1);
+    if(surface == NULL) {
+      std::ostringstream msg;
+      msg << "Couldn't load image '" << glyphimage << "' :" << SDL_GetError();
+      throw std::runtime_error(msg.str());
+      }
+    SDL_LockSurface(surface);
+    }
 
-          glyphs.push_back(glyph);
-          shadow_glyphs.push_back(glyph);
+  for( unsigned int i = 0; i < chars.size(); i++) {
+    for(UTF8Iterator chr(chars[i]); !chr.done(); ++chr) {
+      float y = row * char_height;
+      float x = col * char_width;
+      if( ++col == wrap ) { col=0; row++; }
+      if( *chr == 0x0020 && glyphs[0x20].surface_idx != -1) continue;
+        
+      Glyph glyph;
+      glyph.surface_idx   = surface_idx;
+      
+      if( glyph_width == FIXED ) {
+        glyph.rect    = Rect(x, y, x + char_width, y + char_height);
+        glyph.offset  = Vector(0, 0);
+        glyph.advance = char_width;
+        }
+      else {
+        int left = x;
+        while (left < x + char_width && vline_empty(surface, left, y, y + char_height, 64))
+          left += 1;
+        int right = x + char_width - 1;
+        while (right > left && vline_empty(surface, right, y, y + char_height, 64))
+          right -= 1;
+          
+        if (left <= right)
+          glyph.rect = Rect(left,  y, right+1, y + char_height);
+        else // glyph is completely transparent
+          glyph.rect = Rect(x,  y, x + char_width, y + char_height);
+        
+        glyph.offset  = Vector(0, 0);
+        glyph.advance = glyph.rect.get_width() + 1; // FIXME: might be useful to make spacing configurable
         }
 
-      SDL_UnlockSurface(surface);
-
-      SDL_FreeSurface(surface);
+      glyphs[*chr] = glyph;
+      }
+    if( col>0 && col <= wrap ) { 
+      col = 0;
+      row++;
+      }
+    }
+  
+  if( surface != NULL ) {
+    SDL_UnlockSurface(surface);
+    SDL_FreeSurface(surface);
     }
 }
 
 Font::~Font()
 {
-  delete glyph_surface;
-  delete shadow_glyph_surface;
 }
 
 float
@@ -195,8 +295,10 @@ Font::get_text_width(const std::string& text) const
         }
       else
         {
-          int idx = chr2glyph(*it);
-          curr_width += glyphs[idx].advance;
+          if( glyphs.at(*it).surface_idx != -1 )
+            curr_width += glyphs[*it].advance;
+          else 
+            curr_width += glyphs[0x20].advance;
         }
     }
 
@@ -275,7 +377,7 @@ Font::wrap_to_width(const std::string& s_, float width, std::string* overflow)
 
 void
 Font::draw(Renderer *renderer, const std::string& text, const Vector& pos_,
-           FontAlignment alignment, DrawingEffect drawing_effect,
+           FontAlignment alignment, DrawingEffect drawing_effect, Color color,
            float alpha) const
 {
   float x = pos_.x;
@@ -300,7 +402,7 @@ Font::draw(Renderer *renderer, const std::string& text, const Vector& pos_,
           // no blurring as we would get with subpixel positions
           pos.x = static_cast<int>(pos.x);
 
-          draw_text(renderer, temp, pos, drawing_effect, alpha);
+          draw_text(renderer, temp, pos, drawing_effect, color, alpha);
 
           if (i == text.size())
             break;
@@ -313,53 +415,24 @@ Font::draw(Renderer *renderer, const std::string& text, const Vector& pos_,
 
 void
 Font::draw_text(Renderer *renderer, const std::string& text, const Vector& pos,
-                DrawingEffect drawing_effect, float alpha) const
+                DrawingEffect drawing_effect, Color color, float alpha) const
 {
   if(shadowsize > 0)
-    {
-      // FIXME: shadow_glyph_surface and glyph_surface do currently
-      // share the same glyph array, this is incorrect and should be
-      // fixed, it is however hardly noticeable
-      draw_chars(renderer, shadow_glyph_surface, text,
-                 pos + Vector(shadowsize, shadowsize), drawing_effect, alpha);
-    }
+      draw_chars(renderer, false, text, 
+                 pos + Vector(shadowsize, shadowsize), drawing_effect, Color(1,1,1), alpha);
 
-  draw_chars(renderer, glyph_surface, text, pos, drawing_effect, alpha);
-}
-
-int
-Font::chr2glyph(uint32_t chr) const
-{
-  int glyph_index = chr - first_char;
-
-  // we don't have the control chars 0x80-0xa0 in the font
-  if (chr >= 0x80) { // non-ascii character
-    glyph_index -= 32;
-    if(chr <= 0xa0) {
-      log_debug << "Unsupported utf-8 character '" << chr << "' found" << std::endl;
-      glyph_index = 0;
-    }
-  }
-
-  if(glyph_index < 0 || glyph_index >= (int) char_count) {
-    log_debug << "Unsupported utf-8 character found" << std::endl;
-    glyph_index = 0;
-  }
-
-  return glyph_index;
+  draw_chars(renderer, true, text, pos, drawing_effect, color, alpha);
 }
 
 void
-Font::draw_chars(Renderer *renderer, Surface* pchars, const std::string& text,
-                 const Vector& pos, DrawingEffect drawing_effect,
+Font::draw_chars(Renderer *renderer, bool notshadow, const std::string& text,
+                 const Vector& pos, DrawingEffect drawing_effect, Color color,
                  float alpha) const
 {
   Vector p = pos;
 
   for(UTF8Iterator it(text); !it.done(); ++it)
     {
-      int font_index = chr2glyph(*it);
-
       if(*it == '\n')
         {
           p.x = pos.x;
@@ -367,26 +440,32 @@ Font::draw_chars(Renderer *renderer, Surface* pchars, const std::string& text,
         }
       else if(*it == ' ')
         {
-          p.x += glyphs[font_index].advance;
+          p.x += glyphs[0x20].advance;
         }
       else
         {
-          const Glyph& glyph = glyphs[font_index];
+          Glyph glyph;
+          if( glyphs.at(*it).surface_idx != -1 )
+            glyph = glyphs[*it];
+          else 
+            glyph = glyphs[0x20];
+
           DrawingRequest request;
 
           request.pos = p + glyph.offset;
           request.drawing_effect = drawing_effect;
+          request.color = color;
           request.alpha = alpha;
 
           SurfacePartRequest surfacepartrequest;
           surfacepartrequest.size = glyph.rect.p2 - glyph.rect.p1;
           surfacepartrequest.source = glyph.rect.p1;
-          surfacepartrequest.surface = pchars;
+          surfacepartrequest.surface = notshadow ? &(glyph_surfaces[glyph.surface_idx]) : &(shadow_surfaces[glyph.surface_idx]);
 
           request.request_data = &surfacepartrequest;
           renderer->draw_surface_part(request);
 
-          p.x += glyphs[font_index].advance;
+          p.x += glyph.advance;
         }
     }
 }
index 82f8151..6810d47 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdint.h>
 
 #include "video/surface.hpp"
+#include "video/color.hpp"
 #include "math/vector.hpp"
 #include "math/rect.hpp"
 
@@ -47,14 +48,10 @@ public:
   /** Construct a fixed-width font
    *
    *  @param glyph_width  VARIABLE for proportional fonts, VARIABLE for monospace ones
-   *  @param filename     image file containing the characters
-   *  @param shadowfile   image file containing the characters shadows
-   *  @param char_width   width of a character
-   *  @param char_height  height of a character
+   *  @param fontfile     file in format supertux-font
+   *  @param sgadowsize   offset of shadow
    */
-  Font(GlyphWidth glyph_width,
-       const std::string& filename, const std::string& shadowfile,
-       int char_width, int char_height, int shadowsize = 2);
+  Font(GlyphWidth glyph_width, const std::string& fontfile, int shadowsize = 2);
   ~Font();
 
   /** returns the width of a given text. (Note that I won't add a normal
@@ -90,6 +87,7 @@ public:
   void draw(Renderer *renderer, const std::string& text, const Vector& pos,
             FontAlignment alignment = ALIGN_LEFT,
             DrawingEffect drawing_effect = NO_EFFECT,
+            Color color = Color(1.0,1.0,1.0),
             float alpha = 1.0f) const;
 
 private:
@@ -97,26 +95,20 @@ private:
 
   void draw_text(Renderer *renderer, const std::string& text, const Vector& pos,
                  DrawingEffect drawing_effect = NO_EFFECT,
+                 Color color = Color(1.0,1.0,1.0),
                  float alpha = 1.0f) const;
 
-  void draw_chars(Renderer *renderer, Surface* pchars, const std::string& text,
-                  const Vector& position, DrawingEffect drawing_effect,
+  void draw_chars(Renderer *renderer, bool nonshadow, const std::string& text,
+                  const Vector& position, DrawingEffect drawing_effect, Color color,
                   float alpha) const;
 
-  /** Convert a Unicode character code to the index of its glyph */
-  int chr2glyph(uint32_t chr) const;
-
   GlyphWidth glyph_width;
-  Surface*   glyph_surface;
-  Surface*   shadow_glyph_surface;
+
+  std::vector<Surface>  glyph_surfaces;
+  std::vector<Surface>  shadow_surfaces;
   int char_height;
   int shadowsize;
 
-  /// the number of the first character that is represented in the font
-  uint32_t first_char;
-  /// the number of the last character that is represented in the font
-  uint32_t char_count;
-
   struct Glyph {
     /** How many pixels should the cursor advance after printing the
         glyph */
@@ -125,13 +117,22 @@ private:
     /** Offset that is used when drawing the glyph */
     Vector offset;
 
+    /** index of containing surface */
+    int surface_idx;
+
     /** Position of the glyph inside the surface */
     Rect rect;
   };
 
-  /** Location of the characters inside the surface */
+  /** 65536 of glyphs */
   std::vector<Glyph> glyphs;
-  std::vector<Glyph> shadow_glyphs;
+  void loadFontFile(const std::string &filename);
+  void loadFontSurface(const std::string &glyphimage,
+                  const std::string &shadowimage,
+                  const std::vector<std::string> &chars,
+                  GlyphWidth glyph_width,
+                  int char_width);
 };
 
 #endif
index 83c1847..1d062c4 100644 (file)
@@ -263,7 +263,7 @@ Renderer::draw_surface_part(const DrawingRequest& request)
               uv_bottom,
               0.0,
               request.alpha,
-              Color(1.0, 1.0, 1.0),
+              request.color,
               Blend(),
               request.drawing_effect);
 }
index 33fee59..b02d0a1 100644 (file)
@@ -260,7 +260,7 @@ namespace SDL
     DrawingEffect effect = request.drawing_effect;
     if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
 
-    SDL_Surface *transform = sdltexture->get_transform(Color(1.0, 1.0, 1.0), effect);
+    SDL_Surface *transform = sdltexture->get_transform(request.color, effect);
 
     // get and check SDL_Surface
     if (transform == 0) {
index 13602da..1f2e377 100644 (file)
@@ -857,10 +857,10 @@ WorldMap::draw_status(DrawingContext& context)
         if(level->title == "")
           get_level_title(*level);
 
-        context.draw_text(white_text, level->title,
+        context.draw_text(normal_font, level->title,
                           Vector(SCREEN_WIDTH/2,
-                                 SCREEN_HEIGHT - white_text->get_height() - 30),
-                          ALIGN_CENTER, LAYER_FOREGROUND1);
+                                 SCREEN_HEIGHT - normal_font->get_height() - 30),
+                          ALIGN_CENTER, LAYER_FOREGROUND1, WorldMap::level_title_color);
 
         // if level is solved, draw level picture behind stats
         /*
@@ -887,10 +887,10 @@ WorldMap::draw_status(DrawingContext& context)
       if (special_tile->pos == tux->get_tile_pos()) {
         /* Display an in-map message in the map, if any as been selected */
         if(!special_tile->map_message.empty() && !special_tile->passive_message)
-          context.draw_text(gold_text, special_tile->map_message,
+          context.draw_text(normal_font, special_tile->map_message,
               Vector(SCREEN_WIDTH/2,
-                SCREEN_HEIGHT - white_text->get_height() - 60),
-              ALIGN_CENTER, LAYER_FOREGROUND1);
+                SCREEN_HEIGHT - normal_font->get_height() - 60),
+              ALIGN_CENTER, LAYER_FOREGROUND1, WorldMap::message_color);
         break;
       }
     }
@@ -898,17 +898,17 @@ WorldMap::draw_status(DrawingContext& context)
     // display teleporter messages
     Teleporter* teleporter = at_teleporter(tux->get_tile_pos());
     if (teleporter && (teleporter->message != "")) {
-      Vector pos = Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 30);
-      context.draw_text(white_text, teleporter->message, pos, ALIGN_CENTER, LAYER_FOREGROUND1);
+      Vector pos = Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - normal_font->get_height() - 30);
+      context.draw_text(normal_font, teleporter->message, pos, ALIGN_CENTER, LAYER_FOREGROUND1, WorldMap::teleporter_message_color);
     }
 
   }
 
   /* Display a passive message in the map, if needed */
   if(passive_message_timer.started())
-    context.draw_text(gold_text, passive_message,
-            Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 60),
-            ALIGN_CENTER, LAYER_FOREGROUND1);
+    context.draw_text(normal_font, passive_message,
+            Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - normal_font->get_height() - 60),
+            ALIGN_CENTER, LAYER_FOREGROUND1, WorldMap::message_color);
 
   context.pop_transform();
 }
index e0da9cb..8215cda 100644 (file)
@@ -69,6 +69,9 @@ Direction reverse_dir(Direction d);
  */
 class WorldMap : public Screen
 {
+  static Color level_title_color;
+  static Color message_color;
+  static Color teleporter_message_color;
 private:
   Tux* tux;