- some more bugs/cleanup to the font class
authorIngo Ruhnke <grumbel@gmx.de>
Mon, 29 Jan 2007 08:58:24 +0000 (08:58 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Mon, 29 Jan 2007 08:58:24 +0000 (08:58 +0000)
- shadows are now usable with fixed width fonts, still buggy, but looking mostly ok
- fixed all fonts to variable width

SVN-Revision: 4723

src/resources.cpp
src/video/font.cpp
src/video/font.hpp

index ef251a6..b18cdad 100644 (file)
@@ -45,24 +45,22 @@ void load_shared()
   MouseCursor::set_current(mouse_cursor);
 
   /* Load global images: */
-  gold_text  = new Font(Font::FIXED,
+  gold_text  = new Font(Font::VARIABLE,
                         "images/engine/fonts/gold.png",
                         "images/engine/fonts/shadow.png", 16, 18);
-  blue_text  = new Font(Font::FIXED,
+  blue_text  = new Font(Font::VARIABLE,
                         "images/engine/fonts/blue.png",
                         "images/engine/fonts/shadow.png", 16, 18, 3);
-  //  white_text = new Font("images/engine/fonts/white.png",
-  // "images/engine/fonts/shadow.png", 16, 18);
   white_text = new Font(Font::VARIABLE,
-                        "images/engine/fonts/white.png", 16, 18);
-  gray_text  = new Font(Font::FIXED,
+                        "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",
-                              8, 9);
-  //                              "images/engine/fonts/shadow-small.png", 8, 9, 1);
-  white_big_text = new Font(Font::FIXED,
+                              "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);
 
index 395b6c3..92eb42a 100644 (file)
@@ -90,82 +90,88 @@ bool vline_empty(SDL_Surface* surface, int x, int start_y, int end_y, Uint8 thre
 } // namespace
 
 Font::Font(GlyphWidth glyph_width_, 
-           const std::string& file, const std::string& shadowfile,
-           int char_width, int char_height_, int shadowsize)
+           const std::string& filename, 
+           const std::string& shadowfile,
+           int char_width, int char_height_,
+           int shadowsize_)
   : glyph_width(glyph_width_),
-    glyph_surface(0), shadow_chars(0),
+    glyph_surface(0), shadow_glyph_surface(0), 
     char_height(char_height_), 
-    shadowsize(shadowsize)
+    shadowsize(shadowsize_)
 {
-  glyph_surface = new Surface(file);
-  shadow_chars  = new Surface(shadowfile);
+  glyph_surface = new Surface(filename);
+  shadow_glyph_surface  = new Surface(shadowfile);
 
   first_char = 32;
   char_count = ((int) glyph_surface->get_height() / char_height) * 16;
 
-  for(uint32_t i = 0; i < char_count; ++i)
+  if (glyph_width == FIXED)
     {
-      float x = (i % 16) * char_width;
-      float y = (i / 16) * char_height;
-      glyphs.push_back(Rect(x, y,
-                            x + char_width, y + char_height));
+      for(uint32_t i = 0; i < char_count; ++i)
+        {
+          float x = (i % 16) * char_width;
+          float y = (i / 16) * char_height;
+          
+          Glyph glyph;
+          glyph.advance = char_width;
+          glyph.offset  = Vector(0, 0);
+          glyph.rect    = Rect(x, y, x + char_width, y + char_height);
+
+          glyphs.push_back(glyph);
+          shadow_glyphs.push_back(glyph);
+        }
     }
-}
+  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) {
+        std::ostringstream msg;
+        msg << "Couldn't load image '" << filename << "' :" << SDL_GetError();
+        throw std::runtime_error(msg.str());
+      }
 
-Font::Font(GlyphWidth glyph_width_, const std::string& filename, int char_width, int char_height_)
-  : glyph_width(glyph_width_),
-    glyph_surface(0), shadow_chars(0), 
-    char_height(char_height_), 
-    shadowsize(0)
-{
-  glyph_surface = new Surface(filename);
+      SDL_LockSurface(surface);
 
-  first_char = 32;
-  char_count = ((int) glyph_surface->get_height() / char_height) * 16;
+      for(uint32_t i = 0; i < char_count; ++i)
+        {
+          int x = (i % 16) * char_width;
+          int y = (i / 16) * char_height;
 
-  // 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) {
-    std::ostringstream msg;
-    msg << "Couldn't load image '" << filename << "' :" << SDL_GetError();
-    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;
 
-  SDL_LockSurface(surface);
+          int right = x + char_width - 1;
+          while (right > left && 
+                 vline_empty(surface, right, y, y + char_height, 64))
+            right -= 1;
 
-  for(uint32_t i = 0; i < char_count; ++i)
-    {
-      int x = (i % 16) * char_width;
-      int y = (i / 16) * char_height;
-
-      int left = x;
-      while (left < x + char_width &&
-             vline_empty(surface, left, y, y + char_height, 0))
-        left += 1;
-
-      int right = x + char_width - 1;
-      while (right > left && 
-             vline_empty(surface, right, y, y + char_height, 0))
-        right -= 1;
-
-      if (left <= right)
-        glyphs.push_back(Rect(left,  y,
-                              right+1, y + char_height));
-      else // glyph is completly transparent
-        glyphs.push_back(Rect(x,  y,
-                              x + char_width, y + char_height));
+          Glyph glyph;
+          glyph.offset = Vector(0, 0);
 
-    }
+          if (left <= right)
+            glyph.rect = Rect(left,  y, right+1, y + char_height);
+          else // glyph is completly transparent
+            glyph.rect = Rect(x,  y, x + char_width, y + char_height);
+
+          glyph.advance = glyph.rect.get_width();
+
+          glyphs.push_back(glyph);
+          shadow_glyphs.push_back(glyph);
+        }
   
-  SDL_UnlockSurface(surface);
+      SDL_UnlockSurface(surface);
 
-  SDL_FreeSurface(surface);
+      SDL_FreeSurface(surface);
+    }
 }
 
 Font::~Font()
 {
   delete glyph_surface;
-  delete shadow_chars;
+  delete shadow_glyph_surface;
 }
 
 float
@@ -184,7 +190,7 @@ Font::get_text_width(const std::string& text) const
       else
         {
           int idx = chr2glyph(*it);
-          curr_width += glyphs[idx].get_width();
+          curr_width += glyphs[idx].advance;
         }
     }
 
