00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00024
00026
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
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
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
00068 CreateDefaultFont();
00069 }
00070
00071
00075 sfFontManager::~sfFontManager()
00076 {
00077
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
00089 if (!myLibrary)
00090 return myFonts["default"];
00091
00092
00093 if ((Filename == "") || (Filename == "default"))
00094 return myFonts["default"];
00095
00096
00097 FontTable::iterator It = myFonts.find(Filename);
00098 if ((It != myFonts.end()) && (It->second.CharSize >= CharSize))
00099 return It->second;
00100
00101
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
00112 Font CurFont;
00113 CurFont.CharSize = CharSize;
00114 CurFont.Image.Create(TexWidth, TexHeight, sfColor(0, 0, 0, 0));
00115
00116
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
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
00134 sfIntRect Coords[256];
00135 for (int i = 31; i < 256; ++i)
00136 {
00137
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
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
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
00165 if (Left + Bitmap.width >= TexWidth)
00166 Left = 0;
00167
00168
00169 Top = Tops[Left];
00170 for (int x = 0; x < Bitmap.width; ++x)
00171 Top = std::max(Top, Tops[Left + x]);
00172
00173
00174 if (Top + Bitmap.rows >= TexHeight)
00175 CurFont.Image.Resize(TexWidth, TexHeight * 2, sfColor(0, 0, 0, 0));
00176
00177
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
00186 Coords[i] = sfIntRect(Left, Top, Left + Bitmap.width, Top + Bitmap.rows);
00187
00188
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
00206 for (int i = 31; i < 256; ++i)
00207 CurFont.Coord[i] = CurFont.Image.GetTexCoords(Coords[i]);
00208
00209
00210 CurFont.Image.Update();
00211
00212
00213 myFonts[Filename] = CurFont;
00214
00215 return myFonts[Filename];
00216 }
00217
00218
00222 void sfFontManager::CreateDefaultFont()
00223 {
00224 Font DefaultFont;
00225
00226
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
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
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
00255 for (int i = 0; i < 256; i++)
00256 DefaultFont.Advance[i] = DefaultFontAdvance[i];
00257
00258
00259 DefaultFont.CharSize = DefaultFontCharSize;
00260
00261
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
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
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
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
00306 case FT_Err_Too_Many_Drivers : return "too many modules";
00307 case FT_Err_Too_Many_Extensions : return "too many extensions";
00308
00309
00310 case FT_Err_Out_Of_Memory : return "out of memory";
00311 case FT_Err_Unlisted_Object : return "unlisted object";
00312
00313
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
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
00330 case FT_Err_Too_Many_Caches : return "too many registered caches";
00331
00332
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
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
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 }