Mercurial > octave
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 |