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
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
00027 if(provider != NULL)
00028 input_provider = provider->clone();
00029 else
00030 input_provider = CL_InputSourceProvider::create_file_provider(".");
00031
00032
00033 input_source = input_provider->open_source(filename);
00034
00035
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
00043 input_source->read(font_mem, size);
00044
00045 height = 12;
00046 width = 12;
00047 space_len = 10;
00048 subtract_width = 0;
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
00065 error = FT_Init_FreeType( &library );
00066 if (error != 0)
00067 throw(CL_Error("Cannot initialize the FreeType Library"));
00068
00069
00070 error = FT_New_Memory_Face(library, font_mem, size, 0, &face);
00071
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;
00079 num_fixed_sizes = face->num_fixed_sizes;
00080 num_glyphs = face->num_glyphs;
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)
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 }