@@ -257,6 +263,10 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
           else if(alignment == ALIGN_RIGHT)
             pos.x -= get_text_width(temp);
           
+          // Cast font position to integer to get a clean drawing result and
+          // no bluring as we would get with subpixel positions
+          pos.x = static_cast<int>(pos.x);
+
           draw_text(temp, pos, drawing_effect, alpha);
 
           if (i == text.size())
@@ -273,8 +283,13 @@ Font::draw_text(const std::string& text, const Vector& pos,
                 DrawingEffect drawing_effect, float alpha) const
 {
   if(shadowsize > 0)
-    draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
-               drawing_effect, alpha);
+    {
+      // 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 noticable
+      draw_chars(shadow_glyph_surface, text, pos + Vector(shadowsize, shadowsize),
+                 drawing_effect, alpha);
+    }
 
   draw_chars(glyph_surface, text, pos, drawing_effect, alpha);
 }
@@ -306,6 +321,7 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
                  DrawingEffect drawing_effect, float alpha) const
 {
   Vector p = pos;
+
   for(UTF8Iterator it(text); !it.done(); ++it)
     {
       int font_index = chr2glyph(*it);
@@ -317,16 +333,18 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
         }
       else if(*it == ' ') 
         {
-          p.x += glyphs[font_index].get_width();
+          p.x += glyphs[font_index].advance;
         } 
       else 
         {
-          const Rect& glyph = glyphs[font_index];
-          pchars->draw_part(glyph.get_left(), glyph.get_top(),
-                            p.x, p.y,
-                            glyph.get_width(), glyph.get_height(),
+          const Glyph& glyph = glyphs[font_index];
+          pchars->draw_part(glyph.rect.get_left(),
+                            glyph.rect.get_top(),
+                            p.x + glyph.offset.y,
+                            p.y + glyph.offset.y,
+                            glyph.rect.get_width(), glyph.rect.get_height(),
                             alpha, drawing_effect);
-          p.x += glyphs[font_index].get_width();
+          p.x += glyphs[font_index].advance;
         }
     }
 }
index c8973b0..b8acf0a 100644 (file)
@@ -44,21 +44,15 @@ public:
 
   /** Construct a fixed-width font 
    * 
-   *  @param file image file containing the characters
-   *  @param shadowfile image file containing the characters shadows
-   *  @param w width of a character
-   *  @param h height of a character
+   *  @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
    */
-  Font(GlyphWidth glyph_width, const std::string& file, const std::string& shadowfile,
-       int w, int h, int shadowsize = 2);
-
-  /** Construct a variable-width font 
-   * 
-   *  @param file image file containing the characters
-   */
-  Font(GlyphWidth glyph_width, const std::string& filename, 
-       int char_width, int char_height);
-
+  Font(GlyphWidth glyph_width, 
+       const std::string& filename, const std::string& shadowfile,
+       int char_width, int char_height, int shadowsize = 2);
   ~Font();
 
   /** returns the width of a given text. (Note that I won't add a normal
@@ -107,7 +101,7 @@ private:
 
   GlyphWidth glyph_width;
   Surface*   glyph_surface;
-  Surface*   shadow_chars;
+  Surface*   shadow_glyph_surface;
   int char_height;
   int shadowsize;
 
@@ -116,8 +110,21 @@ private:
   /// 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 */
+    float advance;
+
+    /** Offset that is used when drawing the glyph */
+    Vector offset;
+    
+    /** Position of the glyph inside the surface */
+    Rect rect;
+  };
+
   /** Location of the characters inside the surface */
-  std::vector<Rect> glyphs;
+  std::vector<Glyph> glyphs;
+  std::vector<Glyph> shadow_glyphs;
 };
 
 #endif