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 <SFML/Window/OpenGLCaps.hpp>
00033 #include <iostream>
00034 #include <vector>
00035
00036
00037 namespace sf_private
00038 {
00039
00040 #include <SFML/Graphics/DefaultFont.hpp>
00041
00042
00046 sfFontManager& sfFontManager::GetInstance()
00047 {
00048 static sfFontManager Instance;
00049
00050 return Instance;
00051 }
00052
00053
00057 sfFontManager::sfFontManager() :
00058 myLibrary(NULL)
00059 {
00060
00061 FT_Error Error = FT_Init_FreeType(&myLibrary);
00062 if (Error)
00063 {
00064 std::cerr << "Failed to initialize FreeType library (error code : " << Error << ")" << std::endl;
00065 return;
00066 }
00067
00068
00069 CreateDefaultFont();
00070 }
00071
00072
00076 sfFontManager::~sfFontManager()
00077 {
00078
00079 if (myLibrary)
00080 FT_Done_FreeType(myLibrary);
00081 }
00082
00083
00087 const sfFontManager::Font& sfFontManager::GetBitmapFont(const std::string& Filename, unsigned int CharSize)
00088 {
00089
00090 if (!myLibrary)
00091 return myFonts["default"];
00092
00093
00094 if ((Filename == "") || (Filename == "default"))
00095 return myFonts["default"];
00096
00097
00098 FontTable::iterator It = myFonts.find(Filename);
00099 if ((It != myFonts.end()) && (It->second.CharSize >= CharSize))
00100 return It->second;
00101
00102
00103 int MaxSize = sfOpenGLCaps::GetMaxTextureSize();
00104 if ((int)CharSize >= MaxSize / 8) CharSize = MaxSize / 8;
00105
00106 unsigned int Left = 0;
00107 unsigned int Top = 0;
00108 unsigned int TexWidth = sfImage::GetValidTextureSize(CharSize * 8);
00109 unsigned int TexHeight = sfImage::GetValidTextureSize(CharSize * 8);
00110 std::vector<unsigned int> Tops(TexWidth, 0);
00111
00112
00113 Font CurFont;
00114 CurFont.CharSize = CharSize;
00115 CurFont.Image.Create(TexWidth, TexHeight, sfColor(0, 0, 0, 0));
00116
00117
00118 FT_Face FontFace;
00119 FT_Error Error = FT_New_Face(myLibrary, Filename.c_str(), 0, &FontFace);
00120 if (Error)
00121 {
00122 std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00123 return myFonts["default"];
00124 }
00125
00126
00127 Error = FT_Set_Pixel_Sizes(FontFace, CharSize, CharSize);
00128 if (Error)
00129 {
00130 std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00131 return myFonts["default"];
00132 }
00133
00134
00135 sfIntRect Coords[256];
00136 for (int i = 31; i < 256; ++i)
00137 {
00138
00139 Error = FT_Load_Char(FontFace, i, FT_LOAD_DEFAULT);
00140 if (Error)
00141 {
00142 std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00143 return myFonts["default"];
00144 }
00145
00146
00147 FT_Glyph Glyph;
00148 Error = FT_Get_Glyph(FontFace->glyph, &Glyph);
00149 if (Error)
00150 {
00151 std::cerr << "Error loading font \"" << Filename << "\" (" << GetErrorDesc(Error) << ")" << std::endl;
00152 return myFonts["default"];
00153 }
00154 FT_Glyph_To_Bitmap(&Glyph, ft_render_mode_normal, 0, 1);
00155 FT_BitmapGlyph BitmapGlyph = (FT_BitmapGlyph)Glyph;
00156 FT_Bitmap& Bitmap = BitmapGlyph->bitmap;
00157
00158
00159 if (Bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
00160 {
00161 std::cerr << "Error loading font \"" << Filename << "\" (pixel format not supported)" << std::endl;
00162 return myFonts["default"];
00163 }
00164
00165
00166 if (Left + Bitmap.width >= TexWidth)
00167 Left = 0;
00168
00169
00170 Top = Tops[Left];
00171 for (int x = 0; x < Bitmap.width; ++x)
00172 Top = std::max(Top, Tops[Left + x]);
00173
00174
00175 if (Top + Bitmap.rows >= TexHeight)
00176 {
00177 TexHeight *= 2;
00178 CurFont.Image.Resize(TexWidth, TexHeight, sfColor(0, 0, 0, 0));
00179 }
00180
00181
00182 sfIntRect& Rect = CurFont.Rect[i];
00183 Rect.Left = BitmapGlyph->left;
00184 Rect.Top = -BitmapGlyph->top;
00185 Rect.Right = Rect.Left + Bitmap.width;
00186 Rect.Bottom = Bitmap.rows - BitmapGlyph->top;
00187 CurFont.Advance[i] = FontFace->glyph->advance.x / 64;
00188
00189
00190 Coords[i] = sfIntRect(Left, Top, Left + Bitmap.width, Top + Bitmap.rows);
00191
00192
00193 const sfUint8* Pixels = Bitmap.buffer;
00194 for (int y = 0; y < Bitmap.rows; ++y)
00195 {
00196 for (int x = 0; x < Bitmap.width; ++x)
00197 {
00198 CurFont.Image.SetPixel(x + Left, y + Top, sfColor(Pixels[x], Pixels[x], Pixels[x], Pixels[x]));
00199 }
00200 Pixels += Bitmap.pitch;
00201 }
00202
00203 for (int x = 0; x < Bitmap.width; ++x)
00204 Tops[Left + x] = Top + Bitmap.rows;
00205
00206 Left += Bitmap.width;
00207 }
00208
00209
00210 for (int i = 31; i < 256; ++i)
00211 CurFont.Coord[i] = CurFont.Image.GetTexCoords(Coords[i]);
00212
00213
00214 CurFont.Image.Update();
00215
00216
00217 myFonts[Filename] = CurFont;
00218
00219 return myFonts[Filename];
00220 }
00221
00222
00226 void sfFontManager::CreateDefaultFont()
00227 {
00228 Font DefaultFont;
00229
00230
00231 DefaultFont.Image.Create(256, 512);
00232 for (int j = 0; j < 512; ++j)
00233 for (int i = 0; i < 256; ++i)
00234 {
00235 sfUint8 Lum = DefaultFontBitmap[i + j * 256];
00236 DefaultFont.Image.SetPixel(i, j, sfColor(Lum, Lum, Lum, Lum));
00237 }
00238 DefaultFont.Image.Update();
00239
00240
00241 for (int i = 0; i < 256; i++)
00242 {
00243 DefaultFont.Rect[i] = sfIntRect(DefaultFontRect[i * 4 + 0],
00244 DefaultFontRect[i * 4 + 1],
00245 DefaultFontRect[i * 4 + 2],
00246 DefaultFontRect[i * 4 + 3]);
00247 }
00248
00249
00250 for (int i = 0; i < 256; i++)
00251 {
00252 DefaultFont.Coord[i] = sfFloatRect(DefaultFontCoord[i * 4 + 0],
00253 DefaultFontCoord[i * 4 + 1],
00254 DefaultFontCoord[i * 4 + 2],
00255 DefaultFontCoord[i * 4 + 3]);
00256 }
00257
00258
00259 for (int i = 0; i < 256; i++)
00260 DefaultFont.Advance[i] = DefaultFontAdvance[i];
00261
00262
00263 DefaultFont.CharSize = DefaultFontCharSize;
00264
00265
00266 myFonts.insert(FontTable::value_type("default", DefaultFont));
00267 }
00268
00269
00273 std::string sfFontManager::GetErrorDesc(FT_Error Error)
00274 {
00275 switch (Error)
00276 {
00277
00278 case FT_Err_Cannot_Open_Resource : return "cannot open resource";
00279 case FT_Err_Unknown_File_Format : return "unknown file format";
00280 case FT_Err_Invalid_File_Format : return "broken file";
00281 case FT_Err_Invalid_Version : return "invalid FreeType version";
00282 case FT_Err_Lower_Module_Version : return "module version is too low";
00283 case FT_Err_Invalid_Argument : return "invalid argument";
00284 case FT_Err_Unimplemented_Feature : return "unimplemented feature";
00285 case FT_Err_Invalid_Table : return "broken table";
00286 case FT_Err_Invalid_Offset : return "broken offset within table";
00287
00288
00289 case FT_Err_Invalid_Glyph_Index : return "invalid glyph index";
00290 case FT_Err_Invalid_Character_Code : return "invalid character code";
00291 case FT_Err_Invalid_Glyph_Format : return "unsupported glyph image format";
00292 case FT_Err_Cannot_Render_Glyph : return "cannot render this glyph format";
00293 case FT_Err_Invalid_Outline : return "invalid outline";
00294 case FT_Err_Invalid_Composite : return "invalid composite glyph";
00295 case FT_Err_Too_Many_Hints : return "too many hints";
00296 case FT_Err_Invalid_Pixel_Size : return "invalid pixel size";
00297
00298
00299 case FT_Err_Invalid_Handle : return "invalid object handle";
00300 case FT_Err_Invalid_Library_Handle : return "invalid library handle";
00301 case FT_Err_Invalid_Driver_Handle : return "invalid module handle";
00302 case FT_Err_Invalid_Face_Handle : return "invalid face handle";
00303 case FT_Err_Invalid_Size_Handle : return "invalid size handle";
00304 case FT_Err_Invalid_Slot_Handle : return "invalid glyph slot handle";
00305 case FT_Err_Invalid_CharMap_Handle : return "invalid charmap handle";
00306 case FT_Err_Invalid_Cache_Handle : return "invalid cache manager handle";
00307 case FT_Err_Invalid_Stream_Handle : return "invalid stream handle";
00308
00309
00310 case FT_Err_Too_Many_Drivers : return "too many modules";
00311 case FT_Err_Too_Many_Extensions : return "too many extensions";
00312
00313
00314 case FT_Err_Out_Of_Memory : return "out of memory";
00315 case FT_Err_Unlisted_Object : return "unlisted object";
00316
00317
00318 case FT_Err_Cannot_Open_Stream : return "cannot open stream";
00319 case FT_Err_Invalid_Stream_Seek : return "invalid stream seek";
00320 case FT_Err_Invalid_Stream_Skip : return "invalid stream skip";
00321 case FT_Err_Invalid_Stream_Read : return "invalid stream read";
00322 case FT_Err_Invalid_Stream_Operation : return "invalid stream operation";
00323 case FT_Err_Invalid_Frame_Operation : return "invalid frame operation";
00324 case FT_Err_Nested_Frame_Access : return "nested frame access";
00325 case FT_Err_Invalid_Frame_Read : return "invalid frame read";
00326
00327
00328 case FT_Err_Raster_Uninitialized : return "raster uninitialized";
00329 case FT_Err_Raster_Corrupted : return "raster corrupted";
00330 case FT_Err_Raster_Overflow : return "raster overflow";
00331 case FT_Err_Raster_Negative_Height : return "negative height while rastering";
00332
00333
00334 case FT_Err_Too_Many_Caches : return "too many registered caches";
00335
00336
00337 case FT_Err_Invalid_Opcode : return "invalid opcode";
00338 case FT_Err_Too_Few_Arguments : return "too few arguments";
00339 case FT_Err_Stack_Overflow : return "stack overflow";
00340 case FT_Err_Code_Overflow : return "code overflow";
00341 case FT_Err_Bad_Argument : return "bad argument";
00342 case FT_Err_Divide_By_Zero : return "division by zero";
00343 case FT_Err_Invalid_Reference : return "invalid reference";
00344 case FT_Err_Debug_OpCode : return "found debug opcode";
00345 case FT_Err_ENDF_In_Exec_Stream : return "found ENDF opcode in execution stream";
00346 case FT_Err_Nested_DEFS : return "nested DEFS";
00347 case FT_Err_Invalid_CodeRange : return "invalid code range";
00348 case FT_Err_Execution_Too_Long : return "execution context too long";
00349 case FT_Err_Too_Many_Function_Defs : return "too many function definitions";
00350 case FT_Err_Too_Many_Instruction_Defs : return "too many instruction definitions";
00351 case FT_Err_Table_Missing : return "SFNT font table missing";
00352 case FT_Err_Horiz_Header_Missing : return "horizontal header (hhea) table missing";
00353 case FT_Err_Locations_Missing : return "locations (loca) table missing";
00354 case FT_Err_Name_Table_Missing : return "name table missing";
00355 case FT_Err_CMap_Table_Missing : return "character map (cmap) table missing";
00356 case FT_Err_Hmtx_Table_Missing : return "horizontal metrics (hmtx) table missing";
00357 case FT_Err_Post_Table_Missing : return "PostScript (post) table missing";
00358 case FT_Err_Invalid_Horiz_Metrics : return "invalid horizontal metrics";
00359 case FT_Err_Invalid_CharMap_Format : return "invalid character map (cmap) format";
00360 case FT_Err_Invalid_PPem : return "invalid ppem value";
00361 case FT_Err_Invalid_Vert_Metrics : return "invalid vertical metrics";
00362 case FT_Err_Could_Not_Find_Context : return "could not find context";
00363 case FT_Err_Invalid_Post_Table_Format : return "invalid PostScript (post) table format";
00364 case FT_Err_Invalid_Post_Table : return "invalid PostScript (post) table";
00365
00366
00367 case FT_Err_Syntax_Error : return "opcode syntax error";
00368 case FT_Err_Stack_Underflow : return "argument stack underflow";
00369 case FT_Err_Ignore : return "ignore";
00370
00371
00372 case FT_Err_Missing_Startfont_Field : return "`STARTFONT' field missing";
00373 case FT_Err_Missing_Font_Field : return "`FONT' field missing";
00374 case FT_Err_Missing_Size_Field : return "`SIZE' field missing";
00375 case FT_Err_Missing_Chars_Field : return "`CHARS' field missing";
00376 case FT_Err_Missing_Startchar_Field : return "`STARTCHAR' field missing";
00377 case FT_Err_Missing_Encoding_Field : return "`ENCODING' field missing";
00378 case FT_Err_Missing_Bbx_Field : return "`BBX' field missing";
00379 }
00380
00381 return "";
00382 }
00383
00384 }