changeset 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 352b442a72a5
children 636d75a58cd9
files configure.ac libinterp/corefcn/txt-eng-ft.cc libinterp/corefcn/txt-eng-ft.h
diffstat 3 files changed, 106 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Sat Aug 24 23:29:42 2013 +0200
+++ b/configure.ac	Sun Aug 25 09:26:37 2013 -0400
@@ -1069,6 +1069,10 @@
       AC_MSG_RESULT(yes)
       AC_DEFINE(HAVE_FREETYPE, 1, [Define to 1 if you have Freetype library.])
       XTRA_CXXFLAGS="$XTRA_CXXFLAGS $FT2_CFLAGS"
+      save_LIBS="$LIBS"
+      LIBS="$FT2_LIBS $LIBS"
+      AC_CHECK_FUNCS([FT_Reference_Face])
+      LIBS="$save_LIBS"
     else
       AC_MSG_RESULT(no)
       warn_freetype="FreeType library not found.  Native graphics will be disabled."
--- a/libinterp/corefcn/txt-eng-ft.cc	Sat Aug 24 23:29:42 2013 +0200
+++ b/libinterp/corefcn/txt-eng-ft.cc	Sun Aug 25 09:26:37 2013 -0400
@@ -168,6 +168,7 @@
     {
       FT_Face retval = 0;
 
+#if HAVE_FT_REFERENCE_FACE
       // Look first into the font cache, then use fontconfig. If the font
       // is present in the cache, simply add a reference and return it.
 
@@ -179,6 +180,7 @@
           FT_Reference_Face (it->second);
           return it->second;
         }
+#endif
 
       std::string file;
 
@@ -256,6 +258,7 @@
         {
           if (FT_New_Face (library, file.c_str (), 0, &retval))
             ::warning ("ft_manager: unable to load font: %s", file.c_str ());
+#if HAVE_FT_REFERENCE_FACE
           else
             {
               // Install a finalizer to notify ft_manager that the font is
@@ -269,6 +272,7 @@
 
               cache[key] = retval;
             }
+#endif
         }
 
       return retval;
@@ -317,17 +321,8 @@
                      const std::string& angle, double size)
 {
   // FIXME: take "fontunits" into account
-  FT_Face face = ft_manager::get_font (name, weight, angle, size);
 
-  if (face)
-    {
-      if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
-        ::warning ("ft_render: unable to set font size to %g", size);
-
-      font = ft_font (name, weight, angle, size, face);
-    }
-  else
-    ::warning ("ft_render: unable to load appropriate font");
+  font = ft_font (name, weight, angle, size, 0);
 }
 
 void
