changeset 9616:2093499ec9f4

avoid crash if default font can't be found
author John W. Eaton <jwe@octave.org>
date Fri, 04 Sep 2009 17:47:03 -0400
parents ee3a5e9a381c
children 7c628fb04fd0
files src/ChangeLog src/genprops.awk src/gl-render.cc src/graphics.h.in src/txt-eng-ft.cc
diffstat 5 files changed, 123 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Sep 04 11:34:57 2009 -0400
+++ b/src/ChangeLog	Fri Sep 04 17:47:03 2009 -0400
@@ -1,3 +1,15 @@
+2009-09-04  John W. Eaton  <jwe@octave.org>
+
+	* txt-eng-ft.cc (ft_manager::do_get_font, ft_render::set_font,
+	ft_render::set_mode, ft_render::visit, ft_render::set_color):
+	Issue warnings instead of errors for non-fatal problems.
+	(ft_render::visit): If face is null, then return without warning.
+	* genprops.awk: Also generate const std::string& and const char*
+	versions of the get member functions.
+	* gl-render.cc (opengl_renderer::draw): Omit caseless_str
+	constructor in call to get method.
+	* ft_render::set_font (): Likewise.
+
 2009-09-03  John W. Eaton  <jwe@octave.org>
 
 	* pr-output.cc (set_format (const Complex&, int&, int&)):
--- a/src/genprops.awk	Fri Sep 04 11:34:57 2009 -0400
+++ b/src/genprops.awk	Fri Sep 04 17:47:03 2009 -0400
@@ -246,6 +246,8 @@
   printf ("  void set (const caseless_str& pname, const octave_value& val);\n\n");
   printf ("  octave_value get (bool all = false) const;\n\n");
   printf ("  octave_value get (const caseless_str& pname) const;\n\n");
+  printf ("  octave_value get (const std::string& pname) const\n  {\n  return get (caseless_str (pname)); }\n\n");
+  printf ("  octave_value get (const char *pname) const\n  {\n  return get (caseless_str (pname)); }\n\n");
   printf ("  property get_property (const caseless_str& pname);\n\n");
   printf ("  std::string graphics_object_name (void) const { return go_name; }\n\n");
   printf ("  static property_list::pval_map_type factory_defaults (void);\n\n");
--- a/src/gl-render.cc	Fri Sep 04 11:34:57 2009 -0400
+++ b/src/gl-render.cc	Fri Sep 04 17:47:03 2009 -0400
@@ -1644,15 +1644,15 @@
       graphics_object go = (*it);
 
       // FIXME: check whether object has "units" property and it is set to "data"
-      if (! go.isa ("text") || go.get (caseless_str ("units")).string_value () == "data")
+      if (! go.isa ("text") || go.get ("units").string_value () == "data")
         {
           set_clipping (go.get_properties ().is_clipping ());
           draw (go);
 
           it = obj_list.erase (it);
-        }
+	}
       else
-        it++;
+	it++;
     }
 
   // 3rd pass: draw remaining objects
--- a/src/graphics.h.in	Fri Sep 04 11:34:57 2009 -0400
+++ b/src/graphics.h.in	Fri Sep 04 17:47:03 2009 -0400
@@ -1652,6 +1652,16 @@
 
   virtual octave_value get (const caseless_str& pname) const;
 
+  virtual octave_value get (const std::string& pname) const
+  {
+    return get (caseless_str (pname));
+  }
+
+  virtual octave_value get (const char *pname) const
+  {
+    return get (caseless_str (pname));
+  }
+
   virtual octave_value get (bool all = false) const;
 
   virtual property get_property (const caseless_str& pname);
--- a/src/txt-eng-ft.cc	Fri Sep 04 11:34:57 2009 -0400
+++ b/src/txt-eng-ft.cc	Fri Sep 04 17:47:03 2009 -0400
@@ -125,7 +125,10 @@
 
 	  FcPattern *pat = FcPatternCreate ();
 
-	  FcPatternAddString (pat, FC_FAMILY, reinterpret_cast<const FcChar8*> (name == "*" ? "sans" : name.c_str ()));
+	  FcPatternAddString (pat, FC_FAMILY,
+			      (reinterpret_cast<const FcChar8*>
+			       (name == "*" ? "sans" : name.c_str ())));
+
 	  FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);
 	  FcPatternAddInteger (pat, FC_SLANT, fc_angle);
 	  FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);
