comparison libinterp/corefcn/txt-eng-ft.cc @ 17330:219552139c18

Allow to compile with older freetype on RHEL5 (bug #39823). * configure.ac: Check for FT_Reference_Face in freetype. * libinterp/corefcn/txt-eng-ft.h (ft_render::ft_font::name, ft_render::ft_font::weight, ft_render::ft_font::angle, ft_render::ft_font::size, ft_render::ft_font::face): Make members private. (ft_render::ft_font::ft_font(ft_font), ft_render::ft_font::operator=): Move implementation to source file. (ft_render::ft_font::ft_font(string,string,string,double,FT_Face)): Add default value for last argument. (ft_render::ft_font::get_name, ft_render::ft_font::get_weight, ft_render::ft_font::get_angle, ft_render::ft_font::get_size, ft_render::ft_font::get_face): New methods. * libinterp/corefcn/txt-eng-ft.cc (ft_render::ft_font::ft_font(ft_font), ft_render::ft_font::operator=): Moved implementation from header file. Use FT_Reference_Face conditionally. (ft_render::ft_font::get_face): New method to lazy-load the font structure, implementation from ft_render::set_font. (ft_render::process_character, ft_render::visit(text_element_subscript), ft_render::visit(text_element_superscript), ft_render::visit(text_element_fontsize), ft_render::visit(text_element_fontname), ft_render::visit(text_element_fontstyle), ft_render::update_line_bbox, ft_render::push_new_line): Use ft_render::ft_font accessors. (ft_render::set_font): Move implementation to ft_render::ft_font::get_face. (ft_manager::do_get_font): Use font sharing conditionally, when FT_Reference_Face is present.
author Michael Goffioul <michael.goffioul@gmail.com>
date Sun, 25 Aug 2013 09:26:37 -0400
parents fe6518a1d87c
children 4a348443de9b
comparison
equal deleted inserted replaced
17329:352b442a72a5 17330:219552139c18
166 FT_Face do_get_font (const std::string& name, const std::string& weight, 166 FT_Face do_get_font (const std::string& name, const std::string& weight,
167 const std::string& angle, double size) 167 const std::string& angle, double size)
168 { 168 {
169 FT_Face retval = 0; 169 FT_Face retval = 0;
170 170
171 #if HAVE_FT_REFERENCE_FACE
171 // Look first into the font cache, then use fontconfig. If the font 172 // Look first into the font cache, then use fontconfig. If the font
172 // is present in the cache, simply add a reference and return it. 173 // is present in the cache, simply add a reference and return it.
173 174
174 ft_key key (name + ":" + weight + ":" + angle, size); 175 ft_key key (name + ":" + weight + ":" + angle, size);
175 ft_cache::const_iterator it = cache.find (key); 176 ft_cache::const_iterator it = cache.find (key);
177 if (it != cache.end ()) 178 if (it != cache.end ())
178 { 179 {
179 FT_Reference_Face (it->second); 180 FT_Reference_Face (it->second);
180 return it->second; 181 return it->second;
181 } 182 }
183 #endif
182 184
183 std::string file; 185 std::string file;
184 186
185 #if defined (HAVE_FONTCONFIG) 187 #if defined (HAVE_FONTCONFIG)
186 if (fontconfig_initialized) 188 if (fontconfig_initialized)
254 256
255 if (! file.empty ()) 257 if (! file.empty ())
256 { 258 {
257 if (FT_New_Face (library, file.c_str (), 0, &retval)) 259 if (FT_New_Face (library, file.c_str (), 0, &retval))
258 ::warning ("ft_manager: unable to load font: %s", file.c_str ()); 260 ::warning ("ft_manager: unable to load font: %s", file.c_str ());
261 #if HAVE_FT_REFERENCE_FACE
259 else 262 else
260 { 263 {
261 // Install a finalizer to notify ft_manager that the font is 264 // Install a finalizer to notify ft_manager that the font is
262 // being destroyed. The class ft_manager only keeps weak 265 // being destroyed. The class ft_manager only keeps weak
263 // references to font objects. 266 // references to font objects.
267 270
268 // Insert loaded font into the cache. 271 // Insert loaded font into the cache.
269 272
270 cache[key] = retval; 273 cache[key] = retval;
271 } 274 }
275 #endif
272 } 276 }
273 277
274 return retval; 278 return retval;
275 } 279 }
276 280
315 void 319 void
316 ft_render::set_font (const std::string& name, const std::string& weight, 320 ft_render::set_font (const std::string& name, const std::string& weight,
317 const std::string& angle, double size) 321 const std::string& angle, double size)
318 { 322 {
319 // FIXME: take "fontunits" into account 323 // FIXME: take "fontunits" into account
320 FT_Face face = ft_manager::get_font (name, weight, angle, size); 324
321 325 font = ft_font (name, weight, angle, size, 0);
322 if (face)
323 {
324 if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
325 ::warning ("ft_render: unable to set font size to %g", size);
326
327 font = ft_font (name, weight, angle, size, face);
328 }
329 else
330 ::warning ("ft_render: unable to load appropriate font");
331 } 326 }
332 327
333 void 328 void
334 ft_render::push_new_line (void) 329 ft_render::push_new_line (void)
335 { 330 {
337 { 332 {
338 case MODE_BBOX: 333 case MODE_BBOX:
339 { 334 {
340 // Create a new bbox entry based on the current font. 335 // Create a new bbox entry based on the current font.
341 336
342 FT_Face face = font.face; 337 FT_Face face = font.get_face ();
343 338
344 if (face) 339 if (face)
345 { 340 {
346 int asc = face->size->metrics.ascender >> 6; 341 int asc = face->size->metrics.ascender >> 6;
347 int desc = face->size->metrics.descender >> 6; 342 int desc = face->size->metrics.descender >> 6;
436 // current yoffset, that is the offset of the current glyph's baseline 431 // current yoffset, that is the offset of the current glyph's baseline
437 // the line's baseline. 432 // the line's baseline.
438 433
439 if (mode == MODE_BBOX) 434 if (mode == MODE_BBOX)
440 { 435 {
441 int asc = font.face->size->metrics.ascender >> 6; 436 int asc = font.get_face ()->size->metrics.ascender >> 6;
442 int desc = font.face->size->metrics.descender >> 6; 437 int desc = font.get_face ()->size->metrics.descender >> 6;
443 438
444 Matrix& bb = line_bbox.front (); 439 Matrix& bb = line_bbox.front ();
445 440
446 if ((yoffset + desc) < bb(1)) 441 if ((yoffset + desc) < bb(1))
447 { 442 {
501 } 496 }
502 497
503 FT_UInt 498 FT_UInt
504 ft_render::process_character (FT_ULong code, FT_UInt previous) 499 ft_render::process_character (FT_ULong code, FT_UInt previous)
505 { 500 {
506 FT_Face face = font.face; 501 FT_Face face = font.get_face ();
507 FT_UInt glyph_index = 0; 502 FT_UInt glyph_index = 0;
508 503
509 if (face) 504 if (face)
510 { 505 {
511 glyph_index = FT_Get_Char_Index (face, code); 506 glyph_index = FT_Get_Char_Index (face, code);
668 { 663 {
669 ft_font saved_font (font); 664 ft_font saved_font (font);
670 int saved_line_yoffset = line_yoffset; 665 int saved_line_yoffset = line_yoffset;
671 int saved_yoffset = yoffset; 666 int saved_yoffset = yoffset;
672 667
673 set_font (font.name, font.weight, font.angle, font.size - 2); 668 set_font (font.get_name (), font.get_weight (), font.get_angle (),
669 font.get_size () - 2);
670
674 if (font.is_valid ()) 671 if (font.is_valid ())
675 { 672 {
676 int h = font.face->size->metrics.height >> 6; 673 int h = font.get_face ()->size->metrics.height >> 6;
677 674
678 // Shifting the baseline by 2/3 the font height seems to produce 675 // Shifting the baseline by 2/3 the font height seems to produce
679 // decent result. 676 // decent result.
680 yoffset -= (h * 2) / 3; 677 yoffset -= (h * 2) / 3;
681 678
697 { 694 {
698 ft_font saved_font (font); 695 ft_font saved_font (font);
699 int saved_line_yoffset = line_yoffset; 696 int saved_line_yoffset = line_yoffset;
700 int saved_yoffset = yoffset; 697 int saved_yoffset = yoffset;
701 698
702 set_font (font.name, font.weight, font.angle, font.size - 2); 699 set_font (font.get_name (), font.get_weight (), font.get_angle (),
703 if (saved_font.is_valid () && font.is_valid ()) 700 font.get_size () - 2);
704 { 701
705 int s_asc = saved_font.face->size->metrics.ascender >> 6; 702 if (saved_font.is_valid ())
703 {
704 int s_asc = saved_font.get_face ()->size->metrics.ascender >> 6;
706 705
707 // Shifting the baseline by 2/3 base font ascender seems to produce 706 // Shifting the baseline by 2/3 base font ascender seems to produce
708 // decent result. 707 // decent result.
709 yoffset += (s_asc * 2) / 3; 708 yoffset += (s_asc * 2) / 3;
710 709
734 double sz = e.get_fontsize (); 733 double sz = e.get_fontsize ();
735 734
736 // FIXME: Matlab documentation says that the font size is expressed 735 // FIXME: Matlab documentation says that the font size is expressed
737 // in the text object FontUnit. 736 // in the text object FontUnit.
738 737
739 set_font (font.name, font.weight, font.angle, sz); 738 set_font (font.get_name (), font.get_weight (), font.get_angle (), sz);
740 739
741 if (mode == MODE_BBOX) 740 if (mode == MODE_BBOX)
742 update_line_bbox (); 741 update_line_bbox ();
743 } 742 }
744 743
745 void 744 void
746 ft_render::visit (text_element_fontname& e) 745 ft_render::visit (text_element_fontname& e)
747 { 746 {
748 set_font (e.get_fontname (), font.weight, font.angle, font.size); 747 set_font (e.get_fontname (), font.get_weight (), font.get_angle (),
748 font.get_size ());
749 749
750 if (mode == MODE_BBOX) 750 if (mode == MODE_BBOX)
751 update_line_bbox (); 751 update_line_bbox ();
752 } 752 }
753 753
755 ft_render::visit (text_element_fontstyle& e) 755 ft_render::visit (text_element_fontstyle& e)
756 { 756 {
757 switch (e.get_fontstyle ()) 757 switch (e.get_fontstyle ())
758 { 758 {
759 case text_element_fontstyle::normal: 759 case text_element_fontstyle::normal:
760 set_font (font.name, "normal", "normal", font.size); 760 set_font (font.get_name (), "normal", "normal", font.get_size ());
761 break; 761 break;
762 case text_element_fontstyle::bold: 762 case text_element_fontstyle::bold:
763 set_font (font.name, "bold", "normal", font.size); 763 set_font (font.get_name (), "bold", "normal", font.get_size ());
764 break; 764 break;
765 case text_element_fontstyle::italic: 765 case text_element_fontstyle::italic:
766 set_font (font.name, "normal", "italic", font.size); 766 set_font (font.get_name (), "normal", "italic", font.get_size ());
767 break; 767 break;
768 case text_element_fontstyle::oblique: 768 case text_element_fontstyle::oblique:
769 set_font (font.name, "normal", "oblique", font.size); 769 set_font (font.get_name (), "normal", "oblique", font.get_size ());
770 break; 770 break;
771 } 771 }
772 772
773 if (mode == MODE_BBOX) 773 if (mode == MODE_BBOX)
774 update_line_bbox (); 774 update_line_bbox ();
992 box(1) = -box(1)-box(3); 992 box(1) = -box(1)-box(3);
993 break; 993 break;
994 } 994 }
995 } 995 }
996 996
997 ft_render::ft_font::ft_font (const ft_font& ft)
998 : name (ft.name), weight (ft.weight), angle (ft.angle), size (ft.size),
999 face (0)
1000 {
1001 #if HAVE_FT_REFERENCE_FACE
1002 FT_Face ft_face = ft.get_face ();
1003
1004 if (ft_face && FT_Reference_Face (ft_face) == 0)
1005 face = ft_face;
1006 #endif
1007 }
1008
1009 ft_render::ft_font&
1010 ft_render::ft_font::operator = (const ft_font& ft)
1011 {
1012 if (&ft != this)
1013 {
1014 name = ft.name;
1015 weight = ft.weight;
1016 angle = ft.angle;
1017 size = ft.size;
1018 if (face)
1019 {
1020 FT_Done_Face (face);
1021 face = 0;
1022 }
1023
1024 #if HAVE_FT_REFERENCE_FACE
1025 FT_Face ft_face = ft.get_face ();
1026
1027 if (ft_face && FT_Reference_Face (ft_face) == 0)
1028 face = ft_face;
1029 #endif
1030 }
1031
1032 return *this;
1033 }
1034
1035 FT_Face
1036 ft_render::ft_font::get_face (void) const
1037 {
1038 if (! face && ! name.empty ())
1039 {
1040 face = ft_manager::get_font (name, weight, angle, size);
1041
1042 if (face)
1043 {
1044 if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
1045 ::warning ("ft_render: unable to set font size to %g", size);
1046 }
1047 else
1048 ::warning ("ft_render: unable to load appropriate font");
1049 }
1050
1051 return face;
1052 }
1053
997 #endif // HAVE_FREETYPE 1054 #endif // HAVE_FREETYPE