@@ -339,7 +334,7 @@
         {
           // Create a new bbox entry based on the current font.
 
-          FT_Face face = font.face;
+          FT_Face face = font.get_face ();
 
           if (face)
             {
@@ -438,8 +433,8 @@
 
   if (mode == MODE_BBOX)
     {
-      int asc = font.face->size->metrics.ascender >> 6;
-      int desc = font.face->size->metrics.descender >> 6;
+      int asc = font.get_face ()->size->metrics.ascender >> 6;
+      int desc = font.get_face ()->size->metrics.descender >> 6;
 
       Matrix& bb = line_bbox.front ();
 
@@ -503,7 +498,7 @@
 FT_UInt
 ft_render::process_character (FT_ULong code, FT_UInt previous)
 {
-  FT_Face face = font.face;
+  FT_Face face = font.get_face ();
   FT_UInt glyph_index = 0;
 
   if (face)
@@ -670,10 +665,12 @@
   int saved_line_yoffset = line_yoffset;
   int saved_yoffset = yoffset;
 
-  set_font (font.name, font.weight, font.angle, font.size - 2);
+  set_font (font.get_name (), font.get_weight (), font.get_angle (),
+            font.get_size () - 2);
+
   if (font.is_valid ())
     {
-      int h = font.face->size->metrics.height >> 6;
+      int h = font.get_face ()->size->metrics.height >> 6;
 
       // Shifting the baseline by 2/3 the font height seems to produce
       // decent result.
@@ -699,10 +696,12 @@
   int saved_line_yoffset = line_yoffset;
   int saved_yoffset = yoffset;
 
-  set_font (font.name, font.weight, font.angle, font.size - 2);
-  if (saved_font.is_valid () && font.is_valid ())
+  set_font (font.get_name (), font.get_weight (), font.get_angle (),
+            font.get_size () - 2);
+
+  if (saved_font.is_valid ())
     {
-      int s_asc = saved_font.face->size->metrics.ascender >> 6;
+      int s_asc = saved_font.get_face ()->size->metrics.ascender >> 6;
 
       // Shifting the baseline by 2/3 base font ascender seems to produce
       // decent result.
@@ -736,7 +735,7 @@
   // FIXME: Matlab documentation says that the font size is expressed
   //        in the text object FontUnit.
 
-  set_font (font.name, font.weight, font.angle, sz);
+  set_font (font.get_name (), font.get_weight (), font.get_angle (), sz);
 
   if (mode == MODE_BBOX)
     update_line_bbox ();
@@ -745,7 +744,8 @@
 void
 ft_render::visit (text_element_fontname& e)
 {
-  set_font (e.get_fontname (), font.weight, font.angle, font.size);
+  set_font (e.get_fontname (), font.get_weight (), font.get_angle (),
+            font.get_size ());
 
   if (mode == MODE_BBOX)
     update_line_bbox ();
@@ -757,16 +757,16 @@
   switch (e.get_fontstyle ())
     {
     case text_element_fontstyle::normal:
-      set_font (font.name, "normal", "normal", font.size);
+      set_font (font.get_name (), "normal", "normal", font.get_size ());
       break;
     case text_element_fontstyle::bold:
-      set_font (font.name, "bold", "normal", font.size);
+      set_font (font.get_name (), "bold", "normal", font.get_size ());
       break;
     case text_element_fontstyle::italic:
-      set_font (font.name, "normal", "italic", font.size);
+      set_font (font.get_name (), "normal", "italic", font.get_size ());
       break;
     case text_element_fontstyle::oblique:
-      set_font (font.name, "normal", "oblique", font.size);
+      set_font (font.get_name (), "normal", "oblique", font.get_size ());
       break;
     }
 
@@ -994,4 +994,61 @@
     }
 }
 
+ft_render::ft_font::ft_font (const ft_font& ft)
+     : name (ft.name), weight (ft.weight), angle (ft.angle), size (ft.size),
+       face (0)
+{
+#if HAVE_FT_REFERENCE_FACE
+  FT_Face ft_face = ft.get_face ();
+
+  if (ft_face && FT_Reference_Face (ft_face) == 0)
+    face = ft_face;
+#endif
+}
+
+ft_render::ft_font&
+ft_render::ft_font::operator = (const ft_font& ft)
+{
+  if (&ft != this)
+    {
+      name = ft.name;
+      weight = ft.weight;
+      angle = ft.angle;
+      size = ft.size;
+      if (face)
+        {
+          FT_Done_Face (face);
+          face = 0;
+        }
+
+#if HAVE_FT_REFERENCE_FACE
+      FT_Face ft_face = ft.get_face ();
+
+      if (ft_face && FT_Reference_Face (ft_face) == 0)
+        face = ft_face;
+#endif
+    }
+
+  return *this;
+}
+
+FT_Face
+ft_render::ft_font::get_face (void) const
+{
+  if (! face && ! name.empty ())
+    {
+      face = ft_manager::get_font (name, weight, angle, size);
+
+      if (face)
+        {
+          if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
+            ::warning ("ft_render: unable to set font size to %g", size);
+        }
+      else
+        ::warning ("ft_render: unable to load appropriate font");
+    }
+
+  return face;
+}
+
 #endif // HAVE_FREETYPE
--- a/libinterp/corefcn/txt-eng-ft.h	Sat Aug 24 23:29:42 2013 +0200
+++ b/libinterp/corefcn/txt-eng-ft.h	Sun Aug 25 09:26:37 2013 -0400
@@ -116,26 +116,14 @@
   class ft_font
     {
     public:
-      std::string name;
-      std::string weight;
-      std::string angle;
-      double size;
-      FT_Face face;
-
       ft_font (void)
         : name (), weight (), angle (), size (0), face (0) { }
 
       ft_font (const std::string& nm, const std::string& wt,
-               const std::string& ang, double sz, FT_Face f)
+               const std::string& ang, double sz, FT_Face f = 0)
         : name (nm), weight (wt), angle (ang), size (sz), face (f) { }
 
-      ft_font (const ft_font& ft)
-        : name (ft.name), weight (ft.weight), angle (ft.angle),
-          size (ft.size), face (0)
-        {
-          if (FT_Reference_Face (ft.face) == 0)
-            face = ft.face;
-        }
+      ft_font (const ft_font& ft);
 
       ~ft_font (void)
         {
@@ -143,25 +131,26 @@
             FT_Done_Face (face);
         }
 
-      ft_font& operator = (const ft_font& ft)
-        {
-          if (&ft != this)
-            {
-              name = ft.name;
-              weight = ft.weight;
-              angle = ft.angle;
-              size = ft.size;
-              FT_Done_Face (face);
-              if (FT_Reference_Face (ft.face) == 0)
-                face = ft.face;
-              else
-                face = 0;
-            }
+      ft_font& operator = (const ft_font& ft);
+
+      bool is_valid (void) const { return get_face (); }
+
+      std::string get_name (void) const { return name; }
+
+      std::string get_weight (void) const { return weight; }
+
+      std::string get_angle (void) const { return angle; }
 
-          return *this;
-        }
+      double get_size (void) const { return size; }
+
+      FT_Face get_face (void) const;
 
-      bool is_valid (void) const { return face; }
+    private:
+      std::string name;
+      std::string weight;
+      std::string angle;
+      double size;
+      mutable FT_Face face;
     };
 
   void push_new_line (void);