src/graphic/text.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************/
00019 
00020 #include <SDL_video.h>
00021 #include <SDL_gfxPrimitives.h>
00022 #include <string>
00023 #include <iostream> //cerr
00024 #include "text.h"
00025 #include "color.h"
00026 #include "colors.h"
00027 #include "font.h"
00028 #include "video.h"
00029 #include "../include/app.h"
00030 #include "../tool/error.h"
00031 #include "../interface/interface.h"
00032 #include "../map/map.h"
00033 
00034 Text::Text(const std::string &new_txt, Color new_color,
00035            Font* new_font, bool shadowed)
00036 {
00037                                 
00038   if( new_font == NULL )
00039     new_font = Font::GetInstance(Font::FONT_SMALL);
00040         
00041   txt = new_txt;
00042   color = new_color;
00043   font = new_font;
00044   this->shadowed = shadowed;
00045 
00046   if( shadowed ){
00047     int width = font->GetWidth("x");
00048     bg_offset = (unsigned int)width/8; // shadow offset = 0.125ex
00049     if (bg_offset < 1) bg_offset = 1;
00050   }
00051   else {
00052     bg_offset = 0;
00053   }
00054   max_width = 0;
00055 
00056   Render();
00057 }
00058 
00059 Text::~Text()
00060 {
00061 }
00062 
00063 void Text::Render()
00064 {
00065   if (txt=="") return;
00066 
00067   if (max_width != 0) {
00068     RenderMultiLines();
00069     return;
00070   }
00071 
00072   surf = font->CreateSurface(txt, color);
00073   if ( shadowed ) {
00074     background = font->CreateSurface(txt, black_color);
00075   }
00076 }
00077 
00078 void Text::RenderMultiLines()
00079 {
00080   if (txt=="") return;
00081 
00082   // Make a first try
00083   if (font->GetWidth(txt) < int(max_width)) {
00084     surf = font->CreateSurface(txt, color);
00085     if ( shadowed ) {
00086       background = font->CreateSurface(txt, black_color);
00087     }
00088     return;
00089   }
00090 
00091   // Cut the text on space
00092   std::vector<std::string> tokens;
00093   std::string::size_type old_pos = 0, current_pos = 0;
00094 
00095   while ( old_pos < txt.size() &&
00096           (current_pos = txt.find_first_of(" ", old_pos)) != std::string::npos )
00097     {
00098       std::string tmp = txt.substr(old_pos, current_pos-old_pos);
00099       if (tmp != " ") {
00100         tokens.push_back(tmp);
00101       }
00102       old_pos = current_pos+1;
00103     }
00104   tokens.push_back(txt.substr(old_pos));
00105 
00106   // Compute size
00107   std::vector<std::string> lines;
00108   uint index_lines = 0;
00109   uint index_word = 0;
00110 
00111   while (index_word < tokens.size()) 
00112     {
00113       if ( lines.size() == index_lines ) {
00114         // first word of a line
00115         lines.push_back(tokens.at(index_word));
00116 
00117       } else {
00118 
00119         if ( font->GetWidth(lines.at(index_lines)+" "+tokens.at(index_word)) > int(max_width) ) {
00120           
00121           // line will be too long : prepare next line!
00122           index_lines++;
00123           index_word--;
00124         } else {
00125           lines.at(index_lines) += " " + tokens.at(index_word);
00126         }
00127         
00128       }
00129       
00130       index_word++;
00131     }
00132   
00133   // really Render !
00134 
00135   // First, creating a destination surface
00136   Point2i size(max_width, (font->GetHeight()+2) * lines.size());
00137   surf.NewSurface(size, SDL_SWSURFACE|SDL_SRCALPHA, true);
00138   surf = surf.DisplayFormatAlpha();
00139 
00140   // Puting pixels of each image in destination surface
00141   surf.Lock();
00142 
00143   // for each lines
00144   for (uint i = 0; i < lines.size(); i++) {
00145     Surface tmp=(font->CreateSurface(lines.at(i), color)).DisplayFormatAlpha();
00146     tmp.Lock();
00147 
00148     // for each pixel lines of a source image
00149     for (int x=0; x < tmp.GetWidth() && x < int(max_width); x++) 
00150       { // for each pixel rows of a source image
00151         for (int y=0; y < tmp.GetHeight(); y++) 
00152           { 
00153             surf.PutPixel(x, ((font->GetHeight()+2)*i)+y, 
00154                           tmp.GetPixel(x, y));
00155           }
00156       }
00157     tmp.Unlock();
00158   }
00159   surf.Unlock();
00160 
00161   // Render the shadow !
00162   if (!shadowed) return;
00163 
00164   background.NewSurface(size, SDL_SWSURFACE|SDL_SRCALPHA, true);
00165   background = background.DisplayFormatAlpha();
00166 
00167   // Puting pixels of each image in destination surface
00168   background.Lock();
00169 
00170   // for each lines
00171   for (uint i = 0; i < lines.size(); i++) {
00172     Surface tmp=(font->CreateSurface(lines.at(i), black_color)).DisplayFormatAlpha();
00173     tmp.Lock();
00174 
00175     // for each pixel lines of a source image
00176     for (int x=0; x < tmp.GetWidth() && x < int(max_width); x++) 
00177       { // for each pixel rows of a source image
00178         for (int y=0; y < tmp.GetHeight(); y++) 
00179           { 
00180             background.PutPixel(x, ((font->GetHeight()+2)*i)+y, 
00181                                 tmp.GetPixel(x, y));
00182           }
00183       }
00184     tmp.Unlock();
00185   }
00186   background.Unlock();
00187 }
00188 
00189 void Text::Set(const std::string &new_txt)
00190 {
00191   if(txt == new_txt)
00192     return;
00193 
00194   txt = new_txt;
00195         
00196   Render();
00197 }
00198 
00199 const std::string& Text::GetText() const
00200 {
00201   return txt;
00202 }
00203 
00204 void Text::SetColor(const Color &new_color)
00205 {
00206   if(color == new_color)
00207     return;
00208 
00209   color = new_color;
00210         
00211   Render();
00212 }
00213 
00214 void Text::DrawCenter (int x, int y) const
00215 { 
00216   DrawTopLeft(x - surf.GetWidth() / 2, y - surf.GetHeight() / 2);
00217 }
00218 
00219 void Text::DrawCenter (const Point2i &position) const
00220 {
00221   DrawCenter(position.GetX(), position.GetY());
00222 }
00223 
00224 void Text::DrawTopRight (int x, int y) const
00225 { 
00226   DrawTopLeft( x - surf.GetWidth(), y);
00227 }
00228 
00229 void Text::DrawCenterTop (int x, int y) const
00230 { 
00231   DrawTopLeft( x - surf.GetWidth()/2, y);
00232 }
00233 
00234 void Text::DrawTopLeft(const Point2i &position) const
00235 {
00236   if(txt == "") return;
00237 
00238   Rectanglei dst_rect(position, surf.GetSize());
00239   AppWormux * app = AppWormux::GetInstance();
00240 
00241   if(shadowed){
00242     Rectanglei shad_rect;
00243     
00244     shad_rect.SetPosition(dst_rect.GetPosition() + bg_offset);
00245     shad_rect.SetSize(background.GetWidth(), background.GetHeight() );
00246     
00247     app->video.window.Blit(background, shad_rect.GetPosition());
00248     app->video.window.Blit(surf, dst_rect.GetPosition());
00249                 
00250     world.ToRedrawOnScreen(Rectanglei(dst_rect.GetPosition(),
00251                                       shad_rect.GetSize() + bg_offset));
00252   }else{
00253     app->video.window.Blit(surf, dst_rect.GetPosition());
00254     world.ToRedrawOnScreen(dst_rect);
00255   }             
00256 }
00257 
00258 void Text::DrawTopLeft (int x, int y) const
00259 { 
00260   DrawTopLeft( Point2i(x, y) );
00261 }
00262 
00263 void Text::DrawCenterOnMap (int x, int y) const
00264 {
00265   DrawTopLeftOnMap(x - surf.GetWidth()/2, y - surf.GetHeight()/2 );
00266 }
00267 
00268 void Text::DrawCenterTopOnMap (int x, int y) const
00269 {
00270   DrawTopLeftOnMap(x - surf.GetWidth()/2, y);
00271 }
00272 
00273 void Text::DrawTopLeftOnMap (int x, int y) const
00274 {
00275   if(shadowed)
00276     AbsoluteDraw(background, Point2i(bg_offset + x, bg_offset + y) );
00277   AbsoluteDraw(surf, Point2i(x, y) );
00278 }
00279 
00280 void Text::SetMaxWidth(uint max_w)
00281 {
00282   if (max_width == max_w)
00283     return;
00284 
00285   max_width = max_w;
00286 
00287   Render();
00288 }
00289 
00290 int Text::GetWidth() const
00291 {
00292   if(txt=="") return 0;
00293   return surf.GetWidth();
00294 }
00295 
00296 int Text::GetHeight() const
00297 {
00298   if(txt=="") return 0;
00299   return surf.GetHeight();
00300 }
00301 
00302 void DrawTmpBoxText(Font &font, Point2i pos, 
00303                     const std::string &txt, uint space,
00304                     Color boxColor, Color rectColor)
00305 {
00306   Point2i size = font.GetSize(txt) + Point2i(space, space)*2;
00307   
00308   pos.y -= font.GetHeight(txt)/2;
00309 
00310   Rectanglei rect( pos - size/2, size);
00311   
00312   AppWormux * app = AppWormux::GetInstance();
00313 
00314   app->video.window.BoxColor(rect, boxColor);
00315   app->video.window.RectangleColor(rect, rectColor);  
00316 
00317   world.ToRedrawOnScreen( rect );
00318   font.WriteCenterTop( pos, txt, white_color);
00319 }
00320 
00321 void DrawTmpBoxTextWithReturns(Font &font, const Point2i &position, 
00322                                const std::string &txt, uint space,
00323                                Color boxColor,
00324                                Color rectColor)
00325 {
00326   size_t pos          = 0;
00327   size_t last_pos     = 0;
00328   size_t max_width    = 0;
00329   size_t total_height = 0;
00330   int    x, y;
00331   char  *lines        = strdup(txt.c_str());
00332 
00333   std::vector< size_t > offsets;
00334 
00335   // Store offsets
00336   offsets.push_back(0);
00337   while (lines[pos] != '\0')
00338   {
00339     if (lines[pos] == '\n')
00340     {
00341       lines[pos] = 0;
00342       if (!lines[pos+1]) break;
00343 
00344       offsets.push_back(pos+1);
00345       int w = font.GetWidth(lines+last_pos) + space*2;
00346       if ((int)max_width < w) max_width = w;
00347       total_height += font.GetHeight(lines+last_pos);
00348 #if DEBUG
00349       if (last_pos)
00350       {
00351         std::cerr << "(" << pos << "," << pos-last_pos
00352                   << ") >>> " << lines+last_pos << " <<<\n";
00353       }
00354 #endif
00355       last_pos = pos+1;
00356     }
00357     pos++;
00358   }
00359   if (max_width == 0) {
00360     max_width = font.GetWidth(lines) + space*2;
00361   }
00362 
00363   // Initial position
00364   total_height += 5*space;
00365   x = position.x - max_width / 2;
00366   y = position.y - total_height / 2;
00367 
00368   Rectanglei rect(x, y, max_width, total_height);
00369   
00370   AppWormux * app = AppWormux::GetInstance();
00371 
00372   app->video.window.BoxColor(rect, boxColor);
00373   app->video.window.RectangleColor(rect, rectColor);
00374 
00375   world.ToRedrawOnScreen(rect);
00376 
00377   for( std::vector<size_t>::iterator it=offsets.begin();
00378        it != offsets.end();
00379        ++it)
00380   {
00381     font.WriteLeft( Point2i(x+space, y+space), lines+(*it), white_color);
00382     y += font.GetHeight(lines+(*it));
00383   }
00384   offsets.clear();
00385   free(lines);
00386 }

Generated on Mon Jan 1 13:10:56 2007 for Wormux by  doxygen 1.4.7