Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

font_ttf.cpp

Go to the documentation of this file.
00001 #include "Core/precomp.h"
00002 #include <API/Core/IOData/inputsource_provider.h>
00003 #include <API/Core/IOData/inputsource.h>
00004 #include <API/Core/System/clanstring.h>
00005 #include <API/Display/SurfaceProviders/canvas.h>
00006 #include <API/Display/Display/surface.h>
00007 #include <API/Display/Font/font.h>
00008 #include <malloc.h>
00009 #include "Display/Font/font_generic.h"
00010 
00011 #include <freetype/freetype.h>
00012 
00013 #include "font_ttf.h"
00014 
00015 CL_Font_TTF::CL_Font_TTF(CL_String name, CL_InputSourceProvider* provider)
00016 : CL_Font_Generic()
00017 {
00018         // Init the class
00019         filename = name;
00020         font_mem = NULL;
00021         font_sizes = NULL;
00022         chars_init = false;
00023         a = 255;
00024         r = b = g = 0;
00025 
00026         // Ensure the proper target to load a TTF file
00027         if(provider != NULL)
00028                 input_provider = provider->clone();
00029         else 
00030         input_provider = CL_InputSourceProvider::create_file_provider(".");
00031 
00032         // Open the font
00033         input_source = input_provider->open_source(filename);
00034 
00035         // Allocate memory for the font
00036         font_mem = (unsigned char*)malloc(input_source->size());
00037         size = input_source->size();
00038         if(font_mem == NULL)
00039                 throw CL_Error("Out of Memory");
00040         memset((void*)font_mem, 0, size);
00041 
00042         // Buffered to the size of the font+1 to prevent overflow
00043         input_source->read(font_mem, size);
00044 
00045         height = 12; // Freetype defaults to font size 10 if it uses scaleable fonts
00046         width = 12;
00047         space_len = 10;
00048         subtract_width = 0; // I dunno about this one
00049 
00050         generate_font();
00051 }
00052 
00053 void CL_Font_TTF::generate_font() 
00054 {
00055         if(chars_init)
00056         {
00057                 for(int i=0;i<256;i++)
00058                         delete chars[i];
00059         }
00060         FT_Library library;
00061         FT_Face face;
00062         int error=0;
00063 
00064         // Initialize 'library' as a freetype library.
00065         error = FT_Init_FreeType( &library );
00066         if (error != 0)
00067                 throw(CL_Error("Cannot initialize the FreeType Library"));
00068 
00069         // Turn 'face' into a handle to the font library stored in memory and use 'library' as the library handle
00070         error = FT_New_Memory_Face(library, font_mem, size, 0, &face);
00071         // This loads 'library' with the font at filename with the font face index 0(always valid).
00072 
00073         if( error == FT_Err_Unknown_File_Format)
00074                 throw CL_Error("I can't understand what the file format is.");
00075         else if (error != 0)
00076                 throw CL_Error("I can't access the font file or the font may be broken");
00077 
00078         num_faces = face->num_faces; // Total number of available faces
00079         num_fixed_sizes = face->num_fixed_sizes; // Fixed sizes for non-scallable fonts
00080         num_glyphs = face->num_glyphs; // Number of characters
00081 
00082         if(num_fixed_sizes>0)
00083         {
00084                 font_sizes = new int[num_fixed_sizes];
00085                 for(int i=0;i<num_fixed_sizes;i++) 
00086                         font_sizes[i] = face->available_sizes[i].height;
00087                 
00088                 height = font_sizes[0];
00089                 width = font_sizes[0];
00090         }
00091 
00092         FT_Set_Char_Size(face,height<<6,width<<6,72,72);
00093 
00094         CL_Canvas *canvas=NULL;
00095 
00096         int index;
00097 
00098         for(int i=0;i<num_glyphs;i++)
00099         {
00100                 index = FT_Get_Char_Index(face,i);
00101 
00102                 error = FT_Load_Glyph(face,index,FT_LOAD_DEFAULT);
00103 
00104                 if(error!=0) continue;
00105 
00106                 error = FT_Render_Glyph(face->glyph,ft_render_mode_normal );
00107 
00108                 if(error!=0) continue;
00109 
00110                 adjust[i].top = face->glyph->bitmap_top;
00111                 adjust[i].left = face->glyph->bitmap_left;
00112 
00113         canvas = new CL_Canvas(face->glyph->bitmap.width , face->glyph->bitmap.rows);
00114                 canvas->lock();
00115 
00116                 unsigned char *buffer =(unsigned char*) canvas->get_data();
00117                 unsigned char *bmp = (unsigned char*)face->glyph->bitmap.buffer;
00118 
00119                 for(int j=0;j<(face->glyph->bitmap.rows*face->glyph->bitmap.width);j++) 
00120                 {
00121                         *buffer = (*bmp) & a;
00122                         *(buffer+1) = (*bmp) & b;
00123                         *(buffer+2) = (*bmp) & g;
00124                         *(buffer+3) = (*bmp) & r;
00125                         bmp++;
00126                         buffer+=4;
00127                 }
00128                 
00129                 canvas->unlock();
00130                 chars[i] = CL_Surface::create(canvas);
00131         }
00132         chars_init = true;
00133         FT_Done_Face(face);
00134         FT_Done_FreeType(library);
00135 }
00136 
00137 CL_Font_TTF::~CL_Font_TTF()
00138 {
00139         free((void*)font_mem);
00140         delete[] chars;
00141         delete[] font_sizes;
00142 }
00143 
00144 int CL_Font_TTF::get_text_width(const char *text)
00145 {
00146         int width=0;
00147         while(*text != 0) 
00148         {
00149                 width += chars[*text]->get_width()-subtract_width;
00150                 text++;
00151         }
00152         return width;
00153 }
00154 
00155 int CL_Font_TTF::get_char_width(const char character)
00156 {
00157         return (chars[character]->get_width());
00158 }
00159 
00160 void CL_Font_TTF::print_left(int x, int y, const char *_text, int n_height)
00161 {
00162         int pos_x = x;
00163         const unsigned char *text = (unsigned char*)_text;
00164         while(*text!=0)
00165         {
00166                 if(*text == '\n')
00167                 {
00168                         x = pos_x; 
00169                         y += (get_height() + n_height);
00170                         text++;
00171                         continue;
00172                 }
00173                 if (chars[*text] != NULL)
00174                 {
00175                         int width = chars[*text]->get_width()-subtract_width;
00176 
00177                         chars[*text]->put_screen(x + adjust[*text].left, y-adjust[*text].top);
00178 
00179                         x += width;
00180                         if(*text == 0x20) // Space
00181                                 x += space_len;
00182                 }
00183                 else
00184                         x += space_len;
00185                 text++;
00186   }
00187 }
00188 
00189 
00190 void CL_Font_TTF::print_left(int x, int y, float scale_x, float scale_y, const char *text)
00191 {
00192         int pos_x = x;
00193 
00194         while (*text != 0)
00195         {
00196                 if (chars[*text] != NULL)
00197                 {
00198                         int width = (int) ((chars[*text]->get_width()-subtract_width)*scale_x);
00199 
00200                         chars[*text]->put_screen(pos_x+(adjust[*text].left*scale_y), y-(adjust[*text].top*scale_y));
00201 
00202                         pos_x += width;
00203                 }
00204                 else
00205                 {
00206                         pos_x += (int) (space_len*scale_x);
00207                 }
00208 
00209                 text++;
00210         }
00211 }
00212 
00213 void CL_Font_TTF::print_center(int x, int y, const char *text)
00214 {
00215         print_left(x - get_text_width(text)/2, y, text); 
00216 }
00217 
00218 void CL_Font_TTF::print_right(int x, int y, const char *text)
00219 {
00220         print_left(x - get_text_width(text), y, text);
00221 }
00222 
00223 void CL_Font_TTF::put_target(int x, int y, const char *text, CL_Target *target, int alignment)
00224 {
00225         int pos_x;
00226                 
00227         switch(alignment)
00228         {
00229                 case CL_Font::ALIGN_CENTER:
00230                         pos_x = x - get_text_width(text)/2;
00231                         break;
00232                 case CL_Font::ALIGN_RIGHT:
00233                         pos_x = x - get_text_width(text);
00234                         break;
00235                 default:
00236                         pos_x = x;
00237         }       
00238         
00239         while (*text != 0)
00240         {
00241                 if (chars[*text] != NULL)
00242                 {
00243                         int width = chars[*text]->get_width()-subtract_width;
00244 
00245                         chars[*text]->put_target(pos_x+adjust[*text].left, y-adjust[*text].top, 0, target);
00246 
00247                         pos_x += width;
00248                 }
00249                 else
00250                 {
00251                         pos_x += space_len;
00252                 }
00253 
00254                 text++;
00255         }
00256 }
00257 
00258 int CL_Font_TTF::change_size(int size)
00259 {
00260         if(num_fixed_sizes>0)
00261         {
00262                 for(int i=0;i<num_fixed_sizes;i++)
00263                 {
00264                         if(font_sizes[i] == size)
00265                         {
00266                                 width = size;
00267                                 height = size;
00268                                 generate_font();
00269                                 return size;
00270                         }
00271                 }
00272                 return -1;
00273         }
00274         else
00275         {
00276                 width = size;
00277                 height = size;
00278 
00279                 try
00280                 {
00281                         generate_font();
00282                 }
00283                 catch(...) {return -1;}
00284     
00285                 return size;
00286         }
00287 }
00288 
00289 unsigned int CL_Font_TTF::change_colour(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
00290 {
00291         this->r = r;
00292         this->g = g;
00293         this->b = b;
00294         this->a = a;
00295 
00296         generate_font();
00297 }

Generated at Wed Apr 4 19:54:00 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001