@@ -137,6 +140,7 @@
 
 	      FcDefaultSubstitute (pat);
 	      match = FcFontMatch (0, pat, &res);
+	      match = 0;
 	      
 	      if (match && res != FcResultNoMatch)
 		{
@@ -146,7 +150,7 @@
 		  file = reinterpret_cast<char*> (tmp);
 		}
 	      else
-		::error ("could not match any font: %s-%s-%s-%g",
+		::warning ("could not match any font: %s-%s-%s-%g",
 			 name.c_str (), weight.c_str (), angle.c_str (),
 			 size);
 
@@ -167,11 +171,8 @@
 #endif
 	}
 
-      if (FT_New_Face (library, file.c_str (), 0, &retval))
-	{
-	  ::error ("ft_manager: unable to load font: %s", file.c_str ());
-	}
-
+      if (! file.empty () && FT_New_Face (library, file.c_str (), 0, &retval))
+	::warning ("ft_manager: unable to load font: %s", file.c_str ());
       
       return retval;
     }
@@ -207,22 +208,20 @@
     FT_Done_Face (face);
 
   // FIXME: take "fontunits" into account
-  double font_size = props.get (caseless_str ("fontsize")).double_value ();
+  double font_size = props.get ("fontsize").double_value ();
 
-  face = ft_manager::get_font (props.get (caseless_str ("fontname")).string_value (),
-			       props.get (caseless_str ("fontweight")).string_value (),
-			       props.get (caseless_str ("fontangle")).string_value (),
+  face = ft_manager::get_font (props.get ("fontname").string_value (),
+			       props.get ("fontweight").string_value (),
+			       props.get ("fontangle").string_value (),
 			       font_size);
 
   if (face)
     {
       if (FT_Set_Char_Size (face, 0, font_size*64, 0, 0))
-	{
-	  ::error ("ft_render: unable to set font size to %d", font_size);
-	}
+	::warning ("ft_render: unable to set font size to %d", font_size);
     }
   else
-    ::error ("ft_render: unable to load appropriate font");
+    ::warning ("ft_render: unable to load appropriate font");
 }
 
 void
