D:/Programmation/Cpp/SFML/src/SFML/Graphics/FontManager.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Graphics/FontManager.hpp>
00029 #include <SFML/Graphics/Color.hpp>
00030 #include <SFML/Graphics/GraphicsDevice.hpp>
00031 #include <SFML/Graphics/Image.hpp>
00032 #include <iostream>
00033 #include <vector>
00034 
00035 
00036 namespace sf_private
00037 {
00038 // Default font bitmap and description are stored in a header file as a sequence of arrays
00039 #include <SFML/Graphics/DefaultFont.hpp>
00040 
00041 
00045 sfFontManager& sfFontManager::GetInstance()
00046 {
00047     static sfFontManager Instance;
00048 
00049     return Instance;
00050 }
00051 
00052 
00056 sfFontManager::sfFontManager() :
00057 myLibrary(NULL)
00058 {
00059     // Initialize FreeType library
00060     FT_Error Error = FT_Init_FreeType(&myLibrary);
00061     if (Error)
00062     {
00063         std::cerr << "Failed to initialize FreeType library (error code : " << Error << ")" << std::endl;
00064         return;
00065     }
00066 
00067     // Create the default font
00068     CreateDefaultFont();
00069 }
00070 
00071 
00075 sfFontManager::~sfFontManager()
00076 {
00077     // Shutdown FreeType library
00078     if (myLibrary)
00079         FT_Done_FreeType(myLibrary);
00080 }
00081 
00082 
00086 const sfFontManager::Font& sfFontManager::GetBitmapFont(const std::string& Filename, unsigned int CharSize)
00087 {
00088     // Check if freetype library is correctly initialized
00089     if (!myLibrary)
00090         return myFonts["default"];
00091 
00092     // If font is "default" or empty string, return default font
00093     if ((Filename == "") || (Filename == "default"))
00094         return myFonts["default"];
00095 
00096     // If font is already loaded and char size is big enough, just return it
00097     FontTable::iterator It = myFonts.find(Filename);
00098     if ((It != myFonts.end()) && (It->second.CharSize >= CharSize))
00099         return It->second;
00100 
00101     // Clamp CharSize to make sure we won't have textures too big
00102     int MaxSize = sfGraphicsDevice::GetInstance()->GetCapabilities().MaxTextureSize;
00103     if ((int)CharSize >= MaxSize / 8) CharSize = MaxSize / 8;
00104 
00105     unsigned int Left      = 0;
00106     unsigned int Top       = 0;
00107     unsigned int TexWidth  = sfImage::GetValidTextureSize(CharSize * 8);
00108     unsigned int TexHeight = sfImage::GetValidTextureSize(CharSize * 8);
00109     std::vector<unsigned int> Tops(TexWidth, 0);
00110 
00111     // If font name has not been found, we create a new font description
00112     Font CurFont;
00113     CurFont.CharSize = CharSize;
00114     CurFont.Image.Create(TexWidth, TexHeight, sfColor(0, 0, 0, 0));
00115 
00116     // Create a new font face from specified file
00117     FT_Face FontFace;
00118     FT_Error Error = FT_New_Face(myLibrary, Filename.c_str(), 0, &FontFace);
00119     if (Error)
00120     {
00121         std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00122         return myFonts["default"];
00123     }
00124 
00125     // Setup font size
00126     Error = FT_Set_Pixel_Sizes(FontFace, CharSize, CharSize);
00127     if (Error)
00128     {
00129         std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00130         return myFonts["default"];
00131     }
00132 
00133     // Render characters set to a bitmap (printable characters start at code 31)
00134     sfIntRect Coords[256];
00135     for (int i = 31; i < 256; ++i)
00136     {
00137         // Load the glyph corresponding to current character
00138         Error = FT_Load_Char(FontFace, i, FT_LOAD_DEFAULT);
00139         if (Error)
00140         {
00141             std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00142             return myFonts["default"];
00143         }
00144 
00145         // Convert the glyph to a bitmap
00146         FT_Glyph Glyph;
00147         Error = FT_Get_Glyph(FontFace->glyph, &Glyph);
00148         if (Error)
00149         {
00150             std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00151             return myFonts["default"];
00152         }
00153         FT_Glyph_To_Bitmap(&Glyph, ft_render_mode_normal, 0, 1);
00154         FT_BitmapGlyph BitmapGlyph = (FT_BitmapGlyph)Glyph;
00155         FT_Bitmap& Bitmap = BitmapGlyph->bitmap;
00156 
00157         // TODO : handle other pixel modes
00158         if (Bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
00159         {
00160             std::cerr << "Error loading font \"" << Filename << "\" (pixel format not supported)" << std::endl;
00161             return myFonts["default"];
00162         }
00163 
00164         // Make sure we don't go over texture width
00165         if (Left + Bitmap.width >= TexWidth)
00166             Left = 0;
00167 
00168         // Compute top coordinate
00169         Top = Tops[Left];
00170         for (int x = 0; x < Bitmap.width; ++x)
00171             Top = std::max(Top, Tops[Left + x]);
00172 
00173         // Make sure we don't go over texture height
00174         if (Top + Bitmap.rows >= TexHeight)
00175             CurFont.Image.Resize(TexWidth, TexHeight * 2, sfColor(0, 0, 0, 0));
00176 
00177         // Store character position and size
00178         sfIntRect& Rect = CurFont.Rect[i];
00179         Rect.Left   = BitmapGlyph->left;
00180         Rect.Top    = -BitmapGlyph->top;
00181         Rect.Right  = Rect.Left + Bitmap.width;
00182         Rect.Bottom = Bitmap.rows - BitmapGlyph->top;
00183         CurFont.Advance[i] = FontFace->glyph->advance.x / 64;
00184 
00185         // Texture size may change, so let texture coordinates be calculated later
00186         Coords[i] = sfIntRect(Left, Top, Left + Bitmap.width, Top + Bitmap.rows);
00187 
00188         // Draw glyph into our bitmap font
00189         const sfUint8* Pixels = Bitmap.buffer;
00190         for (int y = 0; y < Bitmap.rows; ++y)
00191         {
00192             for (int x = 0; x < Bitmap.width; ++x)
00193             {
00194                 CurFont.Image.SetPixel(x + Left, y + Top, sfColor(Pixels[x], Pixels[x], Pixels[x], Pixels[x]));
00195             }
00196             Pixels += Bitmap.pitch;
00197         }
00198 
00199         for (int x = 0; x < Bitmap.width; ++x)
00200             Tops[Left + x] = Top + Bitmap.rows;
00201 
00202         Left += Bitmap.width;
00203     }
00204 
00205     // Now that the texture has its final size, we can precompute texture coordinates
00206     for (int i = 31; i < 256; ++i)
00207         CurFont.Coord[i] = CurFont.Image.GetTexCoords(Coords[i]);
00208 
00209     // Update image after modifications
00210     CurFont.Image.Update();
00211 
00212     // Insert new font
00213     myFonts[Filename] = CurFont;
00214 
00215     return myFonts[Filename];
00216 }
00217 
00218 
00222 void sfFontManager::CreateDefaultFont()
00223 {
00224     Font DefaultFont;
00225 
00226     // Load bitmap
00227     DefaultFont.Image.Create(256, 512);
00228     for (int j = 0; j < 512; ++j)
00229         for (int i = 0; i < 256; ++i)
00230         {
00231             sfUint8 Lum = DefaultFontBitmap[i + j * 256];
00232             DefaultFont.Image.SetPixel(i, j, sfColor(Lum, Lum, Lum, Lum));
00233         }
00234     DefaultFont.Image.Update();
00235 
00236     // Load positions
00237     for (int i = 0; i < 256; i++)
00238     {
00239         DefaultFont.Rect[i] = sfIntRect(DefaultFontRect[i * 4 + 0],
00240                                         DefaultFontRect[i * 4 + 1],
00241                                         DefaultFontRect[i * 4 + 2],
00242                                         DefaultFontRect[i * 4 + 3]);
00243     }
00244 
00245     // Load texture coordinates
00246     for (int i = 0; i < 256; i++)
00247     {
00248         DefaultFont.Coord[i] = sfFloatRect(DefaultFontCoord[i * 4 + 0],
00249                                            DefaultFontCoord[i * 4 + 1],
00250                                            DefaultFontCoord[i * 4 + 2],
00251                                            DefaultFontCoord[i * 4 + 3]);
00252     }
00253 
00254     // Load advances
00255     for (int i = 0; i < 256; i++)
00256         DefaultFont.Advance[i] = DefaultFontAdvance[i];
00257 
00258     // Load character size
00259     DefaultFont.CharSize = DefaultFontCharSize;
00260 
00261     // Insert font in font table
00262     myFonts.insert(FontTable::value_type("default", DefaultFont));
00263 }
00264 
00265 
00269 std::string sfFontManager::GetErrorDesc(FT_Error Error)
00270 {
00271     switch (Error)
00272     {
00273         // Generic errors
00274         case FT_Err_Cannot_Open_Resource :      return "cannot open resource";
00275         case FT_Err_Unknown_File_Format :       return "unknown file format";
00276         case FT_Err_Invalid_File_Format :       return "broken file";
00277         case FT_Err_Invalid_Version :           return "invalid FreeType version";
00278         case FT_Err_Lower_Module_Version :      return "module version is too low";
00279         case FT_Err_Invalid_Argument :          return "invalid argument";
00280         case FT_Err_Unimplemented_Feature :     return "unimplemented feature";
00281         case FT_Err_Invalid_Table :             return "broken table";
00282         case FT_Err_Invalid_Offset :            return "broken offset within table";
00283 
00284         // Glyph / character errors
00285         case FT_Err_Invalid_Glyph_Index :       return "invalid glyph index";
00286         case FT_Err_Invalid_Character_Code :    return "invalid character code";
00287         case FT_Err_Invalid_Glyph_Format :      return "unsupported glyph image format";
00288         case FT_Err_Cannot_Render_Glyph :       return "cannot render this glyph format";
00289         case FT_Err_Invalid_Outline :           return "invalid outline";
00290         case FT_Err_Invalid_Composite :         return "invalid composite glyph";
00291         case FT_Err_Too_Many_Hints :            return "too many hints";
00292         case FT_Err_Invalid_Pixel_Size :        return "invalid pixel size";
00293 
00294         // Handle errors
00295         case FT_Err_Invalid_Handle :            return "invalid object handle";
00296         case FT_Err_Invalid_Library_Handle :    return "invalid library handle";
00297         case FT_Err_Invalid_Driver_Handle :     return "invalid module handle";
00298         case FT_Err_Invalid_Face_Handle :       return "invalid face handle";
00299         case FT_Err_Invalid_Size_Handle :       return "invalid size handle";
00300         case FT_Err_Invalid_Slot_Handle :       return "invalid glyph slot handle";
00301         case FT_Err_Invalid_CharMap_Handle :    return "invalid charmap handle";
00302         case FT_Err_Invalid_Cache_Handle :      return "invalid cache manager handle";
00303         case FT_Err_Invalid_Stream_Handle :     return "invalid stream handle";
00304 
00305         // Driver errors
00306         case FT_Err_Too_Many_Drivers :          return "too many modules";
00307         case FT_Err_Too_Many_Extensions :       return "too many extensions";
00308 
00309         // Memory errors
00310         case FT_Err_Out_Of_Memory :             return "out of memory";
00311         case FT_Err_Unlisted_Object :           return "unlisted object";
00312 
00313         // Stream errors
00314         case FT_Err_Cannot_Open_Stream :        return "cannot open stream";
00315         case FT_Err_Invalid_Stream_Seek :       return "invalid stream seek";
00316         case FT_Err_Invalid_Stream_Skip :       return "invalid stream skip";
00317         case FT_Err_Invalid_Stream_Read :       return "invalid stream read";
00318         case FT_Err_Invalid_Stream_Operation :  return "invalid stream operation";
00319         case FT_Err_Invalid_Frame_Operation :   return "invalid frame operation";
00320         case FT_Err_Nested_Frame_Access :       return "nested frame access";
00321         case FT_Err_Invalid_Frame_Read :        return "invalid frame read";
00322 
00323         // Raster errors
00324         case FT_Err_Raster_Uninitialized :      return "raster uninitialized";
00325         case FT_Err_Raster_Corrupted :          return "raster corrupted";
00326         case FT_Err_Raster_Overflow :           return "raster overflow";
00327         case FT_Err_Raster_Negative_Height :    return "negative height while rastering";
00328 
00329         // Cache errors
00330         case FT_Err_Too_Many_Caches :           return "too many registered caches";
00331 
00332         // TrueType and SFNT errors
00333         case FT_Err_Invalid_Opcode :            return "invalid opcode";
00334         case FT_Err_Too_Few_Arguments :         return "too few arguments";
00335         case FT_Err_Stack_Overflow :            return "stack overflow";
00336         case FT_Err_Code_Overflow :             return "code overflow";
00337         case FT_Err_Bad_Argument :              return "bad argument";
00338         case FT_Err_Divide_By_Zero :            return "division by zero";
00339         case FT_Err_Invalid_Reference :         return "invalid reference";
00340         case FT_Err_Debug_OpCode :              return "found debug opcode";
00341         case FT_Err_ENDF_In_Exec_Stream :       return "found ENDF opcode in execution stream";
00342         case FT_Err_Nested_DEFS :               return "nested DEFS";
00343         case FT_Err_Invalid_CodeRange :         return "invalid code range";
00344         case FT_Err_Execution_Too_Long :        return "execution context too long";
00345         case FT_Err_Too_Many_Function_Defs :    return "too many function definitions";
00346         case FT_Err_Too_Many_Instruction_Defs : return "too many instruction definitions";
00347         case FT_Err_Table_Missing :             return "SFNT font table missing";
00348         case FT_Err_Horiz_Header_Missing :      return "horizontal header (hhea) table missing";
00349         case FT_Err_Locations_Missing :         return "locations (loca) table missing";
00350         case FT_Err_Name_Table_Missing :        return "name table missing";
00351         case FT_Err_CMap_Table_Missing :        return "character map (cmap) table missing";
00352         case FT_Err_Hmtx_Table_Missing :        return "horizontal metrics (hmtx) table missing";
00353         case FT_Err_Post_Table_Missing :        return "PostScript (post) table missing";
00354         case FT_Err_Invalid_Horiz_Metrics :     return "invalid horizontal metrics";
00355         case FT_Err_Invalid_CharMap_Format :    return "invalid character map (cmap) format";
00356         case FT_Err_Invalid_PPem :              return "invalid ppem value";
00357         case FT_Err_Invalid_Vert_Metrics :      return "invalid vertical metrics";
00358         case FT_Err_Could_Not_Find_Context :    return "could not find context";
00359         case FT_Err_Invalid_Post_Table_Format : return "invalid PostScript (post) table format";
00360         case FT_Err_Invalid_Post_Table :        return "invalid PostScript (post) table";
00361 
00362         // CCF, CID and Type 1 errors
00363         case FT_Err_Syntax_Error :              return "opcode syntax error";
00364         case FT_Err_Stack_Underflow :           return "argument stack underflow";
00365         case FT_Err_Ignore :                    return "ignore";
00366 
00367         // BDF errors
00368         case FT_Err_Missing_Startfont_Field :   return "`STARTFONT' field missing";
00369         case FT_Err_Missing_Font_Field :        return "`FONT' field missing";
00370         case FT_Err_Missing_Size_Field :        return "`SIZE' field missing";
00371         case FT_Err_Missing_Chars_Field :       return "`CHARS' field missing";
00372         case FT_Err_Missing_Startchar_Field :   return "`STARTCHAR' field missing";
00373         case FT_Err_Missing_Encoding_Field :    return "`ENCODING' field missing";
00374         case FT_Err_Missing_Bbx_Field :         return "`BBX' field missing";
00375     }
00376 
00377     return "";
00378 }
00379 
00380 } // namespace sf_private

Generated for SFML by  doxygen 1.5.2