Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_05 / synfig-core / src / modules / lyr_freetype / lyr_freetype.cpp
1 /*! ========================================================================
2 ** Synfig
3 ** Template File
4 ** $Id: lyr_freetype.cpp,v 1.5 2005/01/24 05:00:18 darco Exp $
5 **
6 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
7 **
8 **      This package is free software; you can redistribute it and/or
9 **      modify it under the terms of the GNU General Public License as
10 **      published by the Free Software Foundation; either version 2 of
11 **      the License, or (at your option) any later version.
12 **
13 **      This package is distributed in the hope that it will be useful,
14 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 **      General Public License for more details.
17 **
18 ** === N O T E S ===========================================================
19 **
20 ** ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #define SYNFIG_LAYER
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "lyr_freetype.h"
34
35
36 #endif
37
38 using namespace std;
39 using namespace etl;
40 using namespace synfig;
41
42 /* === M A C R O S ========================================================= */
43
44 #define MAX_GLYPHS              2000
45
46 #define PANGO_STYLE_NORMAL (0)
47 #define PANGO_STYLE_OBLIQUE (1)
48 #define PANGO_STYLE_ITALIC (2)
49
50
51 #define WEIGHT_NORMAL (400)
52 #define WEIGHT_BOLD (700)
53
54 /* === G L O B A L S ======================================================= */
55
56 SYNFIG_LAYER_INIT(lyr_freetype);
57 SYNFIG_LAYER_SET_NAME(lyr_freetype,"text");
58 SYNFIG_LAYER_SET_LOCAL_NAME(lyr_freetype,_("Simple Text"));
59 SYNFIG_LAYER_SET_CATEGORY(lyr_freetype,_("Typography"));
60 SYNFIG_LAYER_SET_VERSION(lyr_freetype,"0.2");
61 SYNFIG_LAYER_SET_CVS_ID(lyr_freetype,"$Id: lyr_freetype.cpp,v 1.5 2005/01/24 05:00:18 darco Exp $");
62
63 /* === P R O C E D U R E S ================================================= */
64
65 /*Glyph::~Glyph()
66 {
67         if(glyph)FT_Done_Glyph(glyph);  
68 }
69 */
70 void
71 TextLine::clear_and_free()
72 {
73         std::vector<Glyph>::iterator iter;
74         for(iter=glyph_table.begin();iter!=glyph_table.end();++iter)
75         {
76                 if(iter->glyph)FT_Done_Glyph(iter->glyph);
77                 iter->glyph=0;
78         }
79         glyph_table.clear();
80 }
81
82 /* === M E T H O D S ======================================================= */
83
84 lyr_freetype::lyr_freetype()
85 {
86         face=0;
87         
88         size=Vector(0.25,0.25);
89         text=_("Text Layer");
90         color=Color::black();
91         pos=Vector(0,0);
92         orient=Vector(0.5,0.5);
93         compress=1.0;
94         vcompress=1.0;
95         weight=WEIGHT_NORMAL;
96         style=PANGO_STYLE_NORMAL;
97         family="Sans Serif";
98         use_kerning=true;
99         grid_fit=false;
100         old_version=false;
101         set_blend_method(Color::BLEND_COMPOSITE);
102         needs_sync_=true;
103         
104         new_font(family,style,weight);
105         
106         invert=false;
107 }
108
109 lyr_freetype::~lyr_freetype()
110 {
111         if(face)
112                 FT_Done_Face(face);
113 }
114
115 void
116 lyr_freetype::new_font(const synfig::String &family, int style, int weight)
117 {               
118         if(
119                 !new_font_(family,style,weight) &&
120                 !new_font_(family,style,WEIGHT_NORMAL) &&
121                 !new_font_(family,PANGO_STYLE_NORMAL,weight) &&
122                 !new_font_(family,PANGO_STYLE_NORMAL,WEIGHT_NORMAL) &&
123                 !new_font_("sans serif",style,weight) &&
124                 !new_font_("sans serif",style,WEIGHT_NORMAL) &&
125                 !new_font_("sans serif",PANGO_STYLE_NORMAL,weight)
126         )
127                 new_font_("sans serif",PANGO_STYLE_NORMAL,WEIGHT_NORMAL);
128 }
129
130 bool
131 lyr_freetype::new_font_(const synfig::String &font_fam_, int style, int weight)
132 {
133         synfig::String font_fam(font_fam_);
134
135         if(new_face(font_fam_))
136                 return true;
137         
138         //start evil hack
139         for(unsigned int i=0;i<font_fam.size();i++)font_fam[i]=tolower(font_fam[i]);
140         //end evil hack
141
142         if(font_fam=="arial black")
143 #ifndef __APPLE__
144         if(new_face("ariblk"))
145                         return true;
146                 else
147 #endif
148                 font_fam="sans serif";
149         
150         if(font_fam=="sans serif" || font_fam=="arial")
151         {
152                 String arial("arial");
153                 if(weight>WEIGHT_NORMAL)
154                         arial+='b';
155                 if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
156                         arial+='i';
157                 else
158                         if(weight>WEIGHT_NORMAL) arial+='d';
159
160                 if(new_face(arial))
161                         return true;
162 #ifdef __APPLE__
163                 if(new_face("Helvetica RO"))
164                         return true;
165 #endif
166         }
167
168         if(font_fam=="comic" || font_fam=="comic sans")
169         {
170                 String filename("comic");
171                 if(weight>WEIGHT_NORMAL)
172                         filename+='b';
173                 if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
174                         filename+='i';
175                 else if(weight>WEIGHT_NORMAL) filename+='d';
176
177                 if(new_face(filename))
178                         return true;
179         }
180
181         if(font_fam=="courier" || font_fam=="courier new")
182         {
183                 String filename("cour");
184                 if(weight>WEIGHT_NORMAL)
185                         filename+='b';
186                 if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
187                         filename+='i';
188                 else if(weight>WEIGHT_NORMAL) filename+='d';
189
190                 if(new_face(filename))
191                         return true;
192         }
193
194         if(font_fam=="serif" || font_fam=="times" || font_fam=="times new roman")
195         {
196                 String filename("times");
197                 if(weight>WEIGHT_NORMAL)
198                         filename+='b';
199                 if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
200                         filename+='i';
201                 else if(weight>WEIGHT_NORMAL) filename+='d';
202
203                 if(new_face(filename))
204                         return true;
205         }
206         
207         if(font_fam=="trebuchet")
208         {
209                 String filename("trebuc");
210                 if(weight>WEIGHT_NORMAL)
211                         filename+='b';
212                 if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
213                 {
214                         filename+='i';
215                         if(weight<=WEIGHT_NORMAL) filename+='t';
216                 }
217                 else if(weight>WEIGHT_NORMAL) filename+='d';
218
219                 if(new_face(filename))
220                         return true;
221         }
222                 
223         
224         if(font_fam=="sans serif" || font_fam=="luxi sans")
225         {
226                 {
227                         String luxi("luxis");
228                         if(weight>WEIGHT_NORMAL)
229                                 luxi+='b';
230                         else
231                                 luxi+='r';
232                         if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
233                                 luxi+='i';
234                         
235                         
236                         if(new_face(luxi))
237                                 return true;
238                 }
239                 if(new_face("arial"))
240                         return true;
241                 if(new_face("Arial"))
242                         return true;
243         }
244         if(font_fam=="serif" || font_fam=="times" || font_fam=="times new roman" || font_fam=="luxi serif")
245         {
246                 {
247                         String luxi("luxir");
248                         if(weight>WEIGHT_NORMAL)
249                                 luxi+='b';
250                         else
251                                 luxi+='r';
252                         if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
253                                 luxi+='i';
254                         
255                         if(new_face(luxi))
256                                 return true;
257                 }
258                 if(new_face("Times New Roman"))
259                         return true;
260                 if(new_face("Times"))
261                         return true;
262         }
263         if(font_fam=="luxi")
264         {
265                 {
266                         String luxi("luxim");
267                         if(weight>WEIGHT_NORMAL)
268                                 luxi+='b';
269                         else
270                                 luxi+='r';
271                         if(style==PANGO_STYLE_ITALIC||style==PANGO_STYLE_OBLIQUE)
272                                 luxi+='i';
273                         
274                         if(new_face(luxi))
275                                 return true;
276                 }
277
278                 if(new_face("Times New Roman"))
279                         return true;
280                 if(new_face("Times"))
281                         return true;
282         }
283         
284         return new_face(font_fam_) || new_face(font_fam);
285         
286         return false;
287 }
288
289 #ifdef USE_MAC_FT_FUNCS
290 void fss2path(char *path, FSSpec *fss)
291 {
292   int l;             //fss->name contains name of last item in path
293   for(l=0; l<(fss->name[0]); l++) path[l] = fss->name[l + 1]; 
294   path[l] = 0;
295
296   if(fss->parID != fsRtParID) //path is more than just a volume name
297   { 
298     int i, len;
299     CInfoPBRec pb;
300     
301     pb.dirInfo.ioNamePtr = fss->name;
302     pb.dirInfo.ioVRefNum = fss->vRefNum;
303     pb.dirInfo.ioDrParID = fss->parID;
304     do
305     {
306       pb.dirInfo.ioFDirIndex = -1;  //get parent directory name
307       pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;   
308       if(PBGetCatInfoSync(&pb) != noErr) break;
309
310       len = fss->name[0] + 1;
311       for(i=l; i>=0;  i--) path[i + len] = path[i];
312       for(i=1; i<len; i++) path[i - 1] = fss->name[i]; //add to start of path
313       path[i - 1] = ':';
314       l += len;
315 } while(pb.dirInfo.ioDrDirID != fsRtDirID); //while more directory levels
316   }
317 }
318 #endif
319
320 bool
321 lyr_freetype::new_face(const String &newfont)
322 {
323         int error;
324         FT_Long face_index=0;
325
326         // If we are already loaded, don't bother reloading.
327         if(face && font==newfont)
328                 return true;
329
330         if(face)
331         {
332                 FT_Done_Face(face);
333                 face=0;
334         }
335
336         error=FT_New_Face(ft_library,newfont.c_str(),face_index,&face);
337         if(error)error=FT_New_Face(ft_library,(newfont+".ttf").c_str(),face_index,&face);
338
339         if(get_canvas())
340         {
341                 if(error)error=FT_New_Face(ft_library,(get_canvas()->get_file_path()+ETL_DIRECTORY_SEPERATOR+newfont).c_str(),face_index,&face);
342                 if(error)error=FT_New_Face(ft_library,(get_canvas()->get_file_path()+ETL_DIRECTORY_SEPERATOR+newfont+".ttf").c_str(),face_index,&face);
343         }
344
345 #ifdef USE_MAC_FT_FUNCS
346         if(error)
347         {
348                 FSSpec fs_spec;
349                 error=FT_GetFile_From_Mac_Name(newfont.c_str(),&fs_spec,&face_index);
350                 if(!error)
351                 {
352                         char filename[512];
353                         fss2path(filename,&fs_spec);
354                         //FSSpecToNativePathName(fs_spec,filename,sizeof(filename)-1, 0);
355                         
356                         error=FT_New_Face(ft_library, filename, face_index,&face);
357                         //error=FT_New_Face_From_FSSpec(ft_library, &fs_spec, face_index,&face);
358                         synfig::info(__FILE__":%d: \"%s\" (%s) -- ft_error=%d",__LINE__,newfont.c_str(),filename,error);
359                 }
360                 else
361                 {
362                         synfig::info(__FILE__":%d: \"%s\" -- ft_error=%d",__LINE__,newfont.c_str(),error);
363                         // Unable to generate fs_spec
364                 }
365                   
366         }
367 #endif
368
369 #ifdef WIN32
370         if(error)error=FT_New_Face(ft_library,("C:\\WINDOWS\\FONTS\\"+newfont).c_str(),face_index,&face);
371         if(error)error=FT_New_Face(ft_library,("C:\\WINDOWS\\FONTS\\"+newfont+".ttf").c_str(),face_index,&face);
372 #else
373
374 #ifdef __APPLE__
375         if(error)error=FT_New_Face(ft_library,("~/Library/Fonts/"+newfont).c_str(),face_index,&face);
376         if(error)error=FT_New_Face(ft_library,("~/Library/Fonts/"+newfont+".ttf").c_str(),face_index,&face);
377         if(error)error=FT_New_Face(ft_library,("~/Library/Fonts/"+newfont+".dfont").c_str(),face_index,&face);
378
379         if(error)error=FT_New_Face(ft_library,("/Library/Fonts/"+newfont).c_str(),face_index,&face);
380         if(error)error=FT_New_Face(ft_library,("/Library/Fonts/"+newfont+".ttf").c_str(),face_index,&face);
381         if(error)error=FT_New_Face(ft_library,("/Library/Fonts/"+newfont+".dfont").c_str(),face_index,&face);
382 #endif
383
384         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/type1/"+newfont).c_str(),face_index,&face);
385         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/type1/"+newfont+".ttf").c_str(),face_index,&face);
386
387         if(error)error=FT_New_Face(ft_library,("/usr/share/fonts/truetype/"+newfont).c_str(),face_index,&face);
388         if(error)error=FT_New_Face(ft_library,("/usr/share/fonts/truetype/"+newfont+".ttf").c_str(),face_index,&face);
389
390         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/TTF/"+newfont).c_str(),face_index,&face);
391         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/TTF/"+newfont+".ttf").c_str(),face_index,&face);
392
393         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/truetype/"+newfont).c_str(),face_index,&face);
394         if(error)error=FT_New_Face(ft_library,("/usr/X11R6/lib/X11/fonts/truetype/"+newfont+".ttf").c_str(),face_index,&face);
395
396 #endif
397         if(error)
398         {
399                 //synfig::error(strprintf("lyr_freetype:%s (err=%d)",_("Unable to open face."),error));
400                 return false;
401         }
402
403         font=newfont;
404
405         needs_sync_=true;
406         return true;
407 }
408
409 bool
410 lyr_freetype::set_param(const String & param, const ValueBase &value)
411 {
412         Mutex::Lock lock(mutex);
413 /*
414         if(param=="font" && value.same_as(font))
415         {
416                 new_font(etl::basename(value.get(font)),style,weight);
417                 family=etl::basename(value.get(font));
418                 return true;
419         }
420 */
421         IMPORT_PLUS(family,new_font(family,style,weight));
422         IMPORT_PLUS(weight,new_font(family,style,weight));
423         IMPORT_PLUS(style,new_font(family,style,weight));
424         IMPORT_PLUS(size, if(old_version){size/=2.0;} needs_sync_=true );
425         IMPORT_PLUS(text,needs_sync_=true);
426         IMPORT_PLUS(pos,needs_sync_=true);
427         IMPORT(color);
428         IMPORT(invert);
429         IMPORT_PLUS(orient,needs_sync_=true);
430         IMPORT_PLUS(compress,needs_sync_=true);
431         IMPORT_PLUS(vcompress,needs_sync_=true);
432         IMPORT_PLUS(use_kerning,needs_sync_=true);
433         IMPORT_PLUS(grid_fit,needs_sync_=true);
434         
435         return Layer_Composite::set_param(param,value);
436 }
437
438 ValueBase
439 lyr_freetype::get_param(const String& param)const
440 {
441         EXPORT(font);
442         EXPORT(family);
443         EXPORT(style);
444         EXPORT(weight);
445         EXPORT(size);
446         EXPORT(text);
447         EXPORT(color);
448         EXPORT(pos);
449         EXPORT(orient);
450         EXPORT(compress);
451         EXPORT(vcompress);
452         EXPORT(use_kerning);
453         EXPORT(grid_fit);
454         EXPORT(invert);
455         
456         EXPORT_NAME();
457         EXPORT_VERSION();
458
459         return Layer_Composite::get_param(param);
460 }
461
462 Layer::Vocab
463 lyr_freetype::get_param_vocab(void)const
464 {
465         Layer::Vocab ret(Layer_Composite::get_param_vocab());
466
467         ret.push_back(ParamDesc("text")
468                 .set_local_name(_("Text"))
469                 .set_description(_("Text to Render"))
470                 .set_hint("paragraph")
471         );
472
473         ret.push_back(ParamDesc("color")
474                 .set_local_name(_("Color"))
475                 .set_description(_("Color of the text"))
476         );
477
478         ret.push_back(ParamDesc("family")
479                 .set_local_name(_("Font Family"))
480                 .set_hint("font_family")
481         );
482
483         ret.push_back(ParamDesc("style")
484                 .set_local_name(_("Style"))
485                 .set_hint("enum")
486                 .add_enum_value(PANGO_STYLE_NORMAL, "normal" ,_("Normal"))
487                 .add_enum_value(PANGO_STYLE_OBLIQUE, "oblique" ,_("Oblique"))
488                 .add_enum_value(PANGO_STYLE_ITALIC, "italic" ,_("Italic"))
489         );
490
491         ret.push_back(ParamDesc("weight")
492                 .set_local_name(_("Weight"))
493                 .set_hint("enum")
494                 .add_enum_value(200, "ultralight" ,_("Ultralight"))
495                 .add_enum_value(300, "light" ,_("light"))
496                 .add_enum_value(400, "normal" ,_("Normal"))
497                 .add_enum_value(700, "bold" ,_("Bold"))
498                 .add_enum_value(800, "ultrabold" ,_("Ultrabold"))
499                 .add_enum_value(900, "heavy" ,_("Heavy"))
500         );
501         ret.push_back(ParamDesc("compress")
502                 .set_local_name(_("Hozontal Spacing"))
503                 .set_description(_("Describes how close glyphs are horizontally"))
504         );
505
506         ret.push_back(ParamDesc("vcompress")
507                 .set_local_name(_("Vertical Spacing"))
508                 .set_description(_("Describes how close lines of text are vertically"))
509         );
510
511         ret.push_back(ParamDesc("size")
512                 .set_local_name(_("Size"))
513                 .set_description(_("Size of the text"))
514                 .set_hint("size")
515                 .set_origin("pos")
516                 .set_scalar(1)
517         );
518
519         ret.push_back(ParamDesc("orient")
520                 .set_local_name(_("Orientation"))
521                 .set_description(_("Text Orientation"))
522                 .set_invisible_duck()
523         );
524
525         ret.push_back(ParamDesc("pos")
526                 .set_local_name(_("Position"))
527                 .set_description(_("Text Position"))
528         );
529
530         ret.push_back(ParamDesc("font")
531                 .set_local_name(_("Font"))
532                 .set_description(_("Filename of the font to use"))
533                 .set_hint("filename")
534                 .not_critical()
535                 .hidden()
536         );
537
538         ret.push_back(ParamDesc("use_kerning")
539                 .set_local_name(_("Kerning"))
540                 .set_description(_("Enables/Disables font kerning (If the font supports it)"))
541         );
542
543         ret.push_back(ParamDesc("grid_fit")
544                 .set_local_name(_("Sharpen Edges"))
545                 .set_description(_("Turn this off if you are going to be animating the text"))
546         );
547         ret.push_back(ParamDesc("invert")
548                 .set_local_name(_("Invert"))
549         );
550         return ret;
551 }
552
553 void
554 lyr_freetype::sync()
555 {
556         needs_sync_=false;
557         
558         
559         
560         
561 }
562
563 Color
564 lyr_freetype::get_color(Context context, const synfig::Point &pos)const
565 {
566         if(needs_sync_)
567                 const_cast<lyr_freetype*>(this)->sync();
568         
569         if(!face)
570                 return context.get_color(pos);
571         return context.get_color(pos);
572 }
573
574 bool
575 lyr_freetype::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
576 {
577         static synfig::RecMutex freetype_mutex;
578
579         if(needs_sync_)
580                 const_cast<lyr_freetype*>(this)->sync();
581
582         
583         
584         
585         int error;
586         Vector size(lyr_freetype::size*2);
587         
588         if(!context.accelerated_render(surface,quality,renddesc,cb))
589                 return false;
590         
591         if(is_disabled() || text.empty())
592                 return true;
593         
594         // If there is no font loaded, just bail
595         if(!face)
596         {
597                 if(cb)cb->warning(string("lyr_freetype:")+_("No face loaded, no text will be rendered."));
598                 return true;
599         }
600
601         String text(lyr_freetype::text);
602         if(text=="@_FILENAME_@" && get_canvas() && !get_canvas()->get_file_name().empty())
603         {
604                 text=basename(get_canvas()->get_file_name());
605         }
606         
607         // Width and Height of a pixel
608         Vector::value_type pw=renddesc.get_w()/(renddesc.get_br()[0]-renddesc.get_tl()[0]);
609         Vector::value_type ph=renddesc.get_h()/(renddesc.get_br()[1]-renddesc.get_tl()[1]);
610
611     // Calculate character width and height
612         int w=abs(round_to_int(size[0]*pw));
613         int h=abs(round_to_int(size[1]*ph));
614
615     //int bx=(int)((pos[0]-renddesc.get_tl()[0])*pw*64+0.5);
616     //int by=(int)((pos[1]-renddesc.get_tl()[1])*ph*64+0.5);
617     int bx=0;
618     int by=0;
619         
620     // If the font is the size of a pixel, don't bother rendering any text
621         if(w<=1 || h<=1)
622         {
623                 if(cb)cb->warning(string("lyr_freetype:")+_("Text too small, no text will be rendered."));
624                 return true;
625         }
626
627         synfig::RecMutex::Lock lock(freetype_mutex);
628
629 #define CHAR_RESOLUTION         (64)
630         error = FT_Set_Char_Size(
631                 face,                                           // handle to face object           
632                 (int)CHAR_RESOLUTION,   // char_width in 1/64th of points 
633                 (int)CHAR_RESOLUTION,   // char_height in 1/64th of points 
634                 round_to_int(abs(size[0]*pw*CHAR_RESOLUTION)),                                          // horizontal device resolution    
635                 round_to_int(abs(size[1]*ph*CHAR_RESOLUTION)) );                                                // vertical device resolution      
636
637         // Here is where we can compensate for the
638         // error in freetype's rendering engine.
639         const float xerror(abs(size[0]*pw)/(float)face->size->metrics.x_ppem/1.13f/0.996);
640         const float yerror(abs(size[1]*ph)/(float)face->size->metrics.y_ppem/1.13f/0.996);
641         //synfig::info("xerror=%f, yerror=%f",xerror,yerror);
642         const float compress(lyr_freetype::compress*xerror);
643         const float vcompress(lyr_freetype::vcompress*yerror);
644
645         if(error)
646         {
647                 if(cb)cb->error(string("lyr_freetype:")+_("Unable to set face size.")+strprintf(" (err=%d)",error));
648                 return false;
649         }
650
651         FT_GlyphSlot  slot = face->glyph;  // a small shortcut
652         FT_UInt       glyph_index(0);
653         FT_UInt       previous(0);
654         int u,v;
655
656         std::list<TextLine> lines;
657
658         /*
659  --     ** -- CREATE GLYPHS -------------------------------------------------------
660         */
661
662         lines.push_front(TextLine());
663         string::const_iterator iter;
664         for (iter=text.begin(); iter!=text.end(); ++iter)
665         {
666                 int multiplier(1);
667                 if(*iter=='\n')
668                 {
669                         lines.push_front(TextLine());
670                         bx=0;
671                         by=0;
672                         previous=0;
673                         continue;
674                 }
675                 if(*iter=='\t')
676                 {
677                         multiplier=8;
678                         glyph_index = FT_Get_Char_Index( face, ' ' );
679                 }
680                 else
681                         glyph_index = FT_Get_Char_Index( face, *iter );
682
683         // retrieve kerning distance and move pen position
684                 if ( FT_HAS_KERNING(face) && use_kerning && previous && glyph_index )
685                 {
686                         FT_Vector  delta;
687
688                         if(grid_fit)
689                                 FT_Get_Kerning( face, previous, glyph_index, ft_kerning_default, &delta );
690                         else    
691                                 FT_Get_Kerning( face, previous, glyph_index, ft_kerning_unfitted, &delta );
692
693                         if(compress<1.0f)
694                         {
695                                 bx += round_to_int(delta.x*compress);
696                                 by += round_to_int(delta.y*compress);
697                         }
698                         else
699                         {
700                                 bx += delta.x;
701                                 by += delta.y;
702                         }
703         }
704                 
705                 Glyph curr_glyph;
706                 
707         // store current pen position
708         curr_glyph.pos.x = bx;
709         curr_glyph.pos.y = by;
710
711         // load glyph image into the slot. DO NOT RENDER IT !!
712         if(grid_fit)
713                         error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT);
714                 else
715                         error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING );
716         if (error) continue;  // ignore errors, jump to next glyph
717
718         // extract glyph image and store it in our table
719         error = FT_Get_Glyph( face->glyph, &curr_glyph.glyph );
720         if (error) continue;  // ignore errors, jump to next glyph
721
722         // record current glyph index
723         previous = glyph_index;
724                 
725                 // Update the line width
726                 lines.front().width=bx+slot->advance.x;
727                 
728                 // increment pen position
729                 if(multiplier>1)
730                         bx += round_to_int(slot->advance.x*multiplier*compress)-bx%round_to_int(slot->advance.x*multiplier*compress);
731                 else
732                         bx += round_to_int(slot->advance.x*compress*multiplier);
733
734                 //bx += round_to_int(slot->advance.x*compress*multiplier);
735                 //by += round_to_int(slot->advance.y*compress);
736                 by += slot->advance.y*multiplier;
737
738                 lines.front().glyph_table.push_back(curr_glyph);
739                 
740         }
741       
742
743         //float string_height;
744         //string_height=(((lines.size()-1)*face->size->metrics.height+lines.back().actual_height()));
745
746         //int string_height=face->size->metrics.ascender;
747 //#define METRICS_SCALE_ONE             (65536.0f)
748 #define METRICS_SCALE_ONE               ((float)(1<<16))
749         
750         float line_height;
751         line_height=vcompress*((float)face->height*(((float)face->size->metrics.y_scale/METRICS_SCALE_ONE)));
752
753         int     string_height;
754         string_height=round_to_int(((lines.size()-1)*line_height+lines.back().actual_height()));
755         //synfig::info("string_height=%d",string_height);
756         //synfig::info("line_height=%f",line_height);
757         
758         /*
759  --     ** -- RENDER THE GLYPHS ---------------------------------------------------
760         */
761
762         Surface src_;
763         Surface *src_surface;
764         
765         src_surface=surface;
766
767         if(invert)
768         {
769                 src_=*surface;
770                 Surface::alpha_pen pen(surface->begin(),get_amount(),get_blend_method());
771                 
772                 surface->fill(color,pen,src_.get_w(),src_.get_h());
773                 
774                 src_surface=&src_;
775         }
776         
777         {
778         std::list<TextLine>::iterator iter;
779         int curr_line;
780         for(curr_line=0,iter=lines.begin();iter!=lines.end();++iter,curr_line++)
781         {
782                 bx=round_to_int((pos[0]-renddesc.get_tl()[0])*pw*CHAR_RESOLUTION-orient[0]*iter->width);
783                 by=round_to_int((pos[1]-renddesc.get_tl()[1])*ph*CHAR_RESOLUTION+(1.0-orient[1])*string_height-line_height*curr_line);
784                 //by=round_to_int(vcompress*((pos[1]-renddesc.get_tl()[1])*ph*64+(1.0-orient[1])*string_height-face->size->metrics.height*curr_line));
785                 //synfig::info("curr_line=%d, bx=%d, by=%d",curr_line,bx,by);
786                 
787                 std::vector<Glyph>::iterator iter2;
788                 for(iter2=iter->glyph_table.begin();iter2!=iter->glyph_table.end();++iter2)
789                 {
790                         FT_Glyph  image(iter2->glyph);
791                         FT_Vector pen;
792                         FT_BitmapGlyph  bit;
793                                 
794                         pen.x = bx + iter2->pos.x;
795                         pen.y = by + iter2->pos.y;
796                         
797                         //synfig::info("GLYPH: pen.x=%d, pen,y=%d",curr_line,(pen.x+32)>>6,(pen.y+32)>>6);
798                 
799                         error = FT_Glyph_To_Bitmap( &image, ft_render_mode_normal,0/*&pen*/, 1 );
800                         if(error) { FT_Done_Glyph( image ); continue; }
801                 
802                         bit = (FT_BitmapGlyph)image;
803
804                         for(v=0;v<bit->bitmap.rows;v++)
805                                 for(u=0;u<bit->bitmap.width;u++)
806                                 {
807                                         int x=u+((pen.x+32)>>6)+ bit->left;
808                                         int y=v+((pen.y+32)>>6)- bit->top;
809                                         if(     y>=0 &&
810                                                 x>=0 &&
811                                                 y<surface->get_h() &&
812                                                 x<surface->get_w())
813                                         {
814                                                 float myamount=(float)bit->bitmap.buffer[v*bit->bitmap.pitch+u]/255.0f;
815                                                 if(invert)
816                                                         myamount=1.0f-myamount;
817                                                 (*surface)[y][x]=Color::blend(color,(*src_surface)[y][x],myamount*get_amount(),get_blend_method());
818                                         }
819                                 }
820                 
821                         FT_Done_Glyph( image );
822                 }
823                 //iter->clear_and_free();
824         }
825         }
826    
827
828         return true;
829 }
830
831 synfig::Rect
832 lyr_freetype::get_bounding_rect()const
833 {
834         if(needs_sync_)
835                 const_cast<lyr_freetype*>(this)->sync();
836 //      if(!is_disabled())
837                 return synfig::Rect::full_plane();
838 }