Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

imagefont.cpp

00001 /*      _______   __   __   __   ______   __   __   _______   __   __                 
00002  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\                
00003  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /                 
00004  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /                  
00005  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /                   
00006  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /                    
00007  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/                      
00008  *
00009  * Copyright (c) 2004, 2005 darkbits                        Js_./
00010  * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
00011  * Olof Naessén a.k.a jansem/yakslem                _asww7!uY`>  )\a//
00012  *                                                 _Qhm`] _f "'c  1!5m
00013  * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
00014  *                                               .)j(] .d_/ '-(  P .   S
00015  * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
00016  * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
00017  * binary forms, with or without                 )4d[#7r, .   '     )d`)[
00018  * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
00019  * that the following conditions are met:       j<<WP+k/);.        _W=j f
00020  * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
00021  *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
00022  *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
00023  *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
00024  * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
00025  *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
00026  *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
00027  *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
00028  *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
00029  *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
00030  * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
00031  *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
00032  *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
00033  *    from this software without specific        (js, \[QQW$QWW#?!V"".
00034  *    prior written permission.                    ]y:.<\..          .
00035  *                                                 -]n w/ '         [.
00036  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
00037  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
00038  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
00039  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
00041  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
00042  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
00043  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
00044  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
00045  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
00046  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
00047  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00049  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00050  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00051  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00052  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00053  */
00054 
00055 /*
00056  * For comments regarding functions please see the header file. 
00057  */
00058 
00059 #include <sstream>
00060 
00061 #include "guichan/exception.hpp"
00062 #include "guichan/imagefont.hpp"
00063 #include "guichan/image.hpp"
00064 
00065 namespace gcn
00066 {
00067     ImageFont::ImageFont(const std::string& filename, const std::string& glyphs)
00068     {
00069         if (Image::_getImageLoader() == NULL)
00070         {
00071             throw GCN_EXCEPTION("I have no ImageLoader!");
00072         }
00073 
00074         ImageLoader* imageLoader = Image::_getImageLoader();
00075         mFilename = filename;                
00076         Image::_getImageLoader()->prepare(filename);
00077         Color separator = Image::_getImageLoader()->getPixel(0, 0);
00078 
00079         int i = 0;
00080         for (i=0; separator == imageLoader->getPixel(i, 0)
00081                  && i < imageLoader->getWidth(); ++i)
00082         {         
00083         }
00084         
00085         if (i >= imageLoader->getWidth())
00086         {
00087             throw GCN_EXCEPTION("Corrupt image.");
00088         }
00089         
00090         int j = 0;
00091         for (j = 0; j < imageLoader->getHeight(); ++j)
00092         {
00093             if (separator == imageLoader->getPixel(i, j))
00094             {
00095                 break;
00096             }
00097         }                       
00098 
00099         mHeight = j;
00100         int x = 0, y = 0;
00101         unsigned char k;
00102 
00103         for (i=0; i < (int)glyphs.size(); ++i) 
00104         {
00105             k = glyphs.at(i);
00106             addGlyph(k, x, y, separator);
00107         }
00108     
00109         int w = imageLoader->getWidth();
00110         int h = imageLoader->getHeight();
00111         void* data = imageLoader->finalize();
00112     
00113         mImage = new Image(data, w, h);
00114         mRowSpacing = 0;
00115         mGlyphSpacing = 0;        
00116     }
00117 
00118     ImageFont::ImageFont(const std::string& filename, unsigned char glyphsFrom, unsigned char glyphsTo)
00119     {
00120         if (Image::_getImageLoader() == NULL)
00121         {
00122             throw GCN_EXCEPTION("I have no ImageLoader!");
00123         }
00124 
00125         ImageLoader* imageLoader = Image::_getImageLoader();
00126         mFilename = filename;                
00127         Image::_getImageLoader()->prepare(filename);
00128         Color separator = Image::_getImageLoader()->getPixel(0, 0);
00129 
00130         int i = 0;
00131         for (i=0; separator == imageLoader->getPixel(i, 0)
00132                  && i < imageLoader->getWidth(); ++i)
00133         {         
00134         }
00135         
00136         if (i >= imageLoader->getWidth())
00137         {
00138             throw GCN_EXCEPTION("Corrupt image.");
00139         }
00140         
00141         int j = 0;
00142         for (j = 0; j < imageLoader->getHeight(); ++j)
00143         {
00144             if (separator == imageLoader->getPixel(i, j))
00145             {
00146                 break;
00147             }
00148         }                       
00149 
00150         mHeight = j;
00151         int x = 0, y = 0;
00152         unsigned char k;
00153         
00154         for (i=glyphsFrom; i<glyphsTo+1; i++)
00155         {
00156             addGlyph(i, x, y, separator); 
00157         }
00158 
00159         int w = imageLoader->getWidth();
00160         int h = imageLoader->getHeight();
00161         void* data = imageLoader->finalize();
00162         
00163         mImage = new Image(data, w, h);
00164         mRowSpacing = 0;
00165         mGlyphSpacing = 0;        
00166     }
00167 
00168     ImageFont::~ImageFont()
00169     {
00170         Image::_getImageLoader()->free(mImage);
00171         delete mImage;        
00172     }
00173   
00174     int ImageFont::getWidth(unsigned char glyph) const
00175     {
00176         if (mGlyph[glyph].width == 0)
00177         {         
00178             return mGlyph[(int)(' ')].width + mGlyphSpacing;
00179         }
00180     
00181         return mGlyph[glyph].width + mGlyphSpacing;
00182     }
00183 
00184     int ImageFont::getHeight() const
00185     {
00186         return mHeight + mRowSpacing;
00187     }
00188 
00189     int ImageFont::drawGlyph(Graphics* graphics, unsigned char glyph, int x, int y)
00190     {
00191         // This is needed for drawing the Glyph in the middle if we have spacing
00192         int yoffset = getRowSpacing() >> 1;
00193         
00194         if (mGlyph[glyph].width == 0)
00195         {
00196             graphics->drawRectangle(Rectangle(x, y + 1 + yoffset, mGlyph[(int)(' ')].width - 1,
00197                                               mGlyph[(int)(' ')].height - 2));
00198       
00199             return mGlyph[(int)(' ')].width + mGlyphSpacing;
00200         }
00201     
00202         graphics->drawImage(mImage, mGlyph[glyph].x, mGlyph[glyph].y, x,
00203                             y + yoffset, mGlyph[glyph].width, mGlyph[glyph].height);
00204         
00205         return mGlyph[glyph].width + mGlyphSpacing;
00206     }
00207 
00208     void ImageFont::drawString(Graphics* graphics, const std::string& text, int x, int y)
00209     {
00210         unsigned int i;
00211     
00212         for (i = 0; i< text.size(); ++i)
00213         {
00214             drawGlyph(graphics, text.at(i), x, y);
00215             x += getWidth(text.at(i));      
00216         }    
00217     }
00218 
00219     void ImageFont::setRowSpacing(int spacing)
00220     {
00221         mRowSpacing = spacing;
00222     }
00223 
00224     int ImageFont::getRowSpacing()
00225     {
00226         return mRowSpacing;
00227     }
00228     
00229     void ImageFont::setGlyphSpacing(int spacing)
00230     {
00231         mGlyphSpacing = spacing;
00232     }
00233     
00234     int ImageFont::getGlyphSpacing()
00235     {
00236         return mGlyphSpacing;
00237     }
00238 
00239     void ImageFont::addGlyph(unsigned char c, int &x,
00240                              int &y, const Color& separator)
00241     {
00242         ImageLoader* il = Image::_getImageLoader();
00243         
00244         Color color;
00245         do
00246         {
00247             ++x;
00248 
00249             if (x >= il->getWidth())
00250             {
00251                 y += mHeight + 1;
00252                 x = 0;
00253 
00254                 if (y >= il->getHeight())
00255                 {
00256                     std::string str;
00257                     std::ostringstream os(str);
00258                     os << "Image ";
00259                     os << mFilename;
00260                     os << " with font is corrupt near character '";
00261                     os << c;
00262                     os << "'";
00263                     throw GCN_EXCEPTION(os.str());
00264                 }
00265             }            
00266 
00267             color = il->getPixel(x, y);
00268 
00269         } while (color == separator);
00270         
00271         int w = 0;
00272         
00273         do
00274         {
00275             ++w;
00276 
00277             if (x+w >= il->getWidth())
00278             {
00279                 std::string str;
00280                 std::ostringstream os(str);
00281                 os << "Image ";
00282                 os << mFilename;
00283                 os << " with font is corrupt near character '";
00284                 os << c;
00285                 os << "'";
00286                 throw GCN_EXCEPTION(os.str());
00287             }            
00288             
00289             color = il->getPixel(x + w, y);
00290             
00291         } while (color != separator);
00292         
00293         mGlyph[c] = Rectangle(x, y, w, mHeight);
00294         
00295         x += w;        
00296     }
00297 
00298     int ImageFont::getWidth(const std::string& text) const
00299     {
00300         unsigned int i;
00301         int size = 0;
00302     
00303         for (i = 0; i < text.size(); ++i)
00304         {
00305             size += getWidth(text.at(i));
00306         }
00307     
00308         return size;    
00309     }
00310     
00311     int ImageFont::getStringIndexAt(const std::string& text, int x)
00312     {
00313         unsigned int i;
00314         int size = 0;
00315     
00316         for (i = 0; i < text.size(); ++i)
00317         {
00318             size += getWidth(text.at(i));
00319       
00320             if (size > x)
00321             {
00322                 return i;
00323             }
00324         }
00325     
00326         return text.size();    
00327     }
00328 }

Generated on Tue May 17 21:23:26 2005 for Guichan by  doxygen 1.4.1