@@ -239,7 +238,7 @@
     case MODE_RENDER:
       if (bbox.numel () != 4)
 	{
-	  ::error ("ft_render: invalid bounding box, cannot render");
+	  ::warning ("ft_render: invalid bounding box, cannot render");
 
 	  xoffset = yoffset = 0;
 	  pixels = uint8NDArray ();
@@ -261,109 +260,103 @@
 void
 ft_render::visit (text_element_string& e)
 {
-  if (! face)
+  if (face)
     {
-      ::error ("ft_render: font not initialized");
-      return;
-    }
+      std::string str = e.string_value ();
+      FT_UInt glyph_index, previous = 0;
 
-  std::string str = e.string_value ();
-  FT_UInt glyph_index, previous = 0;
-
-  for (int i = 0; i < str.length (); i++)
-    {
-      glyph_index = FT_Get_Char_Index (face, str[i]);
-
-      if (! glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+      for (int i = 0; i < str.length (); i++)
 	{
-	  ::error ("ft_render: unable to load glyph from font for character `%c', skipping",
-		   str[i]);
-	}
-      else
-	{
-	  switch (mode)
+	  glyph_index = FT_Get_Char_Index (face, str[i]);
+
+	  if (! glyph_index
+	      || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+	    ::warning ("ft_render: skipping missing glyph for character `%c'",
+		       str[i]);
+	  else
 	    {
-	    case MODE_RENDER:
-	      if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+	      switch (mode)
 		{
-		  ::error ("ft_render: unable to render glyph for character `%c', skipping",
-			   str[i]);
-		}
-	      else
-		{
-		  FT_Bitmap& bitmap = face->glyph->bitmap;
-		  int x0, y0;
+		case MODE_RENDER:
+		  if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+		    ::warning ("ft_render: unable to render glyph for character `%c'",
+			       str[i]);
+		  else
+		    {
+		      FT_Bitmap& bitmap = face->glyph->bitmap;
+		      int x0, y0;
+
+		      if (previous)
+			{
+			  FT_Vector delta;
+
+			  FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
+			  xoffset += (delta.x >> 6);
+			}
 
+		      x0 = xoffset+face->glyph->bitmap_left;
+		      y0 = yoffset+face->glyph->bitmap_top;
+		      for (int r = 0; r < bitmap.rows; r++)
+			for (int c = 0; c < bitmap.width; c++)
+			  {
+			    unsigned char pix = bitmap.buffer[r*bitmap.width+c];
+			    if (x0+c < 0 || x0+c >= pixels.dim2()
+				|| y0-r < 0 || y0-r >= pixels.dim3())
+			      {
+				//::error ("out-of-bound indexing!!");
+			      }
+			    else if (pixels(3, x0+c, y0-r).value () == 0)
+			      {
+				pixels(0, x0+c, y0-r) = red;
+				pixels(1, x0+c, y0-r) = green;
+				pixels(2, x0+c, y0-r) = blue;
+				pixels(3, x0+c, y0-r) = pix;
+			      }
+			  }
+
+		      xoffset += (face->glyph->advance.x >> 6);
+		    }
+		  break;
+
+		case MODE_BBOX:
+		  // width
 		  if (previous)
 		    {
 		      FT_Vector delta;
 
 		      FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-		      xoffset += (delta.x >> 6);
+		      bbox(2) += (delta.x >> 6);
+		    }
+		  bbox(2) += (face->glyph->advance.x >> 6);
+
+		  int asc, desc;
+
+		  if (false /*tight*/)
+		    {
+		      desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
+		      asc = face->glyph->metrics.horiBearingY;
+		    }
+		  else
+		    {
+		      asc = face->size->metrics.ascender;
+		      desc = face->size->metrics.descender;
 		    }
 
-		  x0 = xoffset+face->glyph->bitmap_left;
-		  y0 = yoffset+face->glyph->bitmap_top;
-		  for (int r = 0; r < bitmap.rows; r++)
-		    for (int c = 0; c < bitmap.width; c++)
-		      {
-			unsigned char pix = bitmap.buffer[r*bitmap.width+c];
-			if (x0+c < 0 || x0+c >= pixels.dim2()
-			    || y0-r < 0 || y0-r >= pixels.dim3())
-			  {
-			    //::error ("out-of-bound indexing!!");
-			  }
-			else if (pixels(3, x0+c, y0-r).value () == 0)
-			  {
-			    pixels(0, x0+c, y0-r) = red;
-			    pixels(1, x0+c, y0-r) = green;
-			    pixels(2, x0+c, y0-r) = blue;
-			    pixels(3, x0+c, y0-r) = pix;
-			  }
-		      }
+		  asc = yoffset + (asc >> 6);
+		  desc = yoffset + (desc >> 6);
 
-		  xoffset += (face->glyph->advance.x >> 6);
-		}
-	      break;
-
-	    case MODE_BBOX:
-	      // width
-	      if (previous)
-		{
-		  FT_Vector delta;
-
-		  FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-		  bbox(2) += (delta.x >> 6);
-		}
-	      bbox(2) += (face->glyph->advance.x >> 6);
-
-	      int asc, desc;
-
-	      if (false /*tight*/)
-		{
-		  desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
-		  asc = face->glyph->metrics.horiBearingY;
-		}
-	      else
-		{
-		  asc = face->size->metrics.ascender;
-		  desc = face->size->metrics.descender;
+		  if (desc < bbox(1))
+		    {
+		      bbox(3) += (bbox(1) - desc);
+		      bbox(1) = desc;
+		    }
+		  if (asc > (bbox(3)+bbox(1)))
+		    bbox(3) = asc-bbox(1);
+		  break;
 		}
 
-	      asc = yoffset + (asc >> 6);
-	      desc = yoffset + (desc >> 6);
-
-	      if (desc < bbox(1))
-		{
-		  bbox(3) += (bbox(1) - desc);
-		  bbox(1) = desc;
-		}
-	      if (asc > (bbox(3)+bbox(1)))
-		bbox(3) = asc-bbox(1);
-	      break;
+	      previous = glyph_index;
 	    }
-	  
-	  previous = glyph_index;
 	}
     }
 }
@@ -385,7 +378,7 @@
       blue = static_cast<uint8_t> (c(2)*255);
     }
   else
-    ::error ("ft_render::set_color: invalid color");
+    ::warning ("ft_render::set_color: invalid color");
 }
 
 uint8